Blame view
fs/gfs2/rgrp.c
42.3 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
fe6c991c5 [GFS2] Get rid of... |
3 |
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 |
*/ |
b3b94faa5 [GFS2] The core o... |
9 10 11 12 |
#include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
f42faf4fa [GFS2] Add gfs2_i... |
13 |
#include <linux/fs.h> |
5c676f6d3 [GFS2] Macros rem... |
14 |
#include <linux/gfs2_ondisk.h> |
1f466a47e [GFS2] Faster gfs... |
15 |
#include <linux/prefetch.h> |
f15ab5619 GFS2: Support gen... |
16 |
#include <linux/blkdev.h> |
7c9ca6211 GFS2: Use rbtree ... |
17 |
#include <linux/rbtree.h> |
b3b94faa5 [GFS2] The core o... |
18 19 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
20 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
21 22 |
#include "glock.h" #include "glops.h" |
b3b94faa5 [GFS2] The core o... |
23 24 25 26 27 28 |
#include "lops.h" #include "meta_io.h" #include "quota.h" #include "rgrp.h" #include "super.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
29 |
#include "util.h" |
172e045a7 [GFS2] flush the ... |
30 |
#include "log.h" |
c8cdf4793 [GFS2] Recovery f... |
31 |
#include "inode.h" |
63997775b GFS2: Add tracepo... |
32 |
#include "trace_gfs2.h" |
b3b94faa5 [GFS2] The core o... |
33 |
|
2c1e52aa9 [GFS2] More style... |
34 |
#define BFITNOENT ((u32)~0) |
6760bdcd0 [GFS2] Prevent in... |
35 |
#define NO_BLOCK ((u64)~0) |
88c8ab1fc [GFS2] Merge bits... |
36 |
|
1f466a47e [GFS2] Faster gfs... |
37 38 39 40 41 42 43 44 45 |
#if BITS_PER_LONG == 32 #define LBITMASK (0x55555555UL) #define LBITSKIP55 (0x55555555UL) #define LBITSKIP00 (0x00000000UL) #else #define LBITMASK (0x5555555555555555UL) #define LBITSKIP55 (0x5555555555555555UL) #define LBITSKIP00 (0x0000000000000000UL) #endif |
88c8ab1fc [GFS2] Merge bits... |
46 47 48 |
/* * These routines are used by the resource group routines (rgrp.c) * to keep track of block allocation. Each block is represented by two |
feaa7bba0 [GFS2] Fix unlink... |
49 50 51 52 53 54 |
* bits. So, each byte represents GFS2_NBBY (i.e. 4) blocks. * * 0 = Free * 1 = Used (not metadata) * 2 = Unlinked (still in use) inode * 3 = Used (metadata) |
88c8ab1fc [GFS2] Merge bits... |
55 56 57 58 |
*/ static const char valid_change[16] = { /* current */ |
feaa7bba0 [GFS2] Fix unlink... |
59 |
/* n */ 0, 1, 1, 1, |
88c8ab1fc [GFS2] Merge bits... |
60 |
/* e */ 1, 0, 0, 0, |
feaa7bba0 [GFS2] Fix unlink... |
61 |
/* w */ 0, 0, 0, 1, |
88c8ab1fc [GFS2] Merge bits... |
62 63 |
1, 0, 0, 0 }; |
c8cdf4793 [GFS2] Recovery f... |
64 |
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
6a8099ed5 GFS2: Fix multi-b... |
65 |
unsigned char old_state, |
b3e47ca0c GFS2: split funct... |
66 |
struct gfs2_bitmap **rbi); |
c8cdf4793 [GFS2] Recovery f... |
67 |
|
88c8ab1fc [GFS2] Merge bits... |
68 69 70 71 72 73 74 75 |
/** * gfs2_setbit - Set a bit in the bitmaps * @buffer: the buffer that holds the bitmaps * @buflen: the length (in bytes) of the buffer * @block: the block to set * @new_state: the new state of the block * */ |
b45e41d7d [GFS2] Add extent... |
76 77 |
static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1, unsigned char *buf2, unsigned int offset, |
95c8e17f2 GFS2: Dump better... |
78 |
struct gfs2_bitmap *bi, u32 block, |
b45e41d7d [GFS2] Add extent... |
79 |
unsigned char new_state) |
88c8ab1fc [GFS2] Merge bits... |
80 |
{ |
b45e41d7d [GFS2] Add extent... |
81 |
unsigned char *byte1, *byte2, *end, cur_state; |
95c8e17f2 GFS2: Dump better... |
82 |
unsigned int buflen = bi->bi_len; |
b45e41d7d [GFS2] Add extent... |
83 |
const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; |
88c8ab1fc [GFS2] Merge bits... |
84 |
|
b45e41d7d [GFS2] Add extent... |
85 86 |
byte1 = buf1 + offset + (block / GFS2_NBBY); end = buf1 + offset + buflen; |
88c8ab1fc [GFS2] Merge bits... |
87 |
|
b45e41d7d [GFS2] Add extent... |
88 |
BUG_ON(byte1 >= end); |
88c8ab1fc [GFS2] Merge bits... |
89 |
|
b45e41d7d [GFS2] Add extent... |
90 |
cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; |
88c8ab1fc [GFS2] Merge bits... |
91 |
|
b45e41d7d [GFS2] Add extent... |
92 |
if (unlikely(!valid_change[new_state * 4 + cur_state])) { |
95c8e17f2 GFS2: Dump better... |
93 94 95 96 97 98 99 100 101 102 103 104 105 |
printk(KERN_WARNING "GFS2: buf_blk = 0x%llx old_state=%d, " "new_state=%d ", (unsigned long long)block, cur_state, new_state); printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%lx ", (unsigned long long)rgd->rd_addr, (unsigned long)bi->bi_start); printk(KERN_WARNING "GFS2: bi_offset=0x%lx bi_len=0x%lx ", (unsigned long)bi->bi_offset, (unsigned long)bi->bi_len); dump_stack(); |
88c8ab1fc [GFS2] Merge bits... |
106 |
gfs2_consist_rgrpd(rgd); |
b45e41d7d [GFS2] Add extent... |
107 108 109 110 111 112 113 114 115 |
return; } *byte1 ^= (cur_state ^ new_state) << bit; if (buf2) { byte2 = buf2 + offset + (block / GFS2_NBBY); cur_state = (*byte2 >> bit) & GFS2_BIT_MASK; *byte2 ^= (cur_state ^ new_state) << bit; } |
88c8ab1fc [GFS2] Merge bits... |
116 117 118 119 120 121 122 123 124 |
} /** * gfs2_testbit - test a bit in the bitmaps * @buffer: the buffer that holds the bitmaps * @buflen: the length (in bytes) of the buffer * @block: the block to read * */ |
b45e41d7d [GFS2] Add extent... |
125 126 127 |
static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, const unsigned char *buffer, unsigned int buflen, u32 block) |
88c8ab1fc [GFS2] Merge bits... |
128 |
{ |
b45e41d7d [GFS2] Add extent... |
129 130 |
const unsigned char *byte, *end; unsigned char cur_state; |
88c8ab1fc [GFS2] Merge bits... |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
unsigned int bit; byte = buffer + (block / GFS2_NBBY); bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; end = buffer + buflen; gfs2_assert(rgd->rd_sbd, byte < end); cur_state = (*byte >> bit) & GFS2_BIT_MASK; return cur_state; } /** |
223b2b889 GFS2: Fix alignme... |
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
* gfs2_bit_search * @ptr: Pointer to bitmap data * @mask: Mask to use (normally 0x55555.... but adjusted for search start) * @state: The state we are searching for * * We xor the bitmap data with a patter which is the bitwise opposite * of what we are looking for, this gives rise to a pattern of ones * wherever there is a match. Since we have two bits per entry, we * take this pattern, shift it down by one place and then and it with * the original. All the even bit positions (0,2,4, etc) then represent * successful matches, so we mask with 0x55555..... to remove the unwanted * odd bit positions. * * This allows searching of a whole u64 at once (32 blocks) with a * single test (on 64 bit arches). */ static inline u64 gfs2_bit_search(const __le64 *ptr, u64 mask, u8 state) { u64 tmp; static const u64 search[] = { |
075ac4487 GFS2: fix sparse ... |
166 167 168 169 |
[0] = 0xffffffffffffffffULL, [1] = 0xaaaaaaaaaaaaaaaaULL, [2] = 0x5555555555555555ULL, [3] = 0x0000000000000000ULL, |
223b2b889 GFS2: Fix alignme... |
170 171 172 173 174 175 176 177 |
}; tmp = le64_to_cpu(*ptr) ^ search[state]; tmp &= (tmp >> 1); tmp &= mask; return tmp; } /** |
88c8ab1fc [GFS2] Merge bits... |
178 179 180 |
* gfs2_bitfit - Search an rgrp's bitmap buffer to find a bit-pair representing * a block in a given allocation state. * @buffer: the buffer that holds the bitmaps |
223b2b889 GFS2: Fix alignme... |
181 |
* @len: the length (in bytes) of the buffer |
88c8ab1fc [GFS2] Merge bits... |
182 |
* @goal: start search at this block's bit-pair (within @buffer) |
223b2b889 GFS2: Fix alignme... |
183 |
* @state: GFS2_BLKST_XXX the state of the block we're looking for. |
88c8ab1fc [GFS2] Merge bits... |
184 185 186 |
* * Scope of @goal and returned block number is only within this bitmap buffer, * not entire rgrp or filesystem. @buffer will be offset from the actual |
223b2b889 GFS2: Fix alignme... |
187 188 189 190 191 |
* beginning of a bitmap block buffer, skipping any header structures, but * headers are always a multiple of 64 bits long so that the buffer is * always aligned to a 64 bit boundary. * * The size of the buffer is in bytes, but is it assumed that it is |
fd589a8f0 trivial: fix typo... |
192 |
* always ok to read a complete multiple of 64 bits at the end |
223b2b889 GFS2: Fix alignme... |
193 |
* of the block in case the end is no aligned to a natural boundary. |
88c8ab1fc [GFS2] Merge bits... |
194 195 196 |
* * Return: the block number (bitmap buffer scope) that was found */ |
02ab17215 GFS2: fix sparse ... |
197 198 |
static u32 gfs2_bitfit(const u8 *buf, const unsigned int len, u32 goal, u8 state) |
88c8ab1fc [GFS2] Merge bits... |
199 |
{ |
223b2b889 GFS2: Fix alignme... |
200 201 202 203 |
u32 spoint = (goal << 1) & ((8*sizeof(u64)) - 1); const __le64 *ptr = ((__le64 *)buf) + (goal >> 5); const __le64 *end = (__le64 *)(buf + ALIGN(len, sizeof(u64))); u64 tmp; |
075ac4487 GFS2: fix sparse ... |
204 |
u64 mask = 0x5555555555555555ULL; |
223b2b889 GFS2: Fix alignme... |
205 206 207 208 209 210 211 212 213 |
u32 bit; BUG_ON(state > 3); /* Mask off bits we don't care about at the start of the search */ mask <<= spoint; tmp = gfs2_bit_search(ptr, mask, state); ptr++; while(tmp == 0 && ptr < end) { |
075ac4487 GFS2: fix sparse ... |
214 |
tmp = gfs2_bit_search(ptr, 0x5555555555555555ULL, state); |
223b2b889 GFS2: Fix alignme... |
215 |
ptr++; |
1f466a47e [GFS2] Faster gfs... |
216 |
} |
223b2b889 GFS2: Fix alignme... |
217 218 219 220 221 222 223 |
/* Mask off any bits which are more than len bytes from the start */ if (ptr == end && (len & (sizeof(u64) - 1))) tmp &= (((u64)~0) >> (64 - 8*(len & (sizeof(u64) - 1)))); /* Didn't find anything, so return */ if (tmp == 0) return BFITNOENT; ptr--; |
d8bd504ab GFS2: Fix bug in ... |
224 |
bit = __ffs64(tmp); |
223b2b889 GFS2: Fix alignme... |
225 226 |
bit /= 2; /* two bits per entry in the bitmap */ return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit; |
88c8ab1fc [GFS2] Merge bits... |
227 228 229 230 231 232 233 234 235 236 |
} /** * gfs2_bitcount - count the number of bits in a certain state * @buffer: the buffer that holds the bitmaps * @buflen: the length (in bytes) of the buffer * @state: the state of the block we're looking for * * Returns: The number of bits */ |
110acf383 [GFS2] Add consts... |
237 238 |
static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer, unsigned int buflen, u8 state) |
88c8ab1fc [GFS2] Merge bits... |
239 |
{ |
110acf383 [GFS2] Add consts... |
240 241 242 243 244 |
const u8 *byte = buffer; const u8 *end = buffer + buflen; const u8 state1 = state << 2; const u8 state2 = state << 4; const u8 state3 = state << 6; |
cd915493f [GFS2] Change all... |
245 |
u32 count = 0; |
88c8ab1fc [GFS2] Merge bits... |
246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
for (; byte < end; byte++) { if (((*byte) & 0x03) == state) count++; if (((*byte) & 0x0C) == state1) count++; if (((*byte) & 0x30) == state2) count++; if (((*byte) & 0xC0) == state3) count++; } return count; } |
b3b94faa5 [GFS2] The core o... |
260 261 262 263 264 265 266 267 268 269 270 |
/** * gfs2_rgrp_verify - Verify that a resource group is consistent * @sdp: the filesystem * @rgd: the rgrp * */ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_bitmap *bi = NULL; |
bb8d8a6f5 [GFS2] Fix sign p... |
271 |
u32 length = rgd->rd_length; |
cd915493f [GFS2] Change all... |
272 |
u32 count[4], tmp; |
b3b94faa5 [GFS2] The core o... |
273 |
int buf, x; |
cd915493f [GFS2] Change all... |
274 |
memset(count, 0, 4 * sizeof(u32)); |
b3b94faa5 [GFS2] The core o... |
275 276 277 278 279 280 281 282 283 284 |
/* Count # blocks in each of 4 possible allocation states */ for (buf = 0; buf < length; buf++) { bi = rgd->rd_bits + buf; for (x = 0; x < 4; x++) count[x] += gfs2_bitcount(rgd, bi->bi_bh->b_data + bi->bi_offset, bi->bi_len, x); } |
cfc8b5492 GFS2: Move rg_fre... |
285 |
if (count[0] != rgd->rd_free) { |
b3b94faa5 [GFS2] The core o... |
286 287 288 |
if (gfs2_consist_rgrpd(rgd)) fs_err(sdp, "free data mismatch: %u != %u ", |
cfc8b5492 GFS2: Move rg_fre... |
289 |
count[0], rgd->rd_free); |
b3b94faa5 [GFS2] The core o... |
290 291 |
return; } |
73f749483 GFS2: Banish stru... |
292 |
tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes; |
6b9461702 GFS2: Fix incorre... |
293 |
if (count[1] != tmp) { |
b3b94faa5 [GFS2] The core o... |
294 295 296 297 298 299 |
if (gfs2_consist_rgrpd(rgd)) fs_err(sdp, "used data mismatch: %u != %u ", count[1], tmp); return; } |
6b9461702 GFS2: Fix incorre... |
300 |
if (count[2] + count[3] != rgd->rd_dinodes) { |
b3b94faa5 [GFS2] The core o... |
301 |
if (gfs2_consist_rgrpd(rgd)) |
feaa7bba0 [GFS2] Fix unlink... |
302 303 |
fs_err(sdp, "used metadata mismatch: %u != %u ", |
6b9461702 GFS2: Fix incorre... |
304 |
count[2] + count[3], rgd->rd_dinodes); |
b3b94faa5 [GFS2] The core o... |
305 306 |
return; } |
b3b94faa5 [GFS2] The core o... |
307 |
} |
bb8d8a6f5 [GFS2] Fix sign p... |
308 |
static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) |
b3b94faa5 [GFS2] The core o... |
309 |
{ |
bb8d8a6f5 [GFS2] Fix sign p... |
310 311 |
u64 first = rgd->rd_data0; u64 last = first + rgd->rd_data; |
16910427e [GFS2] Style chan... |
312 |
return first <= block && block < last; |
b3b94faa5 [GFS2] The core o... |
313 314 315 316 317 318 319 320 321 |
} /** * gfs2_blk2rgrpd - Find resource group for a given data/meta block number * @sdp: The GFS2 superblock * @n: The data block number * * Returns: The resource group, or NULL if not found */ |
cd915493f [GFS2] Change all... |
322 |
struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk) |
b3b94faa5 [GFS2] The core o... |
323 |
{ |
f75bbfb4d GFS2: Fix off-by-... |
324 325 |
struct rb_node **newn; struct gfs2_rgrpd *cur; |
b3b94faa5 [GFS2] The core o... |
326 327 |
spin_lock(&sdp->sd_rindex_spin); |
7c9ca6211 GFS2: Use rbtree ... |
328 |
newn = &sdp->sd_rindex_tree.rb_node; |
7c9ca6211 GFS2: Use rbtree ... |
329 |
while (*newn) { |
f75bbfb4d GFS2: Fix off-by-... |
330 |
cur = rb_entry(*newn, struct gfs2_rgrpd, rd_node); |
7c9ca6211 GFS2: Use rbtree ... |
331 332 |
if (blk < cur->rd_addr) newn = &((*newn)->rb_left); |
f75bbfb4d GFS2: Fix off-by-... |
333 |
else if (blk >= cur->rd_data0 + cur->rd_data) |
7c9ca6211 GFS2: Use rbtree ... |
334 335 |
newn = &((*newn)->rb_right); else { |
b3b94faa5 [GFS2] The core o... |
336 |
spin_unlock(&sdp->sd_rindex_spin); |
7c9ca6211 GFS2: Use rbtree ... |
337 |
return cur; |
b3b94faa5 [GFS2] The core o... |
338 339 |
} } |
b3b94faa5 [GFS2] The core o... |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
spin_unlock(&sdp->sd_rindex_spin); return NULL; } /** * gfs2_rgrpd_get_first - get the first Resource Group in the filesystem * @sdp: The GFS2 superblock * * Returns: The first rgrp in the filesystem */ struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp) { |
7c9ca6211 GFS2: Use rbtree ... |
354 355 |
const struct rb_node *n; struct gfs2_rgrpd *rgd; |
8339ee543 GFS2: Make resour... |
356 |
spin_lock(&sdp->sd_rindex_spin); |
7c9ca6211 GFS2: Use rbtree ... |
357 358 |
n = rb_first(&sdp->sd_rindex_tree); rgd = rb_entry(n, struct gfs2_rgrpd, rd_node); |
8339ee543 GFS2: Make resour... |
359 |
spin_unlock(&sdp->sd_rindex_spin); |
7c9ca6211 GFS2: Use rbtree ... |
360 361 |
return rgd; |
b3b94faa5 [GFS2] The core o... |
362 363 364 365 366 367 368 369 370 371 372 |
} /** * gfs2_rgrpd_get_next - get the next RG * @rgd: A RG * * Returns: The next rgrp */ struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd) { |
7c9ca6211 GFS2: Use rbtree ... |
373 374 375 376 377 378 379 380 381 382 |
struct gfs2_sbd *sdp = rgd->rd_sbd; const struct rb_node *n; spin_lock(&sdp->sd_rindex_spin); n = rb_next(&rgd->rd_node); if (n == NULL) n = rb_first(&sdp->sd_rindex_tree); if (unlikely(&rgd->rd_node == n)) { spin_unlock(&sdp->sd_rindex_spin); |
b3b94faa5 [GFS2] The core o... |
383 |
return NULL; |
7c9ca6211 GFS2: Use rbtree ... |
384 385 386 387 |
} rgd = rb_entry(n, struct gfs2_rgrpd, rd_node); spin_unlock(&sdp->sd_rindex_spin); return rgd; |
b3b94faa5 [GFS2] The core o... |
388 |
} |
8339ee543 GFS2: Make resour... |
389 390 391 392 393 394 395 396 397 398 399 400 |
void gfs2_free_clones(struct gfs2_rgrpd *rgd) { int x; for (x = 0; x < rgd->rd_length; x++) { struct gfs2_bitmap *bi = rgd->rd_bits + x; kfree(bi->bi_clone); bi->bi_clone = NULL; } } void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) |
b3b94faa5 [GFS2] The core o... |
401 |
{ |
7c9ca6211 GFS2: Use rbtree ... |
402 |
struct rb_node *n; |
b3b94faa5 [GFS2] The core o... |
403 404 |
struct gfs2_rgrpd *rgd; struct gfs2_glock *gl; |
7c9ca6211 GFS2: Use rbtree ... |
405 406 |
while ((n = rb_first(&sdp->sd_rindex_tree))) { rgd = rb_entry(n, struct gfs2_rgrpd, rd_node); |
b3b94faa5 [GFS2] The core o... |
407 |
gl = rgd->rd_gl; |
7c9ca6211 GFS2: Use rbtree ... |
408 |
rb_erase(n, &sdp->sd_rindex_tree); |
b3b94faa5 [GFS2] The core o... |
409 410 |
if (gl) { |
8339ee543 GFS2: Make resour... |
411 |
spin_lock(&gl->gl_spin); |
5c676f6d3 [GFS2] Macros rem... |
412 |
gl->gl_object = NULL; |
8339ee543 GFS2: Make resour... |
413 |
spin_unlock(&gl->gl_spin); |
29687a2ac GFS2: Alter point... |
414 |
gfs2_glock_add_to_lru(gl); |
b3b94faa5 [GFS2] The core o... |
415 416 |
gfs2_glock_put(gl); } |
8339ee543 GFS2: Make resour... |
417 |
gfs2_free_clones(rgd); |
b3b94faa5 [GFS2] The core o... |
418 |
kfree(rgd->rd_bits); |
6bdd9be62 [GFS2] Allocate g... |
419 |
kmem_cache_free(gfs2_rgrpd_cachep, rgd); |
b3b94faa5 [GFS2] The core o... |
420 421 |
} } |
bb8d8a6f5 [GFS2] Fix sign p... |
422 423 424 425 426 427 428 429 430 431 432 433 434 |
static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd) { printk(KERN_INFO " ri_addr = %llu ", (unsigned long long)rgd->rd_addr); printk(KERN_INFO " ri_length = %u ", rgd->rd_length); printk(KERN_INFO " ri_data0 = %llu ", (unsigned long long)rgd->rd_data0); printk(KERN_INFO " ri_data = %u ", rgd->rd_data); printk(KERN_INFO " ri_bitbytes = %u ", rgd->rd_bitbytes); } |
b3b94faa5 [GFS2] The core o... |
435 436 437 438 439 440 441 442 443 444 445 446 447 |
/** * gfs2_compute_bitstructs - Compute the bitmap sizes * @rgd: The resource group descriptor * * Calculates bitmap descriptors, one for each block that contains bitmap data * * Returns: errno */ static int compute_bitstructs(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_bitmap *bi; |
bb8d8a6f5 [GFS2] Fix sign p... |
448 |
u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */ |
cd915493f [GFS2] Change all... |
449 |
u32 bytes_left, bytes; |
b3b94faa5 [GFS2] The core o... |
450 |
int x; |
feaa7bba0 [GFS2] Fix unlink... |
451 452 |
if (!length) return -EINVAL; |
dd894be8d [GFS2] Change som... |
453 |
rgd->rd_bits = kcalloc(length, sizeof(struct gfs2_bitmap), GFP_NOFS); |
b3b94faa5 [GFS2] The core o... |
454 455 |
if (!rgd->rd_bits) return -ENOMEM; |
bb8d8a6f5 [GFS2] Fix sign p... |
456 |
bytes_left = rgd->rd_bitbytes; |
b3b94faa5 [GFS2] The core o... |
457 458 459 |
for (x = 0; x < length; x++) { bi = rgd->rd_bits + x; |
60a0b8f93 GFS2: Add a rgrp ... |
460 |
bi->bi_flags = 0; |
b3b94faa5 [GFS2] The core o... |
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
/* small rgrp; bitmap stored completely in header block */ if (length == 1) { bytes = bytes_left; bi->bi_offset = sizeof(struct gfs2_rgrp); bi->bi_start = 0; bi->bi_len = bytes; /* header block */ } else if (x == 0) { bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp); bi->bi_offset = sizeof(struct gfs2_rgrp); bi->bi_start = 0; bi->bi_len = bytes; /* last block */ } else if (x + 1 == length) { bytes = bytes_left; bi->bi_offset = sizeof(struct gfs2_meta_header); |
bb8d8a6f5 [GFS2] Fix sign p... |
477 |
bi->bi_start = rgd->rd_bitbytes - bytes_left; |
b3b94faa5 [GFS2] The core o... |
478 479 480 |
bi->bi_len = bytes; /* other blocks */ } else { |
568f4c965 [GFS2] 80 Column ... |
481 482 |
bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header); |
b3b94faa5 [GFS2] The core o... |
483 |
bi->bi_offset = sizeof(struct gfs2_meta_header); |
bb8d8a6f5 [GFS2] Fix sign p... |
484 |
bi->bi_start = rgd->rd_bitbytes - bytes_left; |
b3b94faa5 [GFS2] The core o... |
485 486 487 488 489 490 491 492 493 494 495 |
bi->bi_len = bytes; } bytes_left -= bytes; } if (bytes_left) { gfs2_consist_rgrpd(rgd); return -EIO; } bi = rgd->rd_bits + (length - 1); |
bb8d8a6f5 [GFS2] Fix sign p... |
496 |
if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) { |
b3b94faa5 [GFS2] The core o... |
497 |
if (gfs2_consist_rgrpd(rgd)) { |
bb8d8a6f5 [GFS2] Fix sign p... |
498 |
gfs2_rindex_print(rgd); |
b3b94faa5 [GFS2] The core o... |
499 500 501 502 503 504 505 506 507 508 509 |
fs_err(sdp, "start=%u len=%u offset=%u ", bi->bi_start, bi->bi_len, bi->bi_offset); } return -EIO; } return 0; } /** |
7ae8fa845 [GFS2] kernel cha... |
510 511 512 513 514 515 516 517 |
* gfs2_ri_total - Total up the file system space, according to the rindex. * */ u64 gfs2_ri_total(struct gfs2_sbd *sdp) { u64 total_data = 0; struct inode *inode = sdp->sd_rindex; struct gfs2_inode *ip = GFS2_I(inode); |
7ae8fa845 [GFS2] kernel cha... |
518 519 520 521 522 523 524 525 |
char buf[sizeof(struct gfs2_rindex)]; struct file_ra_state ra_state; int error, rgrps; mutex_lock(&sdp->sd_rindex_mutex); file_ra_state_init(&ra_state, inode->i_mapping); for (rgrps = 0;; rgrps++) { loff_t pos = rgrps * sizeof(struct gfs2_rindex); |
bcd7278d8 GFS2: fsck.gfs2 r... |
526 |
if (pos + sizeof(struct gfs2_rindex) > i_size_read(inode)) |
7ae8fa845 [GFS2] kernel cha... |
527 528 529 530 531 |
break; error = gfs2_internal_read(ip, &ra_state, buf, &pos, sizeof(struct gfs2_rindex)); if (error != sizeof(struct gfs2_rindex)) break; |
bb8d8a6f5 [GFS2] Fix sign p... |
532 |
total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data); |
7ae8fa845 [GFS2] kernel cha... |
533 534 535 536 |
} mutex_unlock(&sdp->sd_rindex_mutex); return total_data; } |
7c9ca6211 GFS2: Use rbtree ... |
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
static void rgd_insert(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct rb_node **newn = &sdp->sd_rindex_tree.rb_node, *parent = NULL; /* Figure out where to put new node */ while (*newn) { struct gfs2_rgrpd *cur = rb_entry(*newn, struct gfs2_rgrpd, rd_node); parent = *newn; if (rgd->rd_addr < cur->rd_addr) newn = &((*newn)->rb_left); else if (rgd->rd_addr > cur->rd_addr) newn = &((*newn)->rb_right); else return; } rb_link_node(&rgd->rd_node, parent, newn); rb_insert_color(&rgd->rd_node, &sdp->sd_rindex_tree); } |
7ae8fa845 [GFS2] kernel cha... |
559 |
/** |
6c53267f0 [GFS2] Kernel cha... |
560 |
* read_rindex_entry - Pull in a new resource index entry from the disk |
b3b94faa5 [GFS2] The core o... |
561 562 |
* @gl: The glock covering the rindex inode * |
8339ee543 GFS2: Make resour... |
563 |
* Returns: 0 on success, > 0 on EOF, error code otherwise |
6c53267f0 [GFS2] Kernel cha... |
564 565 566 567 568 569 570 |
*/ static int read_rindex_entry(struct gfs2_inode *ip, struct file_ra_state *ra_state) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); |
8339ee543 GFS2: Make resour... |
571 |
struct gfs2_rindex buf; |
6c53267f0 [GFS2] Kernel cha... |
572 573 |
int error; struct gfs2_rgrpd *rgd; |
8339ee543 GFS2: Make resour... |
574 575 576 577 |
if (pos >= i_size_read(&ip->i_inode)) return 1; error = gfs2_internal_read(ip, ra_state, (char *)&buf, &pos, |
6c53267f0 [GFS2] Kernel cha... |
578 |
sizeof(struct gfs2_rindex)); |
8339ee543 GFS2: Make resour... |
579 580 581 |
if (error != sizeof(struct gfs2_rindex)) return (error == 0) ? 1 : error; |
6c53267f0 [GFS2] Kernel cha... |
582 |
|
6bdd9be62 [GFS2] Allocate g... |
583 |
rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS); |
6c53267f0 [GFS2] Kernel cha... |
584 585 586 |
error = -ENOMEM; if (!rgd) return error; |
6c53267f0 [GFS2] Kernel cha... |
587 |
rgd->rd_sbd = sdp; |
8339ee543 GFS2: Make resour... |
588 589 590 591 592 |
rgd->rd_addr = be64_to_cpu(buf.ri_addr); rgd->rd_length = be32_to_cpu(buf.ri_length); rgd->rd_data0 = be64_to_cpu(buf.ri_data0); rgd->rd_data = be32_to_cpu(buf.ri_data); rgd->rd_bitbytes = be32_to_cpu(buf.ri_bitbytes); |
7c9ca6211 GFS2: Use rbtree ... |
593 |
|
6c53267f0 [GFS2] Kernel cha... |
594 595 |
error = compute_bitstructs(rgd); if (error) |
8339ee543 GFS2: Make resour... |
596 |
goto fail; |
6c53267f0 [GFS2] Kernel cha... |
597 |
|
bb8d8a6f5 [GFS2] Fix sign p... |
598 |
error = gfs2_glock_get(sdp, rgd->rd_addr, |
6c53267f0 [GFS2] Kernel cha... |
599 600 |
&gfs2_rgrp_glops, CREATE, &rgd->rd_gl); if (error) |
8339ee543 GFS2: Make resour... |
601 |
goto fail; |
6c53267f0 [GFS2] Kernel cha... |
602 603 |
rgd->rd_gl->gl_object = rgd; |
cf45b752c [GFS2] Remove rgr... |
604 |
rgd->rd_flags &= ~GFS2_RDF_UPTODATE; |
7c9ca6211 GFS2: Use rbtree ... |
605 606 |
if (rgd->rd_data > sdp->sd_max_rg_data) sdp->sd_max_rg_data = rgd->rd_data; |
8339ee543 GFS2: Make resour... |
607 608 609 610 611 612 613 614 615 |
spin_lock(&sdp->sd_rindex_spin); rgd_insert(rgd); sdp->sd_rgrps++; spin_unlock(&sdp->sd_rindex_spin); return error; fail: kfree(rgd->rd_bits); kmem_cache_free(gfs2_rgrpd_cachep, rgd); |
6c53267f0 [GFS2] Kernel cha... |
616 617 618 619 620 621 622 |
return error; } /** * gfs2_ri_update - Pull in a new resource index from the disk * @ip: pointer to the rindex inode * |
b3b94faa5 [GFS2] The core o... |
623 624 |
* Returns: 0 on successful update, error code otherwise */ |
8339ee543 GFS2: Make resour... |
625 |
static int gfs2_ri_update(struct gfs2_inode *ip) |
b3b94faa5 [GFS2] The core o... |
626 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
627 628 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct inode *inode = &ip->i_inode; |
f42faf4fa [GFS2] Add gfs2_i... |
629 |
struct file_ra_state ra_state; |
b3b94faa5 [GFS2] The core o... |
630 |
int error; |
f42faf4fa [GFS2] Add gfs2_i... |
631 |
file_ra_state_init(&ra_state, inode->i_mapping); |
8339ee543 GFS2: Make resour... |
632 |
do { |
6c53267f0 [GFS2] Kernel cha... |
633 |
error = read_rindex_entry(ip, &ra_state); |
8339ee543 GFS2: Make resour... |
634 635 636 637 |
} while (error == 0); if (error < 0) return error; |
b3b94faa5 [GFS2] The core o... |
638 |
|
cf45b752c [GFS2] Remove rgr... |
639 |
sdp->sd_rindex_uptodate = 1; |
6c53267f0 [GFS2] Kernel cha... |
640 641 |
return 0; } |
b3b94faa5 [GFS2] The core o... |
642 |
|
6c53267f0 [GFS2] Kernel cha... |
643 |
/** |
8339ee543 GFS2: Make resour... |
644 |
* gfs2_rindex_update - Update the rindex if required |
b3b94faa5 [GFS2] The core o... |
645 |
* @sdp: The GFS2 superblock |
b3b94faa5 [GFS2] The core o... |
646 647 648 649 650 651 652 653 654 655 656 |
* * We grab a lock on the rindex inode to make sure that it doesn't * change whilst we are performing an operation. We keep this lock * for quite long periods of time compared to other locks. This * doesn't matter, since it is shared and it is very, very rarely * accessed in the exclusive mode (i.e. only when expanding the filesystem). * * This makes sure that we're using the latest copy of the resource index * special file, which might have been updated if someone expanded the * filesystem (via gfs2_grow utility), which adds new resource groups. * |
8339ee543 GFS2: Make resour... |
657 |
* Returns: 0 on succeess, error code otherwise |
b3b94faa5 [GFS2] The core o... |
658 |
*/ |
8339ee543 GFS2: Make resour... |
659 |
int gfs2_rindex_update(struct gfs2_sbd *sdp) |
b3b94faa5 [GFS2] The core o... |
660 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
661 |
struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); |
b3b94faa5 [GFS2] The core o... |
662 |
struct gfs2_glock *gl = ip->i_gl; |
8339ee543 GFS2: Make resour... |
663 664 |
struct gfs2_holder ri_gh; int error = 0; |
b3b94faa5 [GFS2] The core o... |
665 666 |
/* Read new copy from disk if we don't have the latest */ |
cf45b752c [GFS2] Remove rgr... |
667 |
if (!sdp->sd_rindex_uptodate) { |
f55ab26a8 [GFS2] Use mutice... |
668 |
mutex_lock(&sdp->sd_rindex_mutex); |
8339ee543 GFS2: Make resour... |
669 670 671 672 |
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &ri_gh); if (error) return error; if (!sdp->sd_rindex_uptodate) |
b3b94faa5 [GFS2] The core o... |
673 |
error = gfs2_ri_update(ip); |
8339ee543 GFS2: Make resour... |
674 |
gfs2_glock_dq_uninit(&ri_gh); |
f55ab26a8 [GFS2] Use mutice... |
675 |
mutex_unlock(&sdp->sd_rindex_mutex); |
b3b94faa5 [GFS2] The core o... |
676 |
} |
8339ee543 GFS2: Make resour... |
677 |
|
b3b94faa5 [GFS2] The core o... |
678 679 |
return error; } |
42d52e381 [GFS2] Combine rg... |
680 |
static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf) |
bb8d8a6f5 [GFS2] Fix sign p... |
681 682 |
{ const struct gfs2_rgrp *str = buf; |
42d52e381 [GFS2] Combine rg... |
683 |
u32 rg_flags; |
bb8d8a6f5 [GFS2] Fix sign p... |
684 |
|
42d52e381 [GFS2] Combine rg... |
685 |
rg_flags = be32_to_cpu(str->rg_flags); |
090109783 GFS2: Improve res... |
686 |
rg_flags &= ~GFS2_RDF_MASK; |
1ce97e564 GFS2: Be more agg... |
687 688 |
rgd->rd_flags &= GFS2_RDF_MASK; rgd->rd_flags |= rg_flags; |
cfc8b5492 GFS2: Move rg_fre... |
689 |
rgd->rd_free = be32_to_cpu(str->rg_free); |
73f749483 GFS2: Banish stru... |
690 |
rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes); |
d8b71f738 GFS2: Move rg_ige... |
691 |
rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration); |
bb8d8a6f5 [GFS2] Fix sign p... |
692 |
} |
42d52e381 [GFS2] Combine rg... |
693 |
static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) |
bb8d8a6f5 [GFS2] Fix sign p... |
694 695 |
{ struct gfs2_rgrp *str = buf; |
090109783 GFS2: Improve res... |
696 |
str->rg_flags = cpu_to_be32(rgd->rd_flags & ~GFS2_RDF_MASK); |
cfc8b5492 GFS2: Move rg_fre... |
697 |
str->rg_free = cpu_to_be32(rgd->rd_free); |
73f749483 GFS2: Banish stru... |
698 |
str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes); |
bb8d8a6f5 [GFS2] Fix sign p... |
699 |
str->__pad = cpu_to_be32(0); |
d8b71f738 GFS2: Move rg_ige... |
700 |
str->rg_igeneration = cpu_to_be64(rgd->rd_igeneration); |
bb8d8a6f5 [GFS2] Fix sign p... |
701 702 |
memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); } |
b3b94faa5 [GFS2] The core o... |
703 |
/** |
7c9ca6211 GFS2: Use rbtree ... |
704 |
* gfs2_rgrp_go_lock - Read in a RG's header and bitmaps |
b3b94faa5 [GFS2] The core o... |
705 706 707 708 709 710 711 |
* @rgd: the struct gfs2_rgrpd describing the RG to read in * * Read in all of a Resource Group's header and bitmap blocks. * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps. * * Returns: errno */ |
7c9ca6211 GFS2: Use rbtree ... |
712 |
int gfs2_rgrp_go_lock(struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
713 |
{ |
7c9ca6211 GFS2: Use rbtree ... |
714 |
struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; |
b3b94faa5 [GFS2] The core o... |
715 716 |
struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_glock *gl = rgd->rd_gl; |
bb8d8a6f5 [GFS2] Fix sign p... |
717 |
unsigned int length = rgd->rd_length; |
b3b94faa5 [GFS2] The core o... |
718 719 720 |
struct gfs2_bitmap *bi; unsigned int x, y; int error; |
b3b94faa5 [GFS2] The core o... |
721 722 |
for (x = 0; x < length; x++) { bi = rgd->rd_bits + x; |
bb8d8a6f5 [GFS2] Fix sign p... |
723 |
error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh); |
b3b94faa5 [GFS2] The core o... |
724 725 726 727 728 729 |
if (error) goto fail; } for (y = length; y--;) { bi = rgd->rd_bits + y; |
7276b3b0c [GFS2] Tidy up me... |
730 |
error = gfs2_meta_wait(sdp, bi->bi_bh); |
b3b94faa5 [GFS2] The core o... |
731 732 |
if (error) goto fail; |
feaa7bba0 [GFS2] Fix unlink... |
733 |
if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB : |
b3b94faa5 [GFS2] The core o... |
734 735 736 737 738 |
GFS2_METATYPE_RG)) { error = -EIO; goto fail; } } |
cf45b752c [GFS2] Remove rgr... |
739 |
if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) { |
60a0b8f93 GFS2: Add a rgrp ... |
740 741 |
for (x = 0; x < length; x++) clear_bit(GBF_FULL, &rgd->rd_bits[x].bi_flags); |
42d52e381 [GFS2] Combine rg... |
742 |
gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); |
1ce97e564 GFS2: Be more agg... |
743 |
rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); |
7c9ca6211 GFS2: Use rbtree ... |
744 |
rgd->rd_free_clone = rgd->rd_free; |
b3b94faa5 [GFS2] The core o... |
745 |
} |
b3b94faa5 [GFS2] The core o... |
746 |
return 0; |
feaa7bba0 [GFS2] Fix unlink... |
747 |
fail: |
b3b94faa5 [GFS2] The core o... |
748 749 750 751 752 753 |
while (x--) { bi = rgd->rd_bits + x; brelse(bi->bi_bh); bi->bi_bh = NULL; gfs2_assert_warn(sdp, !bi->bi_clone); } |
b3b94faa5 [GFS2] The core o... |
754 755 756 |
return error; } |
b3b94faa5 [GFS2] The core o... |
757 |
/** |
7c9ca6211 GFS2: Use rbtree ... |
758 |
* gfs2_rgrp_go_unlock - Release RG bitmaps read in with gfs2_rgrp_bh_get() |
b3b94faa5 [GFS2] The core o... |
759 760 761 |
* @rgd: the struct gfs2_rgrpd describing the RG to read in * */ |
7c9ca6211 GFS2: Use rbtree ... |
762 |
void gfs2_rgrp_go_unlock(struct gfs2_holder *gh) |
b3b94faa5 [GFS2] The core o... |
763 |
{ |
7c9ca6211 GFS2: Use rbtree ... |
764 |
struct gfs2_rgrpd *rgd = gh->gh_gl->gl_object; |
bb8d8a6f5 [GFS2] Fix sign p... |
765 |
int x, length = rgd->rd_length; |
b3b94faa5 [GFS2] The core o... |
766 |
|
b3b94faa5 [GFS2] The core o... |
767 768 |
for (x = 0; x < length; x++) { struct gfs2_bitmap *bi = rgd->rd_bits + x; |
b3b94faa5 [GFS2] The core o... |
769 770 771 |
brelse(bi->bi_bh); bi->bi_bh = NULL; } |
b3b94faa5 [GFS2] The core o... |
772 |
} |
7c9ca6211 GFS2: Use rbtree ... |
773 774 775 |
void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, struct buffer_head *bh, const struct gfs2_bitmap *bi) |
f15ab5619 GFS2: Support gen... |
776 777 778 779 |
{ struct super_block *sb = sdp->sd_vfs; struct block_device *bdev = sb->s_bdev; const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize / |
e1defc4ff block: Do away wi... |
780 |
bdev_logical_block_size(sb->s_bdev); |
f15ab5619 GFS2: Support gen... |
781 |
u64 blk; |
64d576ba2 GFS2: Add a "demo... |
782 |
sector_t start = 0; |
f15ab5619 GFS2: Support gen... |
783 784 785 786 787 |
sector_t nr_sects = 0; int rv; unsigned int x; for (x = 0; x < bi->bi_len; x++) { |
7c9ca6211 GFS2: Use rbtree ... |
788 |
const u8 *orig = bh->b_data + bi->bi_offset + x; |
f15ab5619 GFS2: Support gen... |
789 790 791 792 793 794 795 796 797 798 799 800 801 |
const u8 *clone = bi->bi_clone + bi->bi_offset + x; u8 diff = ~(*orig | (*orig >> 1)) & (*clone | (*clone >> 1)); diff &= 0x55; if (diff == 0) continue; blk = offset + ((bi->bi_start + x) * GFS2_NBBY); blk *= sects_per_blk; /* convert to sectors */ while(diff) { if (diff & 1) { if (nr_sects == 0) goto start_new_extent; if ((start + nr_sects) != blk) { rv = blkdev_issue_discard(bdev, start, |
746cd1e7e block: use blkdev... |
802 |
nr_sects, GFP_NOFS, |
dd3932edd block: remove BLK... |
803 |
0); |
f15ab5619 GFS2: Support gen... |
804 805 806 807 808 809 810 811 812 813 814 815 816 |
if (rv) goto fail; nr_sects = 0; start_new_extent: start = blk; } nr_sects += sects_per_blk; } diff >>= 2; blk += sects_per_blk; } } if (nr_sects) { |
dd3932edd block: remove BLK... |
817 |
rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0); |
f15ab5619 GFS2: Support gen... |
818 819 820 821 822 823 824 825 |
if (rv) goto fail; } return; fail: fs_warn(sdp, "error %d on discard request, turning discards off for this filesystem", rv); sdp->sd_args.ar_discard = 0; } |
b3b94faa5 [GFS2] The core o... |
826 |
/** |
564e12b11 GFS2: decouple qu... |
827 |
* gfs2_qadata_get - get the struct gfs2_qadata structure for an inode |
b3b94faa5 [GFS2] The core o... |
828 829 |
* @ip: the incore GFS2 inode structure * |
564e12b11 GFS2: decouple qu... |
830 |
* Returns: the struct gfs2_qadata |
b3b94faa5 [GFS2] The core o... |
831 |
*/ |
564e12b11 GFS2: decouple qu... |
832 |
struct gfs2_qadata *gfs2_qadata_get(struct gfs2_inode *ip) |
b3b94faa5 [GFS2] The core o... |
833 |
{ |
8339ee543 GFS2: Make resour... |
834 835 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); int error; |
564e12b11 GFS2: decouple qu... |
836 837 |
BUG_ON(ip->i_qadata != NULL); ip->i_qadata = kzalloc(sizeof(struct gfs2_qadata), GFP_NOFS); |
8339ee543 GFS2: Make resour... |
838 839 840 841 |
error = gfs2_rindex_update(sdp); if (error) fs_warn(sdp, "rindex update returns %d ", error); |
564e12b11 GFS2: decouple qu... |
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 |
return ip->i_qadata; } /** * gfs2_blkrsv_get - get the struct gfs2_blkreserv structure for an inode * @ip: the incore GFS2 inode structure * * Returns: the struct gfs2_qadata */ static struct gfs2_blkreserv *gfs2_blkrsv_get(struct gfs2_inode *ip) { BUG_ON(ip->i_res != NULL); ip->i_res = kzalloc(sizeof(struct gfs2_blkreserv), GFP_NOFS); return ip->i_res; |
b3b94faa5 [GFS2] The core o... |
857 858 859 |
} /** |
b3b94faa5 [GFS2] The core o... |
860 861 |
* try_rgrp_fit - See if a given reservation will fit in a given RG * @rgd: the RG data |
54335b1fc GFS2: Cache the m... |
862 |
* @ip: the inode |
b3b94faa5 [GFS2] The core o... |
863 864 |
* * If there's room for the requested blocks to be allocated from the RG: |
b3b94faa5 [GFS2] The core o... |
865 866 867 |
* * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) */ |
54335b1fc GFS2: Cache the m... |
868 |
static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *ip) |
b3b94faa5 [GFS2] The core o... |
869 |
{ |
564e12b11 GFS2: decouple qu... |
870 |
const struct gfs2_blkreserv *rs = ip->i_res; |
54335b1fc GFS2: Cache the m... |
871 |
|
090109783 GFS2: Improve res... |
872 |
if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) |
a43a49066 [GFS2] Fix bz 234... |
873 |
return 0; |
564e12b11 GFS2: decouple qu... |
874 |
if (rgd->rd_free_clone >= rs->rs_requested) |
7c9ca6211 GFS2: Use rbtree ... |
875 |
return 1; |
7c9ca6211 GFS2: Use rbtree ... |
876 |
return 0; |
b3b94faa5 [GFS2] The core o... |
877 |
} |
b3e47ca0c GFS2: split funct... |
878 879 880 881 |
static inline u32 gfs2_bi2rgd_blk(struct gfs2_bitmap *bi, u32 blk) { return (bi->bi_start * GFS2_NBBY) + blk; } |
b3b94faa5 [GFS2] The core o... |
882 |
/** |
c8cdf4793 [GFS2] Recovery f... |
883 884 885 |
* try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes * @rgd: The rgrp * |
1a0eae884 GFS2: glock livelock |
886 887 |
* Returns: 0 if no error * The inode, if one has been found, in inode. |
c8cdf4793 [GFS2] Recovery f... |
888 |
*/ |
044b9414c GFS2: Fix inode d... |
889 |
static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip) |
c8cdf4793 [GFS2] Recovery f... |
890 |
{ |
6760bdcd0 [GFS2] Prevent in... |
891 |
u32 goal = 0, block; |
bb9bcf061 [GFS2] Obtaining ... |
892 |
u64 no_addr; |
5f3eae754 [GFS2] invalid me... |
893 |
struct gfs2_sbd *sdp = rgd->rd_sbd; |
044b9414c GFS2: Fix inode d... |
894 895 896 897 |
struct gfs2_glock *gl; struct gfs2_inode *ip; int error; int found = 0; |
b3e47ca0c GFS2: split funct... |
898 |
struct gfs2_bitmap *bi; |
c8cdf4793 [GFS2] Recovery f... |
899 |
|
044b9414c GFS2: Fix inode d... |
900 |
while (goal < rgd->rd_data) { |
5f3eae754 [GFS2] invalid me... |
901 |
down_write(&sdp->sd_log_flush_lock); |
6a8099ed5 GFS2: Fix multi-b... |
902 |
block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, &bi); |
5f3eae754 [GFS2] invalid me... |
903 |
up_write(&sdp->sd_log_flush_lock); |
6760bdcd0 [GFS2] Prevent in... |
904 |
if (block == BFITNOENT) |
24c738733 [GFS2] soft locku... |
905 |
break; |
b3e47ca0c GFS2: split funct... |
906 907 |
block = gfs2_bi2rgd_blk(bi, block); |
6760bdcd0 [GFS2] Prevent in... |
908 909 910 |
/* rgblk_search can return a block < goal, so we need to keep it marching forward. */ no_addr = block + rgd->rd_data0; |
44ad37d69 GFS2: filesystem ... |
911 |
goal = max(block + 1, goal + 1); |
6760bdcd0 [GFS2] Prevent in... |
912 |
if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
c8cdf4793 [GFS2] Recovery f... |
913 |
continue; |
1e19a1958 GFS2: Don't try a... |
914 915 |
if (no_addr == skip) continue; |
bb9bcf061 [GFS2] Obtaining ... |
916 |
*last_unlinked = no_addr; |
044b9414c GFS2: Fix inode d... |
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 |
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &gl); if (error) continue; /* If the inode is already in cache, we can ignore it here * because the existing inode disposal code will deal with * it when all refs have gone away. Accessing gl_object like * this is not safe in general. Here it is ok because we do * not dereference the pointer, and we only need an approx * answer to whether it is NULL or not. */ ip = gl->gl_object; if (ip || queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) gfs2_glock_put(gl); else found++; /* Limit reclaim to sensible number of tasks */ |
44ad37d69 GFS2: filesystem ... |
937 |
if (found > NR_CPUS) |
044b9414c GFS2: Fix inode d... |
938 |
return; |
c8cdf4793 [GFS2] Recovery f... |
939 940 941 |
} rgd->rd_flags &= ~GFS2_RDF_CHECK; |
044b9414c GFS2: Fix inode d... |
942 |
return; |
c8cdf4793 [GFS2] Recovery f... |
943 944 945 |
} /** |
b3b94faa5 [GFS2] The core o... |
946 947 948 949 950 951 952 953 |
* get_local_rgrp - Choose and lock a rgrp for allocation * @ip: the inode to reserve space for * @rgp: the chosen and locked rgrp * * Try to acquire rgrp in way which avoids contending with others. * * Returns: errno */ |
044b9414c GFS2: Fix inode d... |
954 |
static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) |
b3b94faa5 [GFS2] The core o... |
955 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
956 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
b3b94faa5 [GFS2] The core o... |
957 |
struct gfs2_rgrpd *rgd, *begin = NULL; |
564e12b11 GFS2: decouple qu... |
958 |
struct gfs2_blkreserv *rs = ip->i_res; |
c688b8b33 GFS2: Add non-try... |
959 |
int error, rg_locked, flags = LM_FLAG_TRY; |
7c9ca6211 GFS2: Use rbtree ... |
960 |
int loops = 0; |
b3b94faa5 [GFS2] The core o... |
961 |
|
54335b1fc GFS2: Cache the m... |
962 963 964 965 |
if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) rgd = begin = ip->i_rgd; else rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal); |
b3b94faa5 [GFS2] The core o... |
966 |
|
7c9ca6211 GFS2: Use rbtree ... |
967 968 969 970 |
if (rgd == NULL) return -EBADSLT; while (loops < 3) { |
292c8c14c [GFS2] patch to c... |
971 972 973 974 975 976 977 |
rg_locked = 0; if (gfs2_glock_is_locked_by_me(rgd->rd_gl)) { rg_locked = 1; error = 0; } else { error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, |
564e12b11 GFS2: decouple qu... |
978 |
flags, &rs->rs_rgd_gh); |
292c8c14c [GFS2] patch to c... |
979 |
} |
b3b94faa5 [GFS2] The core o... |
980 981 |
switch (error) { case 0: |
54335b1fc GFS2: Cache the m... |
982 983 |
if (try_rgrp_fit(rgd, ip)) { ip->i_rgd = rgd; |
7c9ca6211 GFS2: Use rbtree ... |
984 |
return 0; |
54335b1fc GFS2: Cache the m... |
985 |
} |
044b9414c GFS2: Fix inode d... |
986 987 |
if (rgd->rd_flags & GFS2_RDF_CHECK) try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
292c8c14c [GFS2] patch to c... |
988 |
if (!rg_locked) |
564e12b11 GFS2: decouple qu... |
989 |
gfs2_glock_dq_uninit(&rs->rs_rgd_gh); |
9cabcdbd4 [GFS2] Replace rg... |
990 |
/* fall through */ |
b3b94faa5 [GFS2] The core o... |
991 |
case GLR_TRYFAILED: |
7c9ca6211 GFS2: Use rbtree ... |
992 |
rgd = gfs2_rgrpd_get_next(rgd); |
c688b8b33 GFS2: Add non-try... |
993 994 |
if (rgd == begin) { flags = 0; |
7c9ca6211 GFS2: Use rbtree ... |
995 |
loops++; |
c688b8b33 GFS2: Add non-try... |
996 |
} |
b3b94faa5 [GFS2] The core o... |
997 |
break; |
b3b94faa5 [GFS2] The core o... |
998 |
default: |
cc0581bd6 GFS2: stuck in in... |
999 |
return error; |
b3b94faa5 [GFS2] The core o... |
1000 |
} |
b3b94faa5 [GFS2] The core o... |
1001 |
} |
7c9ca6211 GFS2: Use rbtree ... |
1002 |
return -ENOSPC; |
b3b94faa5 [GFS2] The core o... |
1003 |
} |
564e12b11 GFS2: decouple qu... |
1004 1005 1006 1007 1008 1009 |
static void gfs2_blkrsv_put(struct gfs2_inode *ip) { BUG_ON(ip->i_res == NULL); kfree(ip->i_res); ip->i_res = NULL; } |
b3b94faa5 [GFS2] The core o... |
1010 |
/** |
9ae32429f GFS2: Remove two ... |
1011 |
* gfs2_inplace_reserve - Reserve space in the filesystem |
b3b94faa5 [GFS2] The core o... |
1012 1013 1014 1015 |
* @ip: the inode to reserve space for * * Returns: errno */ |
564e12b11 GFS2: decouple qu... |
1016 |
int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) |
b3b94faa5 [GFS2] The core o... |
1017 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
1018 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
564e12b11 GFS2: decouple qu... |
1019 |
struct gfs2_blkreserv *rs; |
7ae8fa845 [GFS2] kernel cha... |
1020 |
int error = 0; |
044b9414c GFS2: Fix inode d... |
1021 1022 |
u64 last_unlinked = NO_BLOCK; int tries = 0; |
b3b94faa5 [GFS2] The core o... |
1023 |
|
564e12b11 GFS2: decouple qu... |
1024 1025 1026 1027 1028 1029 1030 1031 1032 |
rs = gfs2_blkrsv_get(ip); if (!rs) return -ENOMEM; rs->rs_requested = requested; if (gfs2_assert_warn(sdp, requested)) { error = -EINVAL; goto out; } |
b3b94faa5 [GFS2] The core o... |
1033 |
|
044b9414c GFS2: Fix inode d... |
1034 1035 |
do { error = get_local_rgrp(ip, &last_unlinked); |
54335b1fc GFS2: Cache the m... |
1036 1037 1038 1039 1040 1041 1042 1043 |
if (error != -ENOSPC) break; /* Check that fs hasn't grown if writing to rindex */ if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) { error = gfs2_ri_update(ip); if (error) break; continue; |
0489b3f5e GFS2: reread rind... |
1044 |
} |
54335b1fc GFS2: Cache the m... |
1045 1046 1047 |
/* Flushing the log may release space */ gfs2_log_flush(sdp, NULL); } while (tries++ < 3); |
b3b94faa5 [GFS2] The core o... |
1048 |
|
564e12b11 GFS2: decouple qu... |
1049 1050 1051 |
out: if (error) gfs2_blkrsv_put(ip); |
9ae32429f GFS2: Remove two ... |
1052 |
return error; |
b3b94faa5 [GFS2] The core o... |
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 |
} /** * gfs2_inplace_release - release an inplace reservation * @ip: the inode the reservation was taken out on * * Release a reservation made by gfs2_inplace_reserve(). */ void gfs2_inplace_release(struct gfs2_inode *ip) { |
564e12b11 GFS2: decouple qu... |
1064 |
struct gfs2_blkreserv *rs = ip->i_res; |
b3b94faa5 [GFS2] The core o... |
1065 |
|
564e12b11 GFS2: decouple qu... |
1066 1067 |
if (rs->rs_rgd_gh.gh_gl) gfs2_glock_dq_uninit(&rs->rs_rgd_gh); |
49528b4e4 GFS2: Fix a use-a... |
1068 |
gfs2_blkrsv_put(ip); |
b3b94faa5 [GFS2] The core o... |
1069 1070 1071 1072 1073 1074 1075 1076 1077 |
} /** * gfs2_get_block_type - Check a block in a RG is of given type * @rgd: the resource group holding the block * @block: the block number * * Returns: The block type (GFS2_BLKST_*) */ |
acf7e2444 GFS2: Be extra ca... |
1078 |
static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) |
b3b94faa5 [GFS2] The core o... |
1079 1080 |
{ struct gfs2_bitmap *bi = NULL; |
cd915493f [GFS2] Change all... |
1081 |
u32 length, rgrp_block, buf_block; |
b3b94faa5 [GFS2] The core o... |
1082 1083 |
unsigned int buf; unsigned char type; |
bb8d8a6f5 [GFS2] Fix sign p... |
1084 1085 |
length = rgd->rd_length; rgrp_block = block - rgd->rd_data0; |
b3b94faa5 [GFS2] The core o... |
1086 1087 1088 1089 1090 1091 1092 1093 1094 |
for (buf = 0; buf < length; buf++) { bi = rgd->rd_bits + buf; if (rgrp_block < (bi->bi_start + bi->bi_len) * GFS2_NBBY) break; } gfs2_assert(rgd->rd_sbd, buf < length); buf_block = rgrp_block - bi->bi_start * GFS2_NBBY; |
feaa7bba0 [GFS2] Fix unlink... |
1095 |
type = gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset, |
b3b94faa5 [GFS2] The core o... |
1096 1097 1098 1099 1100 1101 |
bi->bi_len, buf_block); return type; } /** |
6a8099ed5 GFS2: Fix multi-b... |
1102 |
* rgblk_search - find a block in @state |
b3b94faa5 [GFS2] The core o... |
1103 1104 |
* @rgd: the resource group descriptor * @goal: the goal block within the RG (start here to search for avail block) |
6a8099ed5 GFS2: Fix multi-b... |
1105 |
* @state: GFS2_BLKST_XXX the before-allocation state to find |
6e87ed0fc GFS2: move toward... |
1106 |
* @dinode: TRUE if the first block we allocate is for a dinode |
b3e47ca0c GFS2: split funct... |
1107 |
* @rbi: address of the pointer to the bitmap containing the block found |
b3b94faa5 [GFS2] The core o... |
1108 |
* |
6a8099ed5 GFS2: Fix multi-b... |
1109 |
* Walk rgrp's bitmap to find bits that represent a block in @state. |
b3b94faa5 [GFS2] The core o... |
1110 1111 1112 1113 |
* * This function never fails, because we wouldn't call it unless we * know (from reservation results, etc.) that a block is available. * |
b3e47ca0c GFS2: split funct... |
1114 1115 |
* Scope of @goal is just within rgrp, not the whole filesystem. * Scope of @returned block is just within bitmap, not the whole filesystem. |
b3b94faa5 [GFS2] The core o... |
1116 |
* |
b3e47ca0c GFS2: split funct... |
1117 |
* Returns: the block number found relative to the bitmap rbi |
b3b94faa5 [GFS2] The core o... |
1118 |
*/ |
cd915493f [GFS2] Change all... |
1119 |
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
6a8099ed5 GFS2: Fix multi-b... |
1120 |
unsigned char state, |
b3e47ca0c GFS2: split funct... |
1121 |
struct gfs2_bitmap **rbi) |
b3b94faa5 [GFS2] The core o... |
1122 1123 |
{ struct gfs2_bitmap *bi = NULL; |
b45e41d7d [GFS2] Add extent... |
1124 |
const u32 length = rgd->rd_length; |
60a0b8f93 GFS2: Add a rgrp ... |
1125 |
u32 blk = BFITNOENT; |
b3b94faa5 [GFS2] The core o... |
1126 |
unsigned int buf, x; |
60a0b8f93 GFS2: Add a rgrp ... |
1127 |
const u8 *buffer = NULL; |
b3b94faa5 [GFS2] The core o... |
1128 |
|
b3e47ca0c GFS2: split funct... |
1129 |
*rbi = NULL; |
b3b94faa5 [GFS2] The core o... |
1130 1131 1132 |
/* Find bitmap block that contains bits for goal block */ for (buf = 0; buf < length; buf++) { bi = rgd->rd_bits + buf; |
60a0b8f93 GFS2: Add a rgrp ... |
1133 1134 1135 1136 1137 |
/* Convert scope of "goal" from rgrp-wide to within found bit block */ if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) { goal -= bi->bi_start * GFS2_NBBY; goto do_search; } |
b3b94faa5 [GFS2] The core o... |
1138 |
} |
60a0b8f93 GFS2: Add a rgrp ... |
1139 1140 |
buf = 0; goal = 0; |
b3b94faa5 [GFS2] The core o... |
1141 |
|
60a0b8f93 GFS2: Add a rgrp ... |
1142 |
do_search: |
b3b94faa5 [GFS2] The core o... |
1143 1144 1145 1146 1147 1148 |
/* Search (up to entire) bitmap in this rgrp for allocatable block. "x <= length", instead of "x < length", because we typically start the search in the middle of a bit block, but if we can't find an allocatable block anywhere else, we want to be able wrap around and search in the first part of our first-searched bit block. */ for (x = 0; x <= length; x++) { |
60a0b8f93 GFS2: Add a rgrp ... |
1149 1150 1151 |
bi = rgd->rd_bits + buf; if (test_bit(GBF_FULL, &bi->bi_flags) && |
6a8099ed5 GFS2: Fix multi-b... |
1152 |
(state == GFS2_BLKST_FREE)) |
60a0b8f93 GFS2: Add a rgrp ... |
1153 |
goto skip; |
5f3eae754 [GFS2] invalid me... |
1154 1155 |
/* The GFS2_BLKST_UNLINKED state doesn't apply to the clone bitmaps, so we must search the originals for that. */ |
b45e41d7d [GFS2] Add extent... |
1156 |
buffer = bi->bi_bh->b_data + bi->bi_offset; |
7c9ca6211 GFS2: Use rbtree ... |
1157 |
WARN_ON(!buffer_uptodate(bi->bi_bh)); |
6a8099ed5 GFS2: Fix multi-b... |
1158 |
if (state != GFS2_BLKST_UNLINKED && bi->bi_clone) |
110acf383 [GFS2] Add consts... |
1159 |
buffer = bi->bi_clone + bi->bi_offset; |
6a8099ed5 GFS2: Fix multi-b... |
1160 |
blk = gfs2_bitfit(buffer, bi->bi_len, goal, state); |
b3b94faa5 [GFS2] The core o... |
1161 1162 |
if (blk != BFITNOENT) break; |
6a8099ed5 GFS2: Fix multi-b... |
1163 |
if ((goal == 0) && (state == GFS2_BLKST_FREE)) |
60a0b8f93 GFS2: Add a rgrp ... |
1164 |
set_bit(GBF_FULL, &bi->bi_flags); |
b3b94faa5 [GFS2] The core o... |
1165 |
/* Try next bitmap block (wrap back to rgrp header if at end) */ |
60a0b8f93 GFS2: Add a rgrp ... |
1166 1167 1168 |
skip: buf++; buf %= length; |
b3b94faa5 [GFS2] The core o... |
1169 1170 |
goal = 0; } |
b3e47ca0c GFS2: split funct... |
1171 1172 |
if (blk != BFITNOENT) *rbi = bi; |
7c9ca6211 GFS2: Use rbtree ... |
1173 |
|
b3e47ca0c GFS2: split funct... |
1174 1175 |
return blk; } |
60a0b8f93 GFS2: Add a rgrp ... |
1176 |
|
b3e47ca0c GFS2: split funct... |
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
/** * gfs2_alloc_extent - allocate an extent from a given bitmap * @rgd: the resource group descriptor * @bi: the bitmap within the rgrp * @blk: the block within the bitmap * @dinode: TRUE if the first block we allocate is for a dinode * @n: The extent length * * Add the found bitmap buffer to the transaction. * Set the found bits to @new_state to change block's allocation state. * Returns: starting block number of the extent (fs scope) */ static u64 gfs2_alloc_extent(struct gfs2_rgrpd *rgd, struct gfs2_bitmap *bi, u32 blk, bool dinode, unsigned int *n) { const unsigned int elen = *n; u32 goal; const u8 *buffer = NULL; |
6a8099ed5 GFS2: Fix multi-b... |
1195 |
*n = 0; |
b3e47ca0c GFS2: split funct... |
1196 |
buffer = bi->bi_bh->b_data + bi->bi_offset; |
60a0b8f93 GFS2: Add a rgrp ... |
1197 1198 |
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
6e87ed0fc GFS2: move toward... |
1199 |
bi, blk, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); |
6a8099ed5 GFS2: Fix multi-b... |
1200 |
(*n)++; |
60a0b8f93 GFS2: Add a rgrp ... |
1201 1202 1203 1204 1205 1206 1207 1208 |
goal = blk; while (*n < elen) { goal++; if (goal >= (bi->bi_len * GFS2_NBBY)) break; if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != GFS2_BLKST_FREE) break; |
b45e41d7d [GFS2] Add extent... |
1209 |
gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
6e87ed0fc GFS2: move toward... |
1210 |
bi, goal, GFS2_BLKST_USED); |
60a0b8f93 GFS2: Add a rgrp ... |
1211 |
(*n)++; |
c8cdf4793 [GFS2] Recovery f... |
1212 |
} |
b3e47ca0c GFS2: split funct... |
1213 |
blk = gfs2_bi2rgd_blk(bi, blk); |
6a8099ed5 GFS2: Fix multi-b... |
1214 |
rgd->rd_last_alloc = blk + *n - 1; |
b3e47ca0c GFS2: split funct... |
1215 |
return rgd->rd_data0 + blk; |
b3b94faa5 [GFS2] The core o... |
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 |
} /** * rgblk_free - Change alloc state of given block(s) * @sdp: the filesystem * @bstart: the start of a run of blocks to free * @blen: the length of the block run (all must lie within ONE RG!) * @new_state: GFS2_BLKST_XXX the after-allocation block state * * Returns: Resource group containing the block(s) */ |
cd915493f [GFS2] Change all... |
1227 1228 |
static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, u32 blen, unsigned char new_state) |
b3b94faa5 [GFS2] The core o... |
1229 1230 1231 |
{ struct gfs2_rgrpd *rgd; struct gfs2_bitmap *bi = NULL; |
cd915493f [GFS2] Change all... |
1232 |
u32 length, rgrp_blk, buf_blk; |
b3b94faa5 [GFS2] The core o... |
1233 1234 1235 1236 1237 |
unsigned int buf; rgd = gfs2_blk2rgrpd(sdp, bstart); if (!rgd) { if (gfs2_consist(sdp)) |
382066da2 [GFS2] Casts for ... |
1238 1239 |
fs_err(sdp, "block = %llu ", (unsigned long long)bstart); |
b3b94faa5 [GFS2] The core o... |
1240 1241 |
return NULL; } |
bb8d8a6f5 [GFS2] Fix sign p... |
1242 |
length = rgd->rd_length; |
b3b94faa5 [GFS2] The core o... |
1243 |
|
bb8d8a6f5 [GFS2] Fix sign p... |
1244 |
rgrp_blk = bstart - rgd->rd_data0; |
b3b94faa5 [GFS2] The core o... |
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 |
while (blen--) { for (buf = 0; buf < length; buf++) { bi = rgd->rd_bits + buf; if (rgrp_blk < (bi->bi_start + bi->bi_len) * GFS2_NBBY) break; } gfs2_assert(rgd->rd_sbd, buf < length); buf_blk = rgrp_blk - bi->bi_start * GFS2_NBBY; rgrp_blk++; if (!bi->bi_clone) { bi->bi_clone = kmalloc(bi->bi_bh->b_size, |
dd894be8d [GFS2] Change som... |
1260 |
GFP_NOFS | __GFP_NOFAIL); |
b3b94faa5 [GFS2] The core o... |
1261 1262 1263 1264 |
memcpy(bi->bi_clone + bi->bi_offset, bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); } |
d4e9c4c3b [GFS2] Add an add... |
1265 |
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
b45e41d7d [GFS2] Add extent... |
1266 |
gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset, |
95c8e17f2 GFS2: Dump better... |
1267 |
bi, buf_blk, new_state); |
b3b94faa5 [GFS2] The core o... |
1268 1269 1270 1271 1272 1273 |
} return rgd; } /** |
090109783 GFS2: Improve res... |
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 |
* gfs2_rgrp_dump - print out an rgrp * @seq: The iterator * @gl: The glock in question * */ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl) { const struct gfs2_rgrpd *rgd = gl->gl_object; if (rgd == NULL) return 0; gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u ", (unsigned long long)rgd->rd_addr, rgd->rd_flags, rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes); return 0; } |
6050b9c74 GFS2: Improve err... |
1291 1292 1293 1294 1295 |
static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount ", |
86d006365 GFS2: Whitespace ... |
1296 |
(unsigned long long)rgd->rd_addr); |
6050b9c74 GFS2: Improve err... |
1297 1298 1299 1300 1301 |
fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error "); gfs2_rgrp_dump(NULL, rgd->rd_gl); rgd->rd_flags |= GFS2_RDF_ERROR; } |
090109783 GFS2: Improve res... |
1302 |
/** |
6e87ed0fc GFS2: move toward... |
1303 |
* gfs2_alloc_blocks - Allocate one or more blocks of data and/or a dinode |
1639431a3 [GFS2] Merge gfs2... |
1304 |
* @ip: the inode to allocate the block for |
090109783 GFS2: Improve res... |
1305 |
* @bn: Used to return the starting block number |
6a8099ed5 GFS2: Fix multi-b... |
1306 |
* @ndata: requested number of blocks/extent length (value/result) |
6e87ed0fc GFS2: move toward... |
1307 |
* @dinode: 1 if we're allocating a dinode block, else 0 |
3c5d785ac GFS2: combine gfs... |
1308 |
* @generation: the generation number of the inode |
b3b94faa5 [GFS2] The core o... |
1309 |
* |
090109783 GFS2: Improve res... |
1310 |
* Returns: 0 or error |
b3b94faa5 [GFS2] The core o... |
1311 |
*/ |
6a8099ed5 GFS2: Fix multi-b... |
1312 |
int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, |
6e87ed0fc GFS2: move toward... |
1313 |
bool dinode, u64 *generation) |
b3b94faa5 [GFS2] The core o... |
1314 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
1315 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
d9ba7615b GFS2: Ensure that... |
1316 |
struct buffer_head *dibh; |
9a3f236d4 GFS2: Add a bug t... |
1317 |
struct gfs2_rgrpd *rgd; |
6a8099ed5 GFS2: Fix multi-b... |
1318 1319 |
unsigned int ndata; u32 goal, blk; /* block, within the rgrp scope */ |
3c5d785ac GFS2: combine gfs... |
1320 |
u64 block; /* block, within the file system scope */ |
d9ba7615b GFS2: Ensure that... |
1321 |
int error; |
b3e47ca0c GFS2: split funct... |
1322 |
struct gfs2_bitmap *bi; |
b3b94faa5 [GFS2] The core o... |
1323 |
|
9a3f236d4 GFS2: Add a bug t... |
1324 1325 1326 |
/* Only happens if there is a bug in gfs2, return something distinctive * to ensure that it is noticed. */ |
564e12b11 GFS2: decouple qu... |
1327 |
if (ip->i_res == NULL) |
9a3f236d4 GFS2: Add a bug t... |
1328 |
return -ECANCELED; |
54335b1fc GFS2: Cache the m... |
1329 |
rgd = ip->i_rgd; |
9a3f236d4 GFS2: Add a bug t... |
1330 |
|
3c5d785ac GFS2: combine gfs... |
1331 |
if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) |
ce276b06e [GFS2] Reduce ino... |
1332 |
goal = ip->i_goal - rgd->rd_data0; |
b3b94faa5 [GFS2] The core o... |
1333 |
else |
ac576cc5b [GFS2] Merge the ... |
1334 |
goal = rgd->rd_last_alloc; |
b3b94faa5 [GFS2] The core o... |
1335 |
|
6a8099ed5 GFS2: Fix multi-b... |
1336 |
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi); |
090109783 GFS2: Improve res... |
1337 1338 1339 1340 |
/* Since all blocks are reserved in advance, this shouldn't happen */ if (blk == BFITNOENT) goto rgrp_error; |
b3b94faa5 [GFS2] The core o... |
1341 |
|
6a8099ed5 GFS2: Fix multi-b... |
1342 1343 1344 1345 |
block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks); ndata = *nblocks; if (dinode) ndata--; |
b3e47ca0c GFS2: split funct... |
1346 |
|
3c5d785ac GFS2: combine gfs... |
1347 |
if (!dinode) { |
6a8099ed5 GFS2: Fix multi-b... |
1348 |
ip->i_goal = block + ndata - 1; |
3c5d785ac GFS2: combine gfs... |
1349 1350 1351 1352 1353 1354 1355 1356 1357 |
error = gfs2_meta_inode_buffer(ip, &dibh); if (error == 0) { struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; gfs2_trans_add_bh(ip->i_gl, dibh, 1); di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); brelse(dibh); } |
d9ba7615b GFS2: Ensure that... |
1358 |
} |
6a8099ed5 GFS2: Fix multi-b... |
1359 |
if (rgd->rd_free < *nblocks) |
090109783 GFS2: Improve res... |
1360 |
goto rgrp_error; |
6a8099ed5 GFS2: Fix multi-b... |
1361 |
rgd->rd_free -= *nblocks; |
3c5d785ac GFS2: combine gfs... |
1362 1363 1364 1365 1366 1367 |
if (dinode) { rgd->rd_dinodes++; *generation = rgd->rd_igeneration++; if (*generation == 0) *generation = rgd->rd_igeneration++; } |
b3b94faa5 [GFS2] The core o... |
1368 |
|
d4e9c4c3b [GFS2] Add an add... |
1369 |
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
42d52e381 [GFS2] Combine rg... |
1370 |
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
b3b94faa5 [GFS2] The core o... |
1371 |
|
6a8099ed5 GFS2: Fix multi-b... |
1372 |
gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); |
3c5d785ac GFS2: combine gfs... |
1373 1374 |
if (dinode) gfs2_trans_add_unrevoke(sdp, block, 1); |
6a8099ed5 GFS2: Fix multi-b... |
1375 1376 1377 1378 1379 1380 1381 |
/* * This needs reviewing to see why we cannot do the quota change * at this point in the dinode case. */ if (ndata) gfs2_quota_change(ip, ndata, ip->i_inode.i_uid, |
3c5d785ac GFS2: combine gfs... |
1382 |
ip->i_inode.i_gid); |
b3b94faa5 [GFS2] The core o... |
1383 |
|
6a8099ed5 GFS2: Fix multi-b... |
1384 1385 |
rgd->rd_free_clone -= *nblocks; trace_gfs2_block_alloc(ip, block, *nblocks, |
6e87ed0fc GFS2: move toward... |
1386 |
dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); |
6050b9c74 GFS2: Improve err... |
1387 1388 1389 1390 1391 1392 |
*bn = block; return 0; rgrp_error: gfs2_rgrp_error(rgd); return -EIO; |
b3b94faa5 [GFS2] The core o... |
1393 1394 1395 |
} /** |
46fcb2ed2 GFS2: combine dup... |
1396 |
* __gfs2_free_blocks - free a contiguous run of block(s) |
b3b94faa5 [GFS2] The core o... |
1397 1398 1399 |
* @ip: the inode these blocks are being freed from * @bstart: first block of a run of contiguous blocks * @blen: the length of the block run |
46fcb2ed2 GFS2: combine dup... |
1400 |
* @meta: 1 if the blocks represent metadata |
b3b94faa5 [GFS2] The core o... |
1401 1402 |
* */ |
46fcb2ed2 GFS2: combine dup... |
1403 |
void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta) |
b3b94faa5 [GFS2] The core o... |
1404 |
{ |
feaa7bba0 [GFS2] Fix unlink... |
1405 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
b3b94faa5 [GFS2] The core o... |
1406 1407 1408 1409 1410 |
struct gfs2_rgrpd *rgd; rgd = rgblk_free(sdp, bstart, blen, GFS2_BLKST_FREE); if (!rgd) return; |
63997775b GFS2: Add tracepo... |
1411 |
trace_gfs2_block_alloc(ip, bstart, blen, GFS2_BLKST_FREE); |
cfc8b5492 GFS2: Move rg_fre... |
1412 |
rgd->rd_free += blen; |
b3b94faa5 [GFS2] The core o... |
1413 |
|
d4e9c4c3b [GFS2] Add an add... |
1414 |
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
42d52e381 [GFS2] Combine rg... |
1415 |
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
b3b94faa5 [GFS2] The core o... |
1416 |
|
6d3117b41 GFS2: Wipe direct... |
1417 |
/* Directories keep their data in the metadata address space */ |
46fcb2ed2 GFS2: combine dup... |
1418 |
if (meta || ip->i_depth) |
6d3117b41 GFS2: Wipe direct... |
1419 |
gfs2_meta_wipe(ip, bstart, blen); |
4c16c36ad GFS2: deallocatio... |
1420 |
} |
b3b94faa5 [GFS2] The core o... |
1421 |
|
4c16c36ad GFS2: deallocatio... |
1422 |
/** |
4c16c36ad GFS2: deallocatio... |
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 |
* gfs2_free_meta - free a contiguous run of data block(s) * @ip: the inode these blocks are being freed from * @bstart: first block of a run of contiguous blocks * @blen: the length of the block run * */ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
46fcb2ed2 GFS2: combine dup... |
1433 |
__gfs2_free_blocks(ip, bstart, blen, 1); |
b3b94faa5 [GFS2] The core o... |
1434 |
gfs2_statfs_change(sdp, 0, +blen, 0); |
2933f9254 [GFS2] Shrink gfs... |
1435 |
gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid); |
b3b94faa5 [GFS2] The core o... |
1436 |
} |
feaa7bba0 [GFS2] Fix unlink... |
1437 1438 1439 1440 1441 |
void gfs2_unlink_di(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_rgrpd *rgd; |
dbb7cae2a [GFS2] Clean up i... |
1442 |
u64 blkno = ip->i_no_addr; |
feaa7bba0 [GFS2] Fix unlink... |
1443 1444 1445 1446 |
rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); if (!rgd) return; |
63997775b GFS2: Add tracepo... |
1447 |
trace_gfs2_block_alloc(ip, blkno, 1, GFS2_BLKST_UNLINKED); |
feaa7bba0 [GFS2] Fix unlink... |
1448 |
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
42d52e381 [GFS2] Combine rg... |
1449 |
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
feaa7bba0 [GFS2] Fix unlink... |
1450 |
} |
cd915493f [GFS2] Change all... |
1451 |
static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) |
b3b94faa5 [GFS2] The core o... |
1452 1453 1454 1455 1456 1457 1458 1459 |
{ struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_rgrpd *tmp_rgd; tmp_rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_FREE); if (!tmp_rgd) return; gfs2_assert_withdraw(sdp, rgd == tmp_rgd); |
73f749483 GFS2: Banish stru... |
1460 |
if (!rgd->rd_dinodes) |
b3b94faa5 [GFS2] The core o... |
1461 |
gfs2_consist_rgrpd(rgd); |
73f749483 GFS2: Banish stru... |
1462 |
rgd->rd_dinodes--; |
cfc8b5492 GFS2: Move rg_fre... |
1463 |
rgd->rd_free++; |
b3b94faa5 [GFS2] The core o... |
1464 |
|
d4e9c4c3b [GFS2] Add an add... |
1465 |
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
42d52e381 [GFS2] Combine rg... |
1466 |
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
b3b94faa5 [GFS2] The core o... |
1467 1468 |
gfs2_statfs_change(sdp, 0, +1, -1); |
b3b94faa5 [GFS2] The core o... |
1469 |
} |
b3b94faa5 [GFS2] The core o... |
1470 1471 1472 |
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) { |
dbb7cae2a [GFS2] Clean up i... |
1473 |
gfs2_free_uninit_di(rgd, ip->i_no_addr); |
63997775b GFS2: Add tracepo... |
1474 |
trace_gfs2_block_alloc(ip, ip->i_no_addr, 1, GFS2_BLKST_FREE); |
2933f9254 [GFS2] Shrink gfs... |
1475 |
gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); |
dbb7cae2a [GFS2] Clean up i... |
1476 |
gfs2_meta_wipe(ip, ip->i_no_addr, 1); |
b3b94faa5 [GFS2] The core o... |
1477 1478 1479 |
} /** |
acf7e2444 GFS2: Be extra ca... |
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 |
* gfs2_check_blk_type - Check the type of a block * @sdp: The superblock * @no_addr: The block number to check * @type: The block type we are looking for * * Returns: 0 if the block type matches the expected type * -ESTALE if it doesn't match * or -ve errno if something went wrong while checking */ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) { struct gfs2_rgrpd *rgd; |
8339ee543 GFS2: Make resour... |
1493 |
struct gfs2_holder rgd_gh; |
acf7e2444 GFS2: Be extra ca... |
1494 |
int error; |
8339ee543 GFS2: Make resour... |
1495 1496 1497 |
error = gfs2_rindex_update(sdp); if (error) return error; |
acf7e2444 GFS2: Be extra ca... |
1498 1499 1500 1501 |
error = -EINVAL; rgd = gfs2_blk2rgrpd(sdp, no_addr); if (!rgd) |
8339ee543 GFS2: Make resour... |
1502 |
goto fail; |
acf7e2444 GFS2: Be extra ca... |
1503 1504 1505 |
error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); if (error) |
8339ee543 GFS2: Make resour... |
1506 |
goto fail; |
acf7e2444 GFS2: Be extra ca... |
1507 1508 1509 1510 1511 |
if (gfs2_get_block_type(rgd, no_addr) != type) error = -ESTALE; gfs2_glock_dq_uninit(&rgd_gh); |
acf7e2444 GFS2: Be extra ca... |
1512 1513 1514 1515 1516 |
fail: return error; } /** |
b3b94faa5 [GFS2] The core o... |
1517 |
* gfs2_rlist_add - add a RG to a list of RGs |
70b0c3656 GFS2: Use cached ... |
1518 |
* @ip: the inode |
b3b94faa5 [GFS2] The core o... |
1519 1520 1521 1522 1523 1524 1525 1526 |
* @rlist: the list of resource groups * @block: the block * * Figure out what RG a block belongs to and add that RG to the list * * FIXME: Don't use NOFAIL * */ |
70b0c3656 GFS2: Use cached ... |
1527 |
void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist, |
cd915493f [GFS2] Change all... |
1528 |
u64 block) |
b3b94faa5 [GFS2] The core o... |
1529 |
{ |
70b0c3656 GFS2: Use cached ... |
1530 |
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
b3b94faa5 [GFS2] The core o... |
1531 1532 1533 1534 1535 1536 1537 |
struct gfs2_rgrpd *rgd; struct gfs2_rgrpd **tmp; unsigned int new_space; unsigned int x; if (gfs2_assert_warn(sdp, !rlist->rl_ghs)) return; |
70b0c3656 GFS2: Use cached ... |
1538 1539 1540 1541 |
if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, block)) rgd = ip->i_rgd; else rgd = gfs2_blk2rgrpd(sdp, block); |
b3b94faa5 [GFS2] The core o... |
1542 |
if (!rgd) { |
70b0c3656 GFS2: Use cached ... |
1543 1544 |
fs_err(sdp, "rlist_add: no rgrp for block %llu ", (unsigned long long)block); |
b3b94faa5 [GFS2] The core o... |
1545 1546 |
return; } |
70b0c3656 GFS2: Use cached ... |
1547 |
ip->i_rgd = rgd; |
b3b94faa5 [GFS2] The core o... |
1548 1549 1550 1551 1552 1553 1554 1555 1556 |
for (x = 0; x < rlist->rl_rgrps; x++) if (rlist->rl_rgd[x] == rgd) return; if (rlist->rl_rgrps == rlist->rl_space) { new_space = rlist->rl_space + 10; tmp = kcalloc(new_space, sizeof(struct gfs2_rgrpd *), |
dd894be8d [GFS2] Change som... |
1557 |
GFP_NOFS | __GFP_NOFAIL); |
b3b94faa5 [GFS2] The core o... |
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 |
if (rlist->rl_rgd) { memcpy(tmp, rlist->rl_rgd, rlist->rl_space * sizeof(struct gfs2_rgrpd *)); kfree(rlist->rl_rgd); } rlist->rl_space = new_space; rlist->rl_rgd = tmp; } rlist->rl_rgd[rlist->rl_rgrps++] = rgd; } /** * gfs2_rlist_alloc - all RGs have been added to the rlist, now allocate * and initialize an array of glock holders for them * @rlist: the list of resource groups * @state: the lock state to acquire the RG lock in * @flags: the modifier flags for the holder structures * * FIXME: Don't use NOFAIL * */ |
fe6c991c5 [GFS2] Get rid of... |
1582 |
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state) |
b3b94faa5 [GFS2] The core o... |
1583 1584 1585 1586 |
{ unsigned int x; rlist->rl_ghs = kcalloc(rlist->rl_rgrps, sizeof(struct gfs2_holder), |
dd894be8d [GFS2] Change som... |
1587 |
GFP_NOFS | __GFP_NOFAIL); |
b3b94faa5 [GFS2] The core o... |
1588 1589 |
for (x = 0; x < rlist->rl_rgrps; x++) gfs2_holder_init(rlist->rl_rgd[x]->rd_gl, |
fe6c991c5 [GFS2] Get rid of... |
1590 |
state, 0, |
b3b94faa5 [GFS2] The core o... |
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 |
&rlist->rl_ghs[x]); } /** * gfs2_rlist_free - free a resource group list * @list: the list of resource groups * */ void gfs2_rlist_free(struct gfs2_rgrp_list *rlist) { unsigned int x; kfree(rlist->rl_rgd); if (rlist->rl_ghs) { for (x = 0; x < rlist->rl_rgrps; x++) gfs2_holder_uninit(&rlist->rl_ghs[x]); kfree(rlist->rl_ghs); } } |