Blame view
fs/reiserfs/bitmap.c
36.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 |
/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ /* Reiserfs block (de)allocator, bitmap-based. */ |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 8 9 10 |
#include <linux/time.h> #include <linux/reiserfs_fs.h> #include <linux/errno.h> #include <linux/buffer_head.h> #include <linux/kernel.h> #include <linux/pagemap.h> |
6f01046b3 [PATCH] reiserfs:... |
11 |
#include <linux/vmalloc.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <linux/reiserfs_fs_sb.h> #include <linux/reiserfs_fs_i.h> #include <linux/quotaops.h> #define PREALLOCATION_SIZE 9 /* different reiserfs block allocator options */ #define SB_ALLOC_OPTS(s) (REISERFS_SB(s)->s_alloc_options.bits) #define _ALLOC_concentrating_formatted_nodes 0 #define _ALLOC_displacing_large_files 1 #define _ALLOC_displacing_new_packing_localities 2 #define _ALLOC_old_hashed_relocation 3 #define _ALLOC_new_hashed_relocation 4 #define _ALLOC_skip_busy 5 #define _ALLOC_displace_based_on_dirid 6 #define _ALLOC_hashed_formatted_nodes 7 #define _ALLOC_old_way 8 #define _ALLOC_hundredth_slices 9 #define _ALLOC_dirid_groups 10 #define _ALLOC_oid_groups 11 #define _ALLOC_packing_groups 12 #define concentrating_formatted_nodes(s) test_bit(_ALLOC_concentrating_formatted_nodes, &SB_ALLOC_OPTS(s)) #define displacing_large_files(s) test_bit(_ALLOC_displacing_large_files, &SB_ALLOC_OPTS(s)) #define displacing_new_packing_localities(s) test_bit(_ALLOC_displacing_new_packing_localities, &SB_ALLOC_OPTS(s)) #define SET_OPTION(optname) \ do { \ |
1d889d995 reiserfs: make so... |
42 43 |
reiserfs_info(s, "block allocator option \"%s\" is set", #optname); \ set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \ |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 |
} while(0) #define TEST_OPTION(optname, s) \ test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)) |
bd4c625c0 reiserfs: run scr... |
47 |
static inline void get_bit_address(struct super_block *s, |
3ee166704 reiserfs: fix usa... |
48 49 50 |
b_blocknr_t block, unsigned int *bmap_nr, unsigned int *offset) |
1da177e4c Linux-2.6.12-rc2 |
51 |
{ |
bd4c625c0 reiserfs: run scr... |
52 53 |
/* It is in the bitmap block number equal to the block * number divided by the number of bits in a block. */ |
e1fabd3cc [PATCH] reiserfs:... |
54 |
*bmap_nr = block >> (s->s_blocksize_bits + 3); |
bd4c625c0 reiserfs: run scr... |
55 56 |
/* Within that bitmap block it is located at bit offset *offset. */ *offset = block & ((s->s_blocksize << 3) - 1); |
1da177e4c Linux-2.6.12-rc2 |
57 |
} |
bd4c625c0 reiserfs: run scr... |
58 |
int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) |
1da177e4c Linux-2.6.12-rc2 |
59 |
{ |
3ee166704 reiserfs: fix usa... |
60 |
unsigned int bmap, offset; |
cb680c1be reiserfs: ignore ... |
61 |
unsigned int bmap_count = reiserfs_bmap_count(s); |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
bd4c625c0 reiserfs: run scr... |
63 |
if (block == 0 || block >= SB_BLOCK_COUNT(s)) { |
0030b6457 reiserfs: use rei... |
64 65 66 |
reiserfs_error(s, "vs-4010", "block number is out of range %lu (%u)", block, SB_BLOCK_COUNT(s)); |
bd4c625c0 reiserfs: run scr... |
67 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
68 |
} |
1da177e4c Linux-2.6.12-rc2 |
69 |
|
e1fabd3cc [PATCH] reiserfs:... |
70 71 72 73 74 75 76 |
get_bit_address(s, block, &bmap, &offset); /* Old format filesystem? Unlikely, but the bitmaps are all up front so * we need to account for it. */ if (unlikely(test_bit(REISERFS_OLD_FORMAT, &(REISERFS_SB(s)->s_properties)))) { b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1; |
cb680c1be reiserfs: ignore ... |
77 78 |
if (block >= bmap1 && block <= bmap1 + bmap_count) { |
0030b6457 reiserfs: use rei... |
79 80 81 |
reiserfs_error(s, "vs-4019", "bitmap block %lu(%u) " "can't be freed or reused", block, bmap_count); |
e1fabd3cc [PATCH] reiserfs:... |
82 83 84 85 |
return 0; } } else { if (offset == 0) { |
0030b6457 reiserfs: use rei... |
86 87 88 |
reiserfs_error(s, "vs-4020", "bitmap block %lu(%u) " "can't be freed or reused", block, bmap_count); |
bd4c625c0 reiserfs: run scr... |
89 90 |
return 0; } |
e1fabd3cc [PATCH] reiserfs:... |
91 |
} |
1da177e4c Linux-2.6.12-rc2 |
92 |
|
cb680c1be reiserfs: ignore ... |
93 |
if (bmap >= bmap_count) { |
0030b6457 reiserfs: use rei... |
94 95 96 |
reiserfs_error(s, "vs-4030", "bitmap for requested block " "is out of range: block=%lu, bitmap_nr=%u", block, bmap); |
bd4c625c0 reiserfs: run scr... |
97 98 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
99 |
|
bd4c625c0 reiserfs: run scr... |
100 |
if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) { |
0030b6457 reiserfs: use rei... |
101 102 |
reiserfs_error(s, "vs-4050", "this is root block (%u), " "it must be busy", SB_ROOT_BLOCK(s)); |
bd4c625c0 reiserfs: run scr... |
103 104 105 106 |
return 0; } return 1; |
1da177e4c Linux-2.6.12-rc2 |
107 |
} |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 |
/* searches in journal structures for a given block number (bmap, off). If block is found in reiserfs journal it suggests next free block candidate to test. */ |
3ee166704 reiserfs: fix usa... |
111 112 |
static inline int is_block_in_journal(struct super_block *s, unsigned int bmap, int off, int *next) |
1da177e4c Linux-2.6.12-rc2 |
113 |
{ |
bd4c625c0 reiserfs: run scr... |
114 115 116 117 118 119 120 121 122 123 124 125 |
b_blocknr_t tmp; if (reiserfs_in_journal(s, bmap, off, 1, &tmp)) { if (tmp) { /* hint supplied */ *next = tmp; PROC_INFO_INC(s, scan_bitmap.in_journal_hint); } else { (*next) = off + 1; /* inc offset to avoid looping. */ PROC_INFO_INC(s, scan_bitmap.in_journal_nohint); } PROC_INFO_INC(s, scan_bitmap.retry); return 1; |
1da177e4c Linux-2.6.12-rc2 |
126 |
} |
bd4c625c0 reiserfs: run scr... |
127 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
128 129 130 131 |
} /* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap * block; */ |
bd4c625c0 reiserfs: run scr... |
132 |
static int scan_bitmap_block(struct reiserfs_transaction_handle *th, |
3ee166704 reiserfs: fix usa... |
133 134 |
unsigned int bmap_n, int *beg, int boundary, int min, int max, int unfm) |
1da177e4c Linux-2.6.12-rc2 |
135 |
{ |
bd4c625c0 reiserfs: run scr... |
136 137 |
struct super_block *s = th->t_super; struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; |
0b3dc17bc [PATCH] reiserfs:... |
138 |
struct buffer_head *bh; |
bd4c625c0 reiserfs: run scr... |
139 140 |
int end, next; int org = *beg; |
1da177e4c Linux-2.6.12-rc2 |
141 |
|
bd4c625c0 reiserfs: run scr... |
142 |
BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
143 |
|
cb680c1be reiserfs: ignore ... |
144 145 |
RFALSE(bmap_n >= reiserfs_bmap_count(s), "Bitmap %u is out of " "range (0..%u)", bmap_n, reiserfs_bmap_count(s) - 1); |
bd4c625c0 reiserfs: run scr... |
146 |
PROC_INFO_INC(s, scan_bitmap.bmap); |
1da177e4c Linux-2.6.12-rc2 |
147 148 149 150 |
/* this is unclear and lacks comments, explain how journal bitmaps work here for the reader. Convey a sense of the design here. What is a window? */ /* - I mean `a window of zero bits' as in description of this function - Zam. */ |
1da177e4c Linux-2.6.12-rc2 |
151 |
|
bd4c625c0 reiserfs: run scr... |
152 |
if (!bi) { |
0030b6457 reiserfs: use rei... |
153 154 |
reiserfs_error(s, "jdm-4055", "NULL bitmap info pointer " "for bitmap %d", bmap_n); |
bd4c625c0 reiserfs: run scr... |
155 156 |
return 0; } |
0b3dc17bc [PATCH] reiserfs:... |
157 |
|
5065227b4 [PATCH] reiserfs:... |
158 159 160 |
bh = reiserfs_read_bitmap_block(s, bmap_n); if (bh == NULL) return 0; |
1da177e4c Linux-2.6.12-rc2 |
161 |
|
bd4c625c0 reiserfs: run scr... |
162 163 |
while (1) { cont: |
0b3dc17bc [PATCH] reiserfs:... |
164 165 |
if (bi->free_count < min) { brelse(bh); |
bd4c625c0 reiserfs: run scr... |
166 |
return 0; // No free blocks in this bitmap |
0b3dc17bc [PATCH] reiserfs:... |
167 |
} |
bd4c625c0 reiserfs: run scr... |
168 |
|
3ad2f3fbb tree-wide: Assort... |
169 |
/* search for a first zero bit -- beginning of a window */ |
bd4c625c0 reiserfs: run scr... |
170 |
*beg = reiserfs_find_next_zero_le_bit |
0b3dc17bc [PATCH] reiserfs:... |
171 |
((unsigned long *)(bh->b_data), boundary, *beg); |
bd4c625c0 reiserfs: run scr... |
172 173 174 |
if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block * cannot contain a zero window of minimum size */ |
0b3dc17bc [PATCH] reiserfs:... |
175 |
brelse(bh); |
bd4c625c0 reiserfs: run scr... |
176 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
177 |
} |
1da177e4c Linux-2.6.12-rc2 |
178 |
|
bd4c625c0 reiserfs: run scr... |
179 180 181 182 183 |
if (unfm && is_block_in_journal(s, bmap_n, *beg, beg)) continue; /* first zero bit found; we check next bits */ for (end = *beg + 1;; end++) { if (end >= *beg + max || end >= boundary |
0b3dc17bc [PATCH] reiserfs:... |
184 |
|| reiserfs_test_le_bit(end, bh->b_data)) { |
bd4c625c0 reiserfs: run scr... |
185 186 187 188 189 190 191 192 |
next = end; break; } /* finding the other end of zero bit window requires looking into journal structures (in * case of searching for free blocks for unformatted nodes) */ if (unfm && is_block_in_journal(s, bmap_n, end, &next)) break; } |
1da177e4c Linux-2.6.12-rc2 |
193 |
|
bd4c625c0 reiserfs: run scr... |
194 195 196 197 |
/* now (*beg) points to beginning of zero bits window, * (end) points to one bit after the window end */ if (end - *beg >= min) { /* it seems we have found window of proper size */ int i; |
0b3dc17bc [PATCH] reiserfs:... |
198 |
reiserfs_prepare_for_journal(s, bh, 1); |
bd4c625c0 reiserfs: run scr... |
199 200 201 202 |
/* try to set all blocks used checking are they still free */ for (i = *beg; i < end; i++) { /* It seems that we should not check in journal again. */ if (reiserfs_test_and_set_le_bit |
0b3dc17bc [PATCH] reiserfs:... |
203 |
(i, bh->b_data)) { |
bd4c625c0 reiserfs: run scr... |
204 205 206 207 208 209 210 211 212 213 |
/* bit was set by another process * while we slept in prepare_for_journal() */ PROC_INFO_INC(s, scan_bitmap.stolen); if (i >= *beg + min) { /* we can continue with smaller set of allocated blocks, * if length of this set is more or equal to `min' */ end = i; break; } /* otherwise we clear all bit were set ... */ while (--i >= *beg) |
0c2fd1bfb reiserfs: use pro... |
214 |
reiserfs_clear_le_bit |
0b3dc17bc [PATCH] reiserfs:... |
215 216 |
(i, bh->b_data); reiserfs_restore_prepared_buffer(s, bh); |
bd4c625c0 reiserfs: run scr... |
217 218 219 220 221 222 |
*beg = org; /* ... and search again in current block from beginning */ goto cont; } } bi->free_count -= (end - *beg); |
0b3dc17bc [PATCH] reiserfs:... |
223 224 |
journal_mark_dirty(th, s, bh); brelse(bh); |
bd4c625c0 reiserfs: run scr... |
225 226 227 228 229 230 231 232 233 234 235 |
/* free block count calculation */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (end - *beg)); journal_mark_dirty(th, s, SB_BUFFER_WITH_SB(s)); return end - (*beg); } else { *beg = next; } |
1da177e4c Linux-2.6.12-rc2 |
236 |
} |
1da177e4c Linux-2.6.12-rc2 |
237 |
} |
bd4c625c0 reiserfs: run scr... |
238 239 240 241 242 243 244 245 246 247 248 |
static int bmap_hash_id(struct super_block *s, u32 id) { char *hash_in = NULL; unsigned long hash; unsigned bm; if (id <= 2) { bm = 1; } else { hash_in = (char *)(&id); hash = keyed_hash(hash_in, 4); |
cb680c1be reiserfs: ignore ... |
249 |
bm = hash % reiserfs_bmap_count(s); |
bd4c625c0 reiserfs: run scr... |
250 251 252 253 |
if (!bm) bm = 1; } /* this can only be true when SB_BMAP_NR = 1 */ |
cb680c1be reiserfs: ignore ... |
254 |
if (bm >= reiserfs_bmap_count(s)) |
bd4c625c0 reiserfs: run scr... |
255 256 |
bm = 0; return bm; |
1da177e4c Linux-2.6.12-rc2 |
257 258 259 260 261 262 |
} /* * hashes the id and then returns > 0 if the block group for the * corresponding hash is full */ |
bd4c625c0 reiserfs: run scr... |
263 264 |
static inline int block_group_used(struct super_block *s, u32 id) { |
5065227b4 [PATCH] reiserfs:... |
265 266 267 268 269 |
int bm = bmap_hash_id(s, id); struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm]; /* If we don't have cached information on this bitmap block, we're * going to have to load it later anyway. Loading it here allows us |
c78bad11f fs/: Spelling fixes |
270 |
* to make a better decision. This favors long-term performance gain |
5065227b4 [PATCH] reiserfs:... |
271 272 |
* with a better on-disk layout vs. a short term gain of skipping the * read and potentially having a bad placement. */ |
4d20851d3 reiserfs: remove ... |
273 |
if (info->free_count == UINT_MAX) { |
5065227b4 [PATCH] reiserfs:... |
274 275 276 277 278 |
struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm); brelse(bh); } if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) { |
bd4c625c0 reiserfs: run scr... |
279 280 281 |
return 0; } return 1; |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 285 286 |
} /* * the packing is returned in disk byte order */ |
bd4c625c0 reiserfs: run scr... |
287 |
__le32 reiserfs_choose_packing(struct inode * dir) |
3e8962be9 [PATCH] reiserfs ... |
288 |
{ |
bd4c625c0 reiserfs: run scr... |
289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
__le32 packing; if (TEST_OPTION(packing_groups, dir->i_sb)) { u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id); /* * some versions of reiserfsck expect packing locality 1 to be * special */ if (parent_dir == 1 || block_group_used(dir->i_sb, parent_dir)) packing = INODE_PKEY(dir)->k_objectid; else packing = INODE_PKEY(dir)->k_dir_id; } else packing = INODE_PKEY(dir)->k_objectid; return packing; |
1da177e4c Linux-2.6.12-rc2 |
303 |
} |
bd4c625c0 reiserfs: run scr... |
304 |
|
1da177e4c Linux-2.6.12-rc2 |
305 306 |
/* Tries to find contiguous zero bit window (given size) in given region of * bitmap and place new blocks there. Returns number of allocated blocks. */ |
bd4c625c0 reiserfs: run scr... |
307 308 |
static int scan_bitmap(struct reiserfs_transaction_handle *th, b_blocknr_t * start, b_blocknr_t finish, |
3ee166704 reiserfs: fix usa... |
309 |
int min, int max, int unfm, sector_t file_block) |
1da177e4c Linux-2.6.12-rc2 |
310 |
{ |
bd4c625c0 reiserfs: run scr... |
311 312 313 314 |
int nr_allocated = 0; struct super_block *s = th->t_super; /* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr * - Hans, it is not a block number - Zam. */ |
3ee166704 reiserfs: fix usa... |
315 316 317 |
unsigned int bm, off; unsigned int end_bm, end_off; unsigned int off_max = s->s_blocksize << 3; |
bd4c625c0 reiserfs: run scr... |
318 319 320 321 322 323 324 325 326 |
BUG_ON(!th->t_trans_id); PROC_INFO_INC(s, scan_bitmap.call); if (SB_FREE_BLOCKS(s) <= 0) return 0; // No point in looking for more free blocks get_bit_address(s, *start, &bm, &off); get_bit_address(s, finish, &end_bm, &end_off); |
cb680c1be reiserfs: ignore ... |
327 |
if (bm > reiserfs_bmap_count(s)) |
bd4c625c0 reiserfs: run scr... |
328 |
return 0; |
cb680c1be reiserfs: ignore ... |
329 330 |
if (end_bm > reiserfs_bmap_count(s)) end_bm = reiserfs_bmap_count(s); |
bd4c625c0 reiserfs: run scr... |
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
/* When the bitmap is more than 10% free, anyone can allocate. * When it's less than 10% free, only files that already use the * bitmap are allowed. Once we pass 80% full, this restriction * is lifted. * * We do this so that files that grow later still have space close to * their original allocation. This improves locality, and presumably * performance as a result. * * This is only an allocation policy and does not make up for getting a * bad hint. Decent hinting must be implemented for this to work well. */ if (TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s) / 20) { for (; bm < end_bm; bm++, off = 0) { if ((off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10) nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm); if (nr_allocated) goto ret; } /* we know from above that start is a reasonable number */ get_bit_address(s, *start, &bm, &off); } for (; bm < end_bm; bm++, off = 0) { nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm); if (nr_allocated) goto ret; } nr_allocated = scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm); ret: *start = bm * off_max + off; return nr_allocated; |
1da177e4c Linux-2.6.12-rc2 |
373 374 |
} |
bd4c625c0 reiserfs: run scr... |
375 376 377 |
static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block, int for_unformatted) |
1da177e4c Linux-2.6.12-rc2 |
378 |
{ |
bd4c625c0 reiserfs: run scr... |
379 380 |
struct super_block *s = th->t_super; struct reiserfs_super_block *rs; |
0b3dc17bc [PATCH] reiserfs:... |
381 |
struct buffer_head *sbh, *bmbh; |
bd4c625c0 reiserfs: run scr... |
382 |
struct reiserfs_bitmap_info *apbi; |
3ee166704 reiserfs: fix usa... |
383 |
unsigned int nr, offset; |
1da177e4c Linux-2.6.12-rc2 |
384 |
|
bd4c625c0 reiserfs: run scr... |
385 |
BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
386 |
|
bd4c625c0 reiserfs: run scr... |
387 |
PROC_INFO_INC(s, free_block); |
1da177e4c Linux-2.6.12-rc2 |
388 |
|
bd4c625c0 reiserfs: run scr... |
389 390 391 |
rs = SB_DISK_SUPER_BLOCK(s); sbh = SB_BUFFER_WITH_SB(s); apbi = SB_AP_BITMAP(s); |
1da177e4c Linux-2.6.12-rc2 |
392 |
|
bd4c625c0 reiserfs: run scr... |
393 |
get_bit_address(s, block, &nr, &offset); |
1da177e4c Linux-2.6.12-rc2 |
394 |
|
cb680c1be reiserfs: ignore ... |
395 |
if (nr >= reiserfs_bmap_count(s)) { |
0030b6457 reiserfs: use rei... |
396 397 |
reiserfs_error(s, "vs-4075", "block %lu is out of range", block); |
bd4c625c0 reiserfs: run scr... |
398 399 |
return; } |
5065227b4 [PATCH] reiserfs:... |
400 401 402 |
bmbh = reiserfs_read_bitmap_block(s, nr); if (!bmbh) return; |
0b3dc17bc [PATCH] reiserfs:... |
403 404 |
reiserfs_prepare_for_journal(s, bmbh, 1); |
bd4c625c0 reiserfs: run scr... |
405 406 |
/* clear bit for the given block in bit map */ |
0b3dc17bc [PATCH] reiserfs:... |
407 |
if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) { |
0030b6457 reiserfs: use rei... |
408 409 |
reiserfs_error(s, "vs-4080", "block %lu: bit already cleared", block); |
bd4c625c0 reiserfs: run scr... |
410 411 |
} apbi[nr].free_count++; |
0b3dc17bc [PATCH] reiserfs:... |
412 413 |
journal_mark_dirty(th, s, bmbh); brelse(bmbh); |
bd4c625c0 reiserfs: run scr... |
414 415 416 417 418 419 420 |
reiserfs_prepare_for_journal(s, sbh, 1); /* update super block */ set_sb_free_blocks(rs, sb_free_blocks(rs) + 1); journal_mark_dirty(th, s, sbh); if (for_unformatted) |
5dd4056db dquot: cleanup sp... |
421 |
dquot_free_block_nodirty(inode, 1); |
1da177e4c Linux-2.6.12-rc2 |
422 |
} |
bd4c625c0 reiserfs: run scr... |
423 424 425 |
void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block, int for_unformatted) |
1da177e4c Linux-2.6.12-rc2 |
426 |
{ |
bd4c625c0 reiserfs: run scr... |
427 |
struct super_block *s = th->t_super; |
bd4c625c0 reiserfs: run scr... |
428 |
BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
429 |
|
bd4c625c0 reiserfs: run scr... |
430 |
RFALSE(!s, "vs-4061: trying to free block on nonexistent device"); |
d4c3d19d0 reiserfs: use is_... |
431 432 433 434 |
if (!is_reusable(s, block, 1)) return; if (block > sb_block_count(REISERFS_SB(s)->s_rs)) { |
0030b6457 reiserfs: use rei... |
435 |
reiserfs_error(th->t_super, "bitmap-4072", |
d4c3d19d0 reiserfs: use is_... |
436 437 438 439 440 |
"Trying to free block outside file system " "boundaries (%lu > %lu)", block, sb_block_count(REISERFS_SB(s)->s_rs)); return; } |
bd4c625c0 reiserfs: run scr... |
441 442 443 |
/* mark it before we clear it, just in case */ journal_mark_freed(th, s, block); _reiserfs_free_block(th, inode, block, for_unformatted); |
1da177e4c Linux-2.6.12-rc2 |
444 445 446 |
} /* preallocated blocks don't need to be run through journal_mark_freed */ |
bd4c625c0 reiserfs: run scr... |
447 448 449 |
static void reiserfs_free_prealloc_block(struct reiserfs_transaction_handle *th, struct inode *inode, b_blocknr_t block) { |
d4c3d19d0 reiserfs: use is_... |
450 |
BUG_ON(!th->t_trans_id); |
bd4c625c0 reiserfs: run scr... |
451 452 |
RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device"); |
d4c3d19d0 reiserfs: use is_... |
453 454 |
if (!is_reusable(th->t_super, block, 1)) return; |
bd4c625c0 reiserfs: run scr... |
455 |
_reiserfs_free_block(th, inode, block, 1); |
1da177e4c Linux-2.6.12-rc2 |
456 |
} |
bd4c625c0 reiserfs: run scr... |
457 458 |
static void __discard_prealloc(struct reiserfs_transaction_handle *th, struct reiserfs_inode_info *ei) |
1da177e4c Linux-2.6.12-rc2 |
459 |
{ |
bd4c625c0 reiserfs: run scr... |
460 461 462 463 |
unsigned long save = ei->i_prealloc_block; int dirty = 0; struct inode *inode = &ei->vfs_inode; BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
464 |
#ifdef CONFIG_REISERFS_CHECK |
bd4c625c0 reiserfs: run scr... |
465 |
if (ei->i_prealloc_count < 0) |
0030b6457 reiserfs: use rei... |
466 467 |
reiserfs_error(th->t_super, "zam-4001", "inode has negative prealloc blocks count."); |
1da177e4c Linux-2.6.12-rc2 |
468 |
#endif |
bd4c625c0 reiserfs: run scr... |
469 470 471 472 473 474 475 476 477 478 |
while (ei->i_prealloc_count > 0) { reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block); ei->i_prealloc_block++; ei->i_prealloc_count--; dirty = 1; } if (dirty) reiserfs_update_sd(th, inode); ei->i_prealloc_block = save; list_del_init(&(ei->i_prealloc_list)); |
1da177e4c Linux-2.6.12-rc2 |
479 480 481 |
} /* FIXME: It should be inline function */ |
bd4c625c0 reiserfs: run scr... |
482 483 |
void reiserfs_discard_prealloc(struct reiserfs_transaction_handle *th, struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
484 |
{ |
bd4c625c0 reiserfs: run scr... |
485 486 487 488 |
struct reiserfs_inode_info *ei = REISERFS_I(inode); BUG_ON(!th->t_trans_id); if (ei->i_prealloc_count) __discard_prealloc(th, ei); |
1da177e4c Linux-2.6.12-rc2 |
489 |
} |
bd4c625c0 reiserfs: run scr... |
490 |
void reiserfs_discard_all_prealloc(struct reiserfs_transaction_handle *th) |
1da177e4c Linux-2.6.12-rc2 |
491 |
{ |
bd4c625c0 reiserfs: run scr... |
492 |
struct list_head *plist = &SB_JOURNAL(th->t_super)->j_prealloc_list; |
1da177e4c Linux-2.6.12-rc2 |
493 |
|
bd4c625c0 reiserfs: run scr... |
494 |
BUG_ON(!th->t_trans_id); |
1da177e4c Linux-2.6.12-rc2 |
495 |
|
bd4c625c0 reiserfs: run scr... |
496 497 498 499 |
while (!list_empty(plist)) { struct reiserfs_inode_info *ei; ei = list_entry(plist->next, struct reiserfs_inode_info, i_prealloc_list); |
1da177e4c Linux-2.6.12-rc2 |
500 |
#ifdef CONFIG_REISERFS_CHECK |
bd4c625c0 reiserfs: run scr... |
501 |
if (!ei->i_prealloc_count) { |
0030b6457 reiserfs: use rei... |
502 503 504 |
reiserfs_error(th->t_super, "zam-4001", "inode is in prealloc list but has " "no preallocated blocks."); |
bd4c625c0 reiserfs: run scr... |
505 |
} |
1da177e4c Linux-2.6.12-rc2 |
506 |
#endif |
bd4c625c0 reiserfs: run scr... |
507 508 |
__discard_prealloc(th, ei); } |
1da177e4c Linux-2.6.12-rc2 |
509 |
} |
bd4c625c0 reiserfs: run scr... |
510 |
void reiserfs_init_alloc_options(struct super_block *s) |
1da177e4c Linux-2.6.12-rc2 |
511 |
{ |
bd4c625c0 reiserfs: run scr... |
512 513 514 |
set_bit(_ALLOC_skip_busy, &SB_ALLOC_OPTS(s)); set_bit(_ALLOC_dirid_groups, &SB_ALLOC_OPTS(s)); set_bit(_ALLOC_packing_groups, &SB_ALLOC_OPTS(s)); |
1da177e4c Linux-2.6.12-rc2 |
515 516 517 |
} /* block allocator related options are parsed here */ |
bd4c625c0 reiserfs: run scr... |
518 |
int reiserfs_parse_alloc_options(struct super_block *s, char *options) |
1da177e4c Linux-2.6.12-rc2 |
519 |
{ |
bd4c625c0 reiserfs: run scr... |
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
char *this_char, *value; REISERFS_SB(s)->s_alloc_options.bits = 0; /* clear default settings */ while ((this_char = strsep(&options, ":")) != NULL) { if ((value = strchr(this_char, '=')) != NULL) *value++ = 0; if (!strcmp(this_char, "concentrating_formatted_nodes")) { int temp; SET_OPTION(concentrating_formatted_nodes); temp = (value && *value) ? simple_strtoul(value, &value, 0) : 10; if (temp <= 0 || temp > 100) { REISERFS_SB(s)->s_alloc_options.border = 10; } else { REISERFS_SB(s)->s_alloc_options.border = 100 / temp; } continue; } if (!strcmp(this_char, "displacing_large_files")) { SET_OPTION(displacing_large_files); REISERFS_SB(s)->s_alloc_options.large_file_size = (value && *value) ? simple_strtoul(value, &value, 0) : 16; continue; } if (!strcmp(this_char, "displacing_new_packing_localities")) { SET_OPTION(displacing_new_packing_localities); continue; }; if (!strcmp(this_char, "old_hashed_relocation")) { SET_OPTION(old_hashed_relocation); continue; } |
1da177e4c Linux-2.6.12-rc2 |
558 |
|
bd4c625c0 reiserfs: run scr... |
559 560 561 562 |
if (!strcmp(this_char, "new_hashed_relocation")) { SET_OPTION(new_hashed_relocation); continue; } |
1da177e4c Linux-2.6.12-rc2 |
563 |
|
bd4c625c0 reiserfs: run scr... |
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
if (!strcmp(this_char, "dirid_groups")) { SET_OPTION(dirid_groups); continue; } if (!strcmp(this_char, "oid_groups")) { SET_OPTION(oid_groups); continue; } if (!strcmp(this_char, "packing_groups")) { SET_OPTION(packing_groups); continue; } if (!strcmp(this_char, "hashed_formatted_nodes")) { SET_OPTION(hashed_formatted_nodes); continue; } |
1da177e4c Linux-2.6.12-rc2 |
580 |
|
bd4c625c0 reiserfs: run scr... |
581 582 583 584 |
if (!strcmp(this_char, "skip_busy")) { SET_OPTION(skip_busy); continue; } |
1da177e4c Linux-2.6.12-rc2 |
585 |
|
bd4c625c0 reiserfs: run scr... |
586 587 588 589 |
if (!strcmp(this_char, "hundredth_slices")) { SET_OPTION(hundredth_slices); continue; } |
1da177e4c Linux-2.6.12-rc2 |
590 |
|
bd4c625c0 reiserfs: run scr... |
591 592 593 594 |
if (!strcmp(this_char, "old_way")) { SET_OPTION(old_way); continue; } |
1da177e4c Linux-2.6.12-rc2 |
595 |
|
bd4c625c0 reiserfs: run scr... |
596 597 598 599 |
if (!strcmp(this_char, "displace_based_on_dirid")) { SET_OPTION(displace_based_on_dirid); continue; } |
1da177e4c Linux-2.6.12-rc2 |
600 |
|
bd4c625c0 reiserfs: run scr... |
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
if (!strcmp(this_char, "preallocmin")) { REISERFS_SB(s)->s_alloc_options.preallocmin = (value && *value) ? simple_strtoul(value, &value, 0) : 4; continue; } if (!strcmp(this_char, "preallocsize")) { REISERFS_SB(s)->s_alloc_options.preallocsize = (value && *value) ? simple_strtoul(value, &value, 0) : PREALLOCATION_SIZE; continue; } |
1da177e4c Linux-2.6.12-rc2 |
616 |
|
45b03d5e8 reiserfs: rework ... |
617 618 |
reiserfs_warning(s, "zam-4001", "unknown option - %s", this_char); |
bd4c625c0 reiserfs: run scr... |
619 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
620 |
} |
1d889d995 reiserfs: make so... |
621 622 |
reiserfs_info(s, "allocator options = [%08x] ", SB_ALLOC_OPTS(s)); |
bd4c625c0 reiserfs: run scr... |
623 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
624 |
} |
bd4c625c0 reiserfs: run scr... |
625 626 |
static inline void new_hashed_relocation(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
627 |
{ |
bd4c625c0 reiserfs: run scr... |
628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
char *hash_in; if (hint->formatted_node) { hash_in = (char *)&hint->key.k_dir_id; } else { if (!hint->inode) { //hint->search_start = hint->beg; hash_in = (char *)&hint->key.k_dir_id; } else if (TEST_OPTION(displace_based_on_dirid, hint->th->t_super)) hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id); else hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid); } |
1da177e4c Linux-2.6.12-rc2 |
642 |
|
bd4c625c0 reiserfs: run scr... |
643 644 |
hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg); |
1da177e4c Linux-2.6.12-rc2 |
645 646 647 648 |
} /* * Relocation based on dirid, hashing them into a given bitmap block |
c78bad11f fs/: Spelling fixes |
649 |
* files. Formatted nodes are unaffected, a separate policy covers them |
1da177e4c Linux-2.6.12-rc2 |
650 |
*/ |
bd4c625c0 reiserfs: run scr... |
651 |
static void dirid_groups(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
652 |
{ |
bd4c625c0 reiserfs: run scr... |
653 654 655 656 |
unsigned long hash; __u32 dirid = 0; int bm = 0; struct super_block *sb = hint->th->t_super; |
1da177e4c Linux-2.6.12-rc2 |
657 |
if (hint->inode) |
bd4c625c0 reiserfs: run scr... |
658 659 660 661 662 663 664 665 666 667 668 669 |
dirid = le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id); else if (hint->formatted_node) dirid = hint->key.k_dir_id; if (dirid) { bm = bmap_hash_id(sb, dirid); hash = bm * (sb->s_blocksize << 3); /* give a portion of the block group to metadata */ if (hint->inode) hash += sb->s_blocksize / 2; hint->search_start = hash; } |
1da177e4c Linux-2.6.12-rc2 |
670 671 672 673 |
} /* * Relocation based on oid, hashing them into a given bitmap block |
c78bad11f fs/: Spelling fixes |
674 |
* files. Formatted nodes are unaffected, a separate policy covers them |
1da177e4c Linux-2.6.12-rc2 |
675 |
*/ |
bd4c625c0 reiserfs: run scr... |
676 |
static void oid_groups(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
677 |
{ |
bd4c625c0 reiserfs: run scr... |
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
if (hint->inode) { unsigned long hash; __u32 oid; __u32 dirid; int bm; dirid = le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id); /* keep the root dir and it's first set of subdirs close to * the start of the disk */ if (dirid <= 2) hash = (hint->inode->i_sb->s_blocksize << 3); else { oid = le32_to_cpu(INODE_PKEY(hint->inode)->k_objectid); bm = bmap_hash_id(hint->inode->i_sb, oid); hash = bm * (hint->inode->i_sb->s_blocksize << 3); } hint->search_start = hash; |
1da177e4c Linux-2.6.12-rc2 |
697 |
} |
1da177e4c Linux-2.6.12-rc2 |
698 699 700 701 702 |
} /* returns 1 if it finds an indirect item and gets valid hint info * from it, otherwise 0 */ |
bd4c625c0 reiserfs: run scr... |
703 |
static int get_left_neighbor(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
704 |
{ |
fec6d055d [PATCH] struct pa... |
705 |
struct treepath *path; |
bd4c625c0 reiserfs: run scr... |
706 707 708 709 710 711 712 |
struct buffer_head *bh; struct item_head *ih; int pos_in_item; __le32 *item; int ret = 0; if (!hint->path) /* reiserfs code can call this function w/o pointer to path |
1da177e4c Linux-2.6.12-rc2 |
713 |
* structure supplied; then we rely on supplied search_start */ |
bd4c625c0 reiserfs: run scr... |
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 |
return 0; path = hint->path; bh = get_last_bh(path); RFALSE(!bh, "green-4002: Illegal path specified to get_left_neighbor"); ih = get_ih(path); pos_in_item = path->pos_in_item; item = get_item(path); hint->search_start = bh->b_blocknr; if (!hint->formatted_node && is_indirect_le_ih(ih)) { /* for indirect item: go to left and look for the first non-hole entry in the indirect item */ if (pos_in_item == I_UNFM_NUM(ih)) pos_in_item--; // pos_in_item = I_UNFM_NUM (ih) - 1; while (pos_in_item >= 0) { int t = get_block_num(item, pos_in_item); if (t) { hint->search_start = t; ret = 1; break; } pos_in_item--; } |
1da177e4c Linux-2.6.12-rc2 |
740 |
} |
1da177e4c Linux-2.6.12-rc2 |
741 |
|
bd4c625c0 reiserfs: run scr... |
742 743 |
/* does result value fit into specified region? */ return ret; |
1da177e4c Linux-2.6.12-rc2 |
744 745 746 747 748 749 |
} /* should be, if formatted node, then try to put on first part of the device specified as number of percent with mount option device, else try to put on last of device. This is not to say it is good code to do so, but the effect should be measured. */ |
bd4c625c0 reiserfs: run scr... |
750 751 |
static inline void set_border_in_hint(struct super_block *s, reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
752 |
{ |
bd4c625c0 reiserfs: run scr... |
753 754 |
b_blocknr_t border = SB_BLOCK_COUNT(s) / REISERFS_SB(s)->s_alloc_options.border; |
1da177e4c Linux-2.6.12-rc2 |
755 |
|
bd4c625c0 reiserfs: run scr... |
756 757 758 759 |
if (hint->formatted_node) hint->end = border - 1; else hint->beg = border; |
1da177e4c Linux-2.6.12-rc2 |
760 |
} |
bd4c625c0 reiserfs: run scr... |
761 |
static inline void displace_large_file(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
762 |
{ |
bd4c625c0 reiserfs: run scr... |
763 764 765 766 767 768 769 770 771 772 |
if (TEST_OPTION(displace_based_on_dirid, hint->th->t_super)) hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_dir_id), 4) % (hint->end - hint->beg); else hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_objectid), 4) % (hint->end - hint->beg); |
1da177e4c Linux-2.6.12-rc2 |
773 |
} |
bd4c625c0 reiserfs: run scr... |
774 |
static inline void hash_formatted_node(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
775 |
{ |
bd4c625c0 reiserfs: run scr... |
776 |
char *hash_in; |
1da177e4c Linux-2.6.12-rc2 |
777 |
|
bd4c625c0 reiserfs: run scr... |
778 779 780 781 782 783 |
if (!hint->inode) hash_in = (char *)&hint->key.k_dir_id; else if (TEST_OPTION(displace_based_on_dirid, hint->th->t_super)) hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id); else hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid); |
1da177e4c Linux-2.6.12-rc2 |
784 |
|
bd4c625c0 reiserfs: run scr... |
785 786 |
hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg); |
1da177e4c Linux-2.6.12-rc2 |
787 |
} |
bd4c625c0 reiserfs: run scr... |
788 789 790 |
static inline int this_blocknr_allocation_would_make_it_a_large_file(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
791 |
{ |
bd4c625c0 reiserfs: run scr... |
792 793 |
return hint->block == REISERFS_SB(hint->th->t_super)->s_alloc_options.large_file_size; |
1da177e4c Linux-2.6.12-rc2 |
794 795 796 |
} #ifdef DISPLACE_NEW_PACKING_LOCALITIES |
bd4c625c0 reiserfs: run scr... |
797 |
static inline void displace_new_packing_locality(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
798 |
{ |
bd4c625c0 reiserfs: run scr... |
799 |
struct in_core_key *key = &hint->key; |
1da177e4c Linux-2.6.12-rc2 |
800 |
|
bd4c625c0 reiserfs: run scr... |
801 802 803 804 |
hint->th->displace_new_blocks = 0; hint->search_start = hint->beg + keyed_hash((char *)(&key->k_objectid), 4) % (hint->end - hint->beg); |
1da177e4c Linux-2.6.12-rc2 |
805 |
} |
bd4c625c0 reiserfs: run scr... |
806 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
807 |
|
bd4c625c0 reiserfs: run scr... |
808 |
static inline int old_hashed_relocation(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
809 |
{ |
bd4c625c0 reiserfs: run scr... |
810 811 |
b_blocknr_t border; u32 hash_in; |
1da177e4c Linux-2.6.12-rc2 |
812 |
|
bd4c625c0 reiserfs: run scr... |
813 814 815 |
if (hint->formatted_node || hint->inode == NULL) { return 0; } |
1da177e4c Linux-2.6.12-rc2 |
816 |
|
bd4c625c0 reiserfs: run scr... |
817 818 819 820 821 822 |
hash_in = le32_to_cpu((INODE_PKEY(hint->inode))->k_dir_id); border = hint->beg + (u32) keyed_hash(((char *)(&hash_in)), 4) % (hint->end - hint->beg - 1); if (border > hint->search_start) hint->search_start = border; |
1da177e4c Linux-2.6.12-rc2 |
823 |
|
bd4c625c0 reiserfs: run scr... |
824 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
825 |
} |
bd4c625c0 reiserfs: run scr... |
826 |
static inline int old_way(reiserfs_blocknr_hint_t * hint) |
1da177e4c Linux-2.6.12-rc2 |
827 |
{ |
bd4c625c0 reiserfs: run scr... |
828 829 830 831 832 833 834 835 836 837 838 839 |
b_blocknr_t border; if (hint->formatted_node || hint->inode == NULL) { return 0; } border = hint->beg + le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id) % (hint->end - hint->beg); if (border > hint->search_start) hint->search_start = border; |
1da177e4c Linux-2.6.12-rc2 |
840 |
|
bd4c625c0 reiserfs: run scr... |
841 842 843 844 845 846 847 848 849 850 851 852 853 854 |
return 1; } static inline void hundredth_slices(reiserfs_blocknr_hint_t * hint) { struct in_core_key *key = &hint->key; b_blocknr_t slice_start; slice_start = (keyed_hash((char *)(&key->k_dir_id), 4) % 100) * (hint->end / 100); if (slice_start > hint->search_start || slice_start + (hint->end / 100) <= hint->search_start) { hint->search_start = slice_start; } |
1da177e4c Linux-2.6.12-rc2 |
855 |
} |
bd4c625c0 reiserfs: run scr... |
856 857 858 |
static void determine_search_start(reiserfs_blocknr_hint_t * hint, int amount_needed) |
1da177e4c Linux-2.6.12-rc2 |
859 |
{ |
bd4c625c0 reiserfs: run scr... |
860 861 |
struct super_block *s = hint->th->t_super; int unfm_hint; |
1da177e4c Linux-2.6.12-rc2 |
862 |
|
bd4c625c0 reiserfs: run scr... |
863 864 |
hint->beg = 0; hint->end = SB_BLOCK_COUNT(s) - 1; |
1da177e4c Linux-2.6.12-rc2 |
865 |
|
bd4c625c0 reiserfs: run scr... |
866 867 868 |
/* This is former border algorithm. Now with tunable border offset */ if (concentrating_formatted_nodes(s)) set_border_in_hint(s, hint); |
1da177e4c Linux-2.6.12-rc2 |
869 870 |
#ifdef DISPLACE_NEW_PACKING_LOCALITIES |
bd4c625c0 reiserfs: run scr... |
871 872 873 874 875 876 877 878 879 880 881 |
/* whenever we create a new directory, we displace it. At first we will hash for location, later we might look for a moderately empty place for it */ if (displacing_new_packing_localities(s) && hint->th->displace_new_blocks) { displace_new_packing_locality(hint); /* we do not continue determine_search_start, * if new packing locality is being displaced */ return; } |
1da177e4c Linux-2.6.12-rc2 |
882 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
883 |
|
bd4c625c0 reiserfs: run scr... |
884 885 |
/* all persons should feel encouraged to add more special cases here and * test them */ |
1da177e4c Linux-2.6.12-rc2 |
886 |
|
bd4c625c0 reiserfs: run scr... |
887 888 889 890 891 |
if (displacing_large_files(s) && !hint->formatted_node && this_blocknr_allocation_would_make_it_a_large_file(hint)) { displace_large_file(hint); return; } |
1da177e4c Linux-2.6.12-rc2 |
892 |
|
bd4c625c0 reiserfs: run scr... |
893 894 895 896 897 898 |
/* if none of our special cases is relevant, use the left neighbor in the tree order of the new node we are allocating for */ if (hint->formatted_node && TEST_OPTION(hashed_formatted_nodes, s)) { hash_formatted_node(hint); return; } |
1da177e4c Linux-2.6.12-rc2 |
899 |
|
bd4c625c0 reiserfs: run scr... |
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 |
unfm_hint = get_left_neighbor(hint); /* Mimic old block allocator behaviour, that is if VFS allowed for preallocation, new blocks are displaced based on directory ID. Also, if suggested search_start is less than last preallocated block, we start searching from it, assuming that HDD dataflow is faster in forward direction */ if (TEST_OPTION(old_way, s)) { if (!hint->formatted_node) { if (!reiserfs_hashed_relocation(s)) old_way(hint); else if (!reiserfs_no_unhashed_relocation(s)) old_hashed_relocation(hint); if (hint->inode && hint->search_start < REISERFS_I(hint->inode)->i_prealloc_block) hint->search_start = REISERFS_I(hint->inode)->i_prealloc_block; } return; |
1da177e4c Linux-2.6.12-rc2 |
920 |
} |
1da177e4c Linux-2.6.12-rc2 |
921 |
|
bd4c625c0 reiserfs: run scr... |
922 923 924 925 926 927 |
/* This is an approach proposed by Hans */ if (TEST_OPTION(hundredth_slices, s) && !(displacing_large_files(s) && !hint->formatted_node)) { hundredth_slices(hint); return; } |
1da177e4c Linux-2.6.12-rc2 |
928 |
|
bd4c625c0 reiserfs: run scr... |
929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
/* old_hashed_relocation only works on unformatted */ if (!unfm_hint && !hint->formatted_node && TEST_OPTION(old_hashed_relocation, s)) { old_hashed_relocation(hint); } /* new_hashed_relocation works with both formatted/unformatted nodes */ if ((!unfm_hint || hint->formatted_node) && TEST_OPTION(new_hashed_relocation, s)) { new_hashed_relocation(hint); } /* dirid grouping works only on unformatted nodes */ if (!unfm_hint && !hint->formatted_node && TEST_OPTION(dirid_groups, s)) { dirid_groups(hint); } |
1da177e4c Linux-2.6.12-rc2 |
943 |
#ifdef DISPLACE_NEW_PACKING_LOCALITIES |
bd4c625c0 reiserfs: run scr... |
944 945 946 |
if (hint->formatted_node && TEST_OPTION(dirid_groups, s)) { dirid_groups(hint); } |
1da177e4c Linux-2.6.12-rc2 |
947 |
#endif |
bd4c625c0 reiserfs: run scr... |
948 949 950 951 952 |
/* oid grouping works only on unformatted nodes */ if (!unfm_hint && !hint->formatted_node && TEST_OPTION(oid_groups, s)) { oid_groups(hint); } return; |
1da177e4c Linux-2.6.12-rc2 |
953 954 955 956 |
} static int determine_prealloc_size(reiserfs_blocknr_hint_t * hint) { |
bd4c625c0 reiserfs: run scr... |
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
/* make minimum size a mount option and benchmark both ways */ /* we preallocate blocks only for regular files, specific size */ /* benchmark preallocating always and see what happens */ hint->prealloc_size = 0; if (!hint->formatted_node && hint->preallocate) { if (S_ISREG(hint->inode->i_mode) && hint->inode->i_size >= REISERFS_SB(hint->th->t_super)->s_alloc_options. preallocmin * hint->inode->i_sb->s_blocksize) hint->prealloc_size = REISERFS_SB(hint->th->t_super)->s_alloc_options. preallocsize - 1; } return CARRY_ON; |
1da177e4c Linux-2.6.12-rc2 |
973 974 975 976 |
} /* XXX I know it could be merged with upper-level function; but may be result function would be too complex. */ |
bd4c625c0 reiserfs: run scr... |
977 978 979 980 981 982 |
static inline int allocate_without_wrapping_disk(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new_blocknrs, b_blocknr_t start, b_blocknr_t finish, int min, int amount_needed, int prealloc_size) |
1da177e4c Linux-2.6.12-rc2 |
983 |
{ |
bd4c625c0 reiserfs: run scr... |
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
int rest = amount_needed; int nr_allocated; while (rest > 0 && start <= finish) { nr_allocated = scan_bitmap(hint->th, &start, finish, min, rest + prealloc_size, !hint->formatted_node, hint->block); if (nr_allocated == 0) /* no new blocks allocated, return */ break; /* fill free_blocknrs array first */ while (rest > 0 && nr_allocated > 0) { *new_blocknrs++ = start++; rest--; nr_allocated--; } |
1da177e4c Linux-2.6.12-rc2 |
1001 |
|
bd4c625c0 reiserfs: run scr... |
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
/* do we have something to fill prealloc. array also ? */ if (nr_allocated > 0) { /* it means prealloc_size was greater that 0 and we do preallocation */ list_add(&REISERFS_I(hint->inode)->i_prealloc_list, &SB_JOURNAL(hint->th->t_super)-> j_prealloc_list); REISERFS_I(hint->inode)->i_prealloc_block = start; REISERFS_I(hint->inode)->i_prealloc_count = nr_allocated; break; } |
1da177e4c Linux-2.6.12-rc2 |
1013 |
} |
1da177e4c Linux-2.6.12-rc2 |
1014 |
|
bd4c625c0 reiserfs: run scr... |
1015 |
return (amount_needed - rest); |
1da177e4c Linux-2.6.12-rc2 |
1016 1017 1018 |
} static inline int blocknrs_and_prealloc_arrays_from_search_start |
bd4c625c0 reiserfs: run scr... |
1019 1020 1021 1022 1023 1024 1025 |
(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new_blocknrs, int amount_needed) { struct super_block *s = hint->th->t_super; b_blocknr_t start = hint->search_start; b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; int passno = 0; int nr_allocated = 0; |
bd4c625c0 reiserfs: run scr... |
1026 1027 1028 1029 |
determine_prealloc_size(hint); if (!hint->formatted_node) { int quota_ret; |
1da177e4c Linux-2.6.12-rc2 |
1030 |
#ifdef REISERQUOTA_DEBUG |
bd4c625c0 reiserfs: run scr... |
1031 1032 1033 |
reiserfs_debug(s, REISERFS_DEBUG_CODE, "reiserquota: allocating %d blocks id=%u", amount_needed, hint->inode->i_uid); |
1da177e4c Linux-2.6.12-rc2 |
1034 |
#endif |
bd4c625c0 reiserfs: run scr... |
1035 |
quota_ret = |
5dd4056db dquot: cleanup sp... |
1036 |
dquot_alloc_block_nodirty(hint->inode, amount_needed); |
bd4c625c0 reiserfs: run scr... |
1037 1038 1039 |
if (quota_ret) /* Quota exceeded? */ return QUOTA_EXCEEDED; if (hint->preallocate && hint->prealloc_size) { |
1da177e4c Linux-2.6.12-rc2 |
1040 |
#ifdef REISERQUOTA_DEBUG |
bd4c625c0 reiserfs: run scr... |
1041 1042 1043 |
reiserfs_debug(s, REISERFS_DEBUG_CODE, "reiserquota: allocating (prealloc) %d blocks id=%u", hint->prealloc_size, hint->inode->i_uid); |
1da177e4c Linux-2.6.12-rc2 |
1044 |
#endif |
5dd4056db dquot: cleanup sp... |
1045 |
quota_ret = dquot_prealloc_block_nodirty(hint->inode, |
bd4c625c0 reiserfs: run scr... |
1046 1047 1048 1049 1050 |
hint->prealloc_size); if (quota_ret) hint->preallocate = hint->prealloc_size = 0; } /* for unformatted nodes, force large allocations */ |
1da177e4c Linux-2.6.12-rc2 |
1051 |
} |
1da177e4c Linux-2.6.12-rc2 |
1052 |
|
bd4c625c0 reiserfs: run scr... |
1053 |
do { |
bd4c625c0 reiserfs: run scr... |
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
switch (passno++) { case 0: /* Search from hint->search_start to end of disk */ start = hint->search_start; finish = SB_BLOCK_COUNT(s) - 1; break; case 1: /* Search from hint->beg to hint->search_start */ start = hint->beg; finish = hint->search_start; break; case 2: /* Last chance: Search from 0 to hint->beg */ start = 0; finish = hint->beg; break; default: /* We've tried searching everywhere, not enough space */ /* Free the blocks */ if (!hint->formatted_node) { |
1da177e4c Linux-2.6.12-rc2 |
1070 |
#ifdef REISERQUOTA_DEBUG |
bd4c625c0 reiserfs: run scr... |
1071 1072 1073 1074 1075 1076 |
reiserfs_debug(s, REISERFS_DEBUG_CODE, "reiserquota: freeing (nospace) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated, hint->inode->i_uid); |
1da177e4c Linux-2.6.12-rc2 |
1077 |
#endif |
77db4f25b reiserfs: Use low... |
1078 |
/* Free not allocated blocks */ |
5dd4056db dquot: cleanup sp... |
1079 |
dquot_free_block_nodirty(hint->inode, |
77db4f25b reiserfs: Use low... |
1080 1081 |
amount_needed + hint->prealloc_size - nr_allocated); |
bd4c625c0 reiserfs: run scr... |
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 |
} while (nr_allocated--) reiserfs_free_block(hint->th, hint->inode, new_blocknrs[nr_allocated], !hint->formatted_node); return NO_DISK_SPACE; } } while ((nr_allocated += allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish, |
9ea0f9499 [PATCH] reiserfs:... |
1094 |
1, |
bd4c625c0 reiserfs: run scr... |
1095 1096 1097 1098 1099 1100 1101 1102 1103 |
amount_needed - nr_allocated, hint-> prealloc_size)) < amount_needed); if (!hint->formatted_node && amount_needed + hint->prealloc_size > nr_allocated + REISERFS_I(hint->inode)->i_prealloc_count) { /* Some of preallocation blocks were not allocated */ |
1da177e4c Linux-2.6.12-rc2 |
1104 |
#ifdef REISERQUOTA_DEBUG |
bd4c625c0 reiserfs: run scr... |
1105 1106 1107 1108 1109 1110 |
reiserfs_debug(s, REISERFS_DEBUG_CODE, "reiserquota: freeing (failed prealloc) %d blocks id=%u", amount_needed + hint->prealloc_size - nr_allocated - REISERFS_I(hint->inode)->i_prealloc_count, hint->inode->i_uid); |
1da177e4c Linux-2.6.12-rc2 |
1111 |
#endif |
5dd4056db dquot: cleanup sp... |
1112 |
dquot_free_block_nodirty(hint->inode, amount_needed + |
bd4c625c0 reiserfs: run scr... |
1113 1114 1115 1116 |
hint->prealloc_size - nr_allocated - REISERFS_I(hint->inode)-> i_prealloc_count); } |
1da177e4c Linux-2.6.12-rc2 |
1117 |
|
bd4c625c0 reiserfs: run scr... |
1118 |
return CARRY_ON; |
1da177e4c Linux-2.6.12-rc2 |
1119 1120 1121 1122 |
} /* grab new blocknrs from preallocated list */ /* return amount still needed after using them */ |
bd4c625c0 reiserfs: run scr... |
1123 1124 1125 |
static int use_preallocated_list_if_available(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new_blocknrs, int amount_needed) |
1da177e4c Linux-2.6.12-rc2 |
1126 |
{ |
bd4c625c0 reiserfs: run scr... |
1127 |
struct inode *inode = hint->inode; |
1da177e4c Linux-2.6.12-rc2 |
1128 |
|
bd4c625c0 reiserfs: run scr... |
1129 1130 |
if (REISERFS_I(inode)->i_prealloc_count > 0) { while (amount_needed) { |
1da177e4c Linux-2.6.12-rc2 |
1131 |
|
bd4c625c0 reiserfs: run scr... |
1132 1133 |
*new_blocknrs++ = REISERFS_I(inode)->i_prealloc_block++; REISERFS_I(inode)->i_prealloc_count--; |
1da177e4c Linux-2.6.12-rc2 |
1134 |
|
bd4c625c0 reiserfs: run scr... |
1135 |
amount_needed--; |
1da177e4c Linux-2.6.12-rc2 |
1136 |
|
bd4c625c0 reiserfs: run scr... |
1137 1138 1139 1140 1141 |
if (REISERFS_I(inode)->i_prealloc_count <= 0) { list_del(&REISERFS_I(inode)->i_prealloc_list); break; } } |
1da177e4c Linux-2.6.12-rc2 |
1142 |
} |
bd4c625c0 reiserfs: run scr... |
1143 1144 |
/* return amount still needed after using preallocated blocks */ return amount_needed; |
1da177e4c Linux-2.6.12-rc2 |
1145 |
} |
bd4c625c0 reiserfs: run scr... |
1146 1147 |
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new_blocknrs, int amount_needed, int reserved_by_us /* Amount of blocks we have already reserved */ ) |
1da177e4c Linux-2.6.12-rc2 |
1148 |
{ |
bd4c625c0 reiserfs: run scr... |
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 |
int initial_amount_needed = amount_needed; int ret; struct super_block *s = hint->th->t_super; /* Check if there is enough space, taking into account reserved space */ if (SB_FREE_BLOCKS(s) - REISERFS_SB(s)->reserved_blocks < amount_needed - reserved_by_us) return NO_DISK_SPACE; /* should this be if !hint->inode && hint->preallocate? */ /* do you mean hint->formatted_node can be removed ? - Zam */ /* hint->formatted_node cannot be removed because we try to access inode information here, and there is often no inode assotiated with metadata allocations - green */ if (!hint->formatted_node && hint->preallocate) { amount_needed = use_preallocated_list_if_available (hint, new_blocknrs, amount_needed); if (amount_needed == 0) /* all blocknrs we need we got from prealloc. list */ return CARRY_ON; new_blocknrs += (initial_amount_needed - amount_needed); } /* find search start and save it in hint structure */ determine_search_start(hint, amount_needed); if (hint->search_start >= SB_BLOCK_COUNT(s)) hint->search_start = SB_BLOCK_COUNT(s) - 1; /* allocation itself; fill new_blocknrs and preallocation arrays */ ret = blocknrs_and_prealloc_arrays_from_search_start |
1da177e4c Linux-2.6.12-rc2 |
1179 |
(hint, new_blocknrs, amount_needed); |
bd4c625c0 reiserfs: run scr... |
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 |
/* we used prealloc. list to fill (partially) new_blocknrs array. If final allocation fails we * need to return blocks back to prealloc. list or just free them. -- Zam (I chose second * variant) */ if (ret != CARRY_ON) { while (amount_needed++ < initial_amount_needed) { reiserfs_free_block(hint->th, hint->inode, *(--new_blocknrs), 1); } |
1da177e4c Linux-2.6.12-rc2 |
1190 |
} |
bd4c625c0 reiserfs: run scr... |
1191 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1192 |
} |
6f01046b3 [PATCH] reiserfs:... |
1193 1194 1195 1196 1197 |
void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info) { unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size); |
4d20851d3 reiserfs: remove ... |
1198 |
/* The first bit must ALWAYS be 1 */ |
0030b6457 reiserfs: use rei... |
1199 1200 1201 |
if (!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data)) reiserfs_error(sb, "reiserfs-2025", "bitmap block %lu is " "corrupted: first bit must be 1", bh->b_blocknr); |
4d20851d3 reiserfs: remove ... |
1202 1203 |
info->free_count = 0; |
6f01046b3 [PATCH] reiserfs:... |
1204 1205 |
while (--cur >= (unsigned long *)bh->b_data) { |
6f01046b3 [PATCH] reiserfs:... |
1206 |
/* 0 and ~0 are special, we can optimize for them */ |
4d20851d3 reiserfs: remove ... |
1207 |
if (*cur == 0) |
6f01046b3 [PATCH] reiserfs:... |
1208 |
info->free_count += BITS_PER_LONG; |
4d20851d3 reiserfs: remove ... |
1209 |
else if (*cur != ~0L) /* A mix, investigate */ |
9d6bf5aa1 reiserfs: use hwe... |
1210 |
info->free_count += BITS_PER_LONG - hweight_long(*cur); |
6f01046b3 [PATCH] reiserfs:... |
1211 |
} |
6f01046b3 [PATCH] reiserfs:... |
1212 1213 1214 1215 1216 1217 |
} struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap) { b_blocknr_t block = (sb->s_blocksize << 3) * bitmap; |
5065227b4 [PATCH] reiserfs:... |
1218 |
struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap; |
6f01046b3 [PATCH] reiserfs:... |
1219 1220 1221 1222 1223 1224 1225 1226 1227 |
struct buffer_head *bh; /* Way old format filesystems had the bitmaps packed up front. * I doubt there are any of these left, but just in case... */ if (unlikely(test_bit(REISERFS_OLD_FORMAT, &(REISERFS_SB(sb)->s_properties)))) block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap; else if (bitmap == 0) block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; |
4c5eface5 kill-the-BKL/reis... |
1228 |
reiserfs_write_unlock(sb); |
5065227b4 [PATCH] reiserfs:... |
1229 |
bh = sb_bread(sb, block); |
4c5eface5 kill-the-BKL/reis... |
1230 |
reiserfs_write_lock(sb); |
5065227b4 [PATCH] reiserfs:... |
1231 |
if (bh == NULL) |
00079e04f [PATCH] reiserfs:... |
1232 |
reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " |
fbe5498b3 reiserfs: replace... |
1233 |
"reading failed", __func__, block); |
5065227b4 [PATCH] reiserfs:... |
1234 1235 1236 |
else { if (buffer_locked(bh)) { PROC_INFO_INC(sb, scan_bitmap.wait); |
8ebc42323 reiserfs: kill-th... |
1237 |
reiserfs_write_unlock(sb); |
5065227b4 [PATCH] reiserfs:... |
1238 |
__wait_on_buffer(bh); |
8ebc42323 reiserfs: kill-th... |
1239 |
reiserfs_write_lock(sb); |
5065227b4 [PATCH] reiserfs:... |
1240 1241 1242 |
} BUG_ON(!buffer_uptodate(bh)); BUG_ON(atomic_read(&bh->b_count) == 0); |
4d20851d3 reiserfs: remove ... |
1243 |
if (info->free_count == UINT_MAX) |
5065227b4 [PATCH] reiserfs:... |
1244 1245 |
reiserfs_cache_bitmap_metadata(sb, bh, info); } |
6f01046b3 [PATCH] reiserfs:... |
1246 1247 1248 1249 1250 1251 1252 |
return bh; } int reiserfs_init_bitmap_cache(struct super_block *sb) { struct reiserfs_bitmap_info *bitmap; |
cb680c1be reiserfs: ignore ... |
1253 |
unsigned int bmap_nr = reiserfs_bmap_count(sb); |
6f01046b3 [PATCH] reiserfs:... |
1254 |
|
500f5a0bf reiserfs: Fix pos... |
1255 1256 |
/* Avoid lock recursion in fault case */ reiserfs_write_unlock(sb); |
cb680c1be reiserfs: ignore ... |
1257 |
bitmap = vmalloc(sizeof(*bitmap) * bmap_nr); |
500f5a0bf reiserfs: Fix pos... |
1258 |
reiserfs_write_lock(sb); |
6f01046b3 [PATCH] reiserfs:... |
1259 1260 |
if (bitmap == NULL) return -ENOMEM; |
cb680c1be reiserfs: ignore ... |
1261 |
memset(bitmap, 0xff, sizeof(*bitmap) * bmap_nr); |
6f01046b3 [PATCH] reiserfs:... |
1262 |
|
6f01046b3 [PATCH] reiserfs:... |
1263 1264 1265 1266 |
SB_AP_BITMAP(sb) = bitmap; return 0; } |
5065227b4 [PATCH] reiserfs:... |
1267 1268 1269 1270 1271 1272 1273 1274 |
void reiserfs_free_bitmap_cache(struct super_block *sb) { if (SB_AP_BITMAP(sb)) { vfree(SB_AP_BITMAP(sb)); SB_AP_BITMAP(sb) = NULL; } } |