Blame view
fs/udf/balloc.c
21.6 KB
1da177e4c
|
1 2 3 4 5 6 |
/* * balloc.c * * PURPOSE * Block allocation handling routines for the OSTA-UDF(tm) filesystem. * |
1da177e4c
|
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 1999-2001 Ben Fennema * (C) 1999 Stelias Computing Inc * * HISTORY * * 02/24/99 blf Created. * */ #include "udfdecl.h" |
1da177e4c
|
23 24 25 26 27 |
#include <linux/buffer_head.h> #include <linux/bitops.h> #include "udf_i.h" #include "udf_sb.h" |
4b11111ab
|
28 29 |
#define udf_clear_bit(nr, addr) ext2_clear_bit(nr, addr) #define udf_set_bit(nr, addr) ext2_set_bit(nr, addr) |
1da177e4c
|
30 |
#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr) |
4b11111ab
|
31 |
#define udf_find_next_one_bit(addr, size, offset) \ |
3a065fcf9
|
32 |
ext2_find_next_bit(addr, size, offset) |
1da177e4c
|
33 |
|
cb00ea352
|
34 35 36 |
static int read_block_bitmap(struct super_block *sb, struct udf_bitmap *bitmap, unsigned int block, unsigned long bitmap_nr) |
1da177e4c
|
37 38 39 |
{ struct buffer_head *bh = NULL; int retval = 0; |
5ca4e4be8
|
40 |
struct kernel_lb_addr loc; |
1da177e4c
|
41 42 |
loc.logicalBlockNum = bitmap->s_extPosition; |
6c79e987d
|
43 |
loc.partitionReferenceNum = UDF_SB(sb)->s_partition; |
1da177e4c
|
44 |
|
97e961fdb
|
45 |
bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block)); |
4b11111ab
|
46 |
if (!bh) |
1da177e4c
|
47 |
retval = -EIO; |
4b11111ab
|
48 |
|
1da177e4c
|
49 50 51 |
bitmap->s_block_bitmap[bitmap_nr] = bh; return retval; } |
cb00ea352
|
52 53 54 |
static int __load_block_bitmap(struct super_block *sb, struct udf_bitmap *bitmap, unsigned int block_group) |
1da177e4c
|
55 56 57 |
{ int retval = 0; int nr_groups = bitmap->s_nr_groups; |
cb00ea352
|
58 59 60 61 |
if (block_group >= nr_groups) { udf_debug("block_group (%d) > nr_groups (%d) ", block_group, nr_groups); |
1da177e4c
|
62 |
} |
28de7948a
|
63 |
if (bitmap->s_block_bitmap[block_group]) { |
1da177e4c
|
64 |
return block_group; |
28de7948a
|
65 66 67 |
} else { retval = read_block_bitmap(sb, bitmap, block_group, block_group); |
1da177e4c
|
68 69 70 71 72 |
if (retval < 0) return retval; return block_group; } } |
cb00ea352
|
73 74 75 |
static inline int load_block_bitmap(struct super_block *sb, struct udf_bitmap *bitmap, unsigned int block_group) |
1da177e4c
|
76 77 78 79 80 81 82 83 84 85 86 87 88 |
{ int slot; slot = __load_block_bitmap(sb, bitmap, block_group); if (slot < 0) return slot; if (!bitmap->s_block_bitmap[slot]) return -EIO; return slot; } |
146bca72c
|
89 |
static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt) |
742ba02a5
|
90 |
{ |
146bca72c
|
91 |
struct udf_sb_info *sbi = UDF_SB(sb); |
742ba02a5
|
92 |
struct logicalVolIntegrityDesc *lvid; |
146bca72c
|
93 94 |
if (!sbi->s_lvid_bh) return; |
742ba02a5
|
95 96 |
lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; |
c2104fda5
|
97 |
le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); |
146bca72c
|
98 |
udf_updated_lvid(sb); |
742ba02a5
|
99 |
} |
cb00ea352
|
100 101 102 |
static void udf_bitmap_free_blocks(struct super_block *sb, struct inode *inode, struct udf_bitmap *bitmap, |
97e961fdb
|
103 104 |
struct kernel_lb_addr *bloc, uint32_t offset, |
cb00ea352
|
105 |
uint32_t count) |
1da177e4c
|
106 107 |
{ struct udf_sb_info *sbi = UDF_SB(sb); |
cb00ea352
|
108 |
struct buffer_head *bh = NULL; |
97e961fdb
|
109 |
struct udf_part_map *partmap; |
1da177e4c
|
110 111 112 113 114 115 |
unsigned long block; unsigned long block_group; unsigned long bit; unsigned long i; int bitmap_nr; unsigned long overflow; |
1e7933def
|
116 |
mutex_lock(&sbi->s_alloc_mutex); |
97e961fdb
|
117 |
partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; |
69ecbbeda
|
118 119 |
if (bloc->logicalBlockNum + count < count || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { |
28de7948a
|
120 121 |
udf_debug("%d < %d || %d + %d > %d ", |
97e961fdb
|
122 123 |
bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, partmap->s_partition_len); |
1da177e4c
|
124 125 |
goto error_return; } |
97e961fdb
|
126 |
block = bloc->logicalBlockNum + offset + |
4b11111ab
|
127 |
(sizeof(struct spaceBitmapDesc) << 3); |
1da177e4c
|
128 |
|
4daa1b879
|
129 130 131 132 133 134 135 136 137 138 139 |
do { overflow = 0; block_group = block >> (sb->s_blocksize_bits + 3); bit = block % (sb->s_blocksize << 3); /* * Check to see if we are freeing blocks across a group boundary. */ if (bit + count > (sb->s_blocksize << 3)) { overflow = bit + count - (sb->s_blocksize << 3); count -= overflow; |
1da177e4c
|
140 |
} |
4daa1b879
|
141 142 143 144 145 146 147 148 149 150 151 152 153 |
bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; bh = bitmap->s_block_bitmap[bitmap_nr]; for (i = 0; i < count; i++) { if (udf_set_bit(bit + i, bh->b_data)) { udf_debug("bit %ld already set ", bit + i); udf_debug("byte=%2x ", ((char *)bh->b_data)[(bit + i) >> 3]); } else { |
146bca72c
|
154 |
udf_add_free_space(sb, sbi->s_partition, 1); |
4daa1b879
|
155 156 157 158 159 160 161 162 |
} } mark_buffer_dirty(bh); if (overflow) { block += count; count = overflow; } } while (overflow); |
28de7948a
|
163 |
error_return: |
1e7933def
|
164 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
165 |
} |
cb00ea352
|
166 167 168 169 170 |
static int udf_bitmap_prealloc_blocks(struct super_block *sb, struct inode *inode, struct udf_bitmap *bitmap, uint16_t partition, uint32_t first_block, uint32_t block_count) |
1da177e4c
|
171 172 173 174 175 176 |
{ struct udf_sb_info *sbi = UDF_SB(sb); int alloc_count = 0; int bit, block, block_group, group_start; int nr_groups, bitmap_nr; struct buffer_head *bh; |
6c79e987d
|
177 |
__u32 part_len; |
1da177e4c
|
178 |
|
1e7933def
|
179 |
mutex_lock(&sbi->s_alloc_mutex); |
6c79e987d
|
180 |
part_len = sbi->s_partmaps[partition].s_partition_len; |
3391faa4f
|
181 |
if (first_block >= part_len) |
1da177e4c
|
182 |
goto out; |
6c79e987d
|
183 184 |
if (first_block + block_count > part_len) block_count = part_len - first_block; |
1da177e4c
|
185 |
|
4daa1b879
|
186 187 188 189 190 |
do { nr_groups = udf_compute_nr_groups(sb, partition); block = first_block + (sizeof(struct spaceBitmapDesc) << 3); block_group = block >> (sb->s_blocksize_bits + 3); group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); |
1da177e4c
|
191 |
|
4daa1b879
|
192 193 194 195 |
bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto out; bh = bitmap->s_block_bitmap[bitmap_nr]; |
1da177e4c
|
196 |
|
4daa1b879
|
197 |
bit = block % (sb->s_blocksize << 3); |
1da177e4c
|
198 |
|
4daa1b879
|
199 |
while (bit < (sb->s_blocksize << 3) && block_count > 0) { |
363504628
|
200 |
if (!udf_clear_bit(bit, bh->b_data)) |
4daa1b879
|
201 |
goto out; |
4daa1b879
|
202 203 204 205 |
block_count--; alloc_count++; bit++; block++; |
1da177e4c
|
206 |
} |
4daa1b879
|
207 208 |
mark_buffer_dirty(bh); } while (block_count > 0); |
28de7948a
|
209 |
out: |
146bca72c
|
210 |
udf_add_free_space(sb, partition, -alloc_count); |
1e7933def
|
211 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
212 213 |
return alloc_count; } |
cb00ea352
|
214 215 216 217 |
static int udf_bitmap_new_block(struct super_block *sb, struct inode *inode, struct udf_bitmap *bitmap, uint16_t partition, uint32_t goal, int *err) |
1da177e4c
|
218 219 |
{ struct udf_sb_info *sbi = UDF_SB(sb); |
cb00ea352
|
220 |
int newbit, bit = 0, block, block_group, group_start; |
1da177e4c
|
221 222 223 224 225 226 |
int end_goal, nr_groups, bitmap_nr, i; struct buffer_head *bh = NULL; char *ptr; int newblock = 0; *err = -ENOSPC; |
1e7933def
|
227 |
mutex_lock(&sbi->s_alloc_mutex); |
1da177e4c
|
228 |
|
28de7948a
|
229 |
repeat: |
3391faa4f
|
230 |
if (goal >= sbi->s_partmaps[partition].s_partition_len) |
1da177e4c
|
231 232 233 234 235 236 237 238 239 240 241 |
goal = 0; nr_groups = bitmap->s_nr_groups; block = goal + (sizeof(struct spaceBitmapDesc) << 3); block_group = block >> (sb->s_blocksize_bits + 3); group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; bh = bitmap->s_block_bitmap[bitmap_nr]; |
28de7948a
|
242 243 |
ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); |
1da177e4c
|
244 |
|
cb00ea352
|
245 |
if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) { |
1da177e4c
|
246 |
bit = block % (sb->s_blocksize << 3); |
28de7948a
|
247 |
if (udf_test_bit(bit, bh->b_data)) |
1da177e4c
|
248 |
goto got_block; |
28de7948a
|
249 |
|
1da177e4c
|
250 251 252 253 |
end_goal = (bit + 63) & ~63; bit = udf_find_next_one_bit(bh->b_data, end_goal, bit); if (bit < end_goal) goto got_block; |
28de7948a
|
254 |
|
4b11111ab
|
255 256 |
ptr = memscan((char *)bh->b_data + (bit >> 3), 0xFF, sb->s_blocksize - ((bit + 7) >> 3)); |
1da177e4c
|
257 |
newbit = (ptr - ((char *)bh->b_data)) << 3; |
cb00ea352
|
258 |
if (newbit < sb->s_blocksize << 3) { |
1da177e4c
|
259 260 261 |
bit = newbit; goto search_back; } |
28de7948a
|
262 |
|
4b11111ab
|
263 264 |
newbit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, bit); |
cb00ea352
|
265 |
if (newbit < sb->s_blocksize << 3) { |
1da177e4c
|
266 267 268 269 |
bit = newbit; goto got_block; } } |
cb00ea352
|
270 271 |
for (i = 0; i < (nr_groups * 2); i++) { block_group++; |
1da177e4c
|
272 273 274 275 276 277 278 279 |
if (block_group >= nr_groups) block_group = 0; group_start = block_group ? 0 : sizeof(struct spaceBitmapDesc); bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; bh = bitmap->s_block_bitmap[bitmap_nr]; |
cb00ea352
|
280 |
if (i < nr_groups) { |
28de7948a
|
281 282 |
ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); |
cb00ea352
|
283 |
if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) { |
1da177e4c
|
284 285 286 |
bit = (ptr - ((char *)bh->b_data)) << 3; break; } |
cb00ea352
|
287 |
} else { |
28de7948a
|
288 289 290 |
bit = udf_find_next_one_bit((char *)bh->b_data, sb->s_blocksize << 3, group_start << 3); |
1da177e4c
|
291 292 293 294 |
if (bit < sb->s_blocksize << 3) break; } } |
cb00ea352
|
295 |
if (i >= (nr_groups * 2)) { |
1e7933def
|
296 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
297 298 299 300 301 |
return newblock; } if (bit < sb->s_blocksize << 3) goto search_back; else |
4b11111ab
|
302 303 |
bit = udf_find_next_one_bit(bh->b_data, sb->s_blocksize << 3, group_start << 3); |
cb00ea352
|
304 |
if (bit >= sb->s_blocksize << 3) { |
1e7933def
|
305 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
306 307 |
return 0; } |
28de7948a
|
308 |
search_back: |
4b11111ab
|
309 310 311 312 313 314 |
i = 0; while (i < 7 && bit > (group_start << 3) && udf_test_bit(bit - 1, bh->b_data)) { ++i; --bit; } |
1da177e4c
|
315 |
|
28de7948a
|
316 |
got_block: |
1da177e4c
|
317 |
newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) - |
28de7948a
|
318 |
(sizeof(struct spaceBitmapDesc) << 3); |
1da177e4c
|
319 |
|
cb00ea352
|
320 |
if (!udf_clear_bit(bit, bh->b_data)) { |
1da177e4c
|
321 322 323 324 325 326 |
udf_debug("bit already cleared for block %d ", bit); goto repeat; } mark_buffer_dirty(bh); |
146bca72c
|
327 |
udf_add_free_space(sb, partition, -1); |
1e7933def
|
328 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
329 330 |
*err = 0; return newblock; |
28de7948a
|
331 |
error_return: |
1da177e4c
|
332 |
*err = -EIO; |
1e7933def
|
333 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
334 335 |
return 0; } |
cb00ea352
|
336 337 338 |
static void udf_table_free_blocks(struct super_block *sb, struct inode *inode, struct inode *table, |
97e961fdb
|
339 340 |
struct kernel_lb_addr *bloc, uint32_t offset, |
cb00ea352
|
341 |
uint32_t count) |
1da177e4c
|
342 343 |
{ struct udf_sb_info *sbi = UDF_SB(sb); |
97e961fdb
|
344 |
struct udf_part_map *partmap; |
1da177e4c
|
345 |
uint32_t start, end; |
ff116fc8d
|
346 |
uint32_t elen; |
5ca4e4be8
|
347 |
struct kernel_lb_addr eloc; |
ff116fc8d
|
348 |
struct extent_position oepos, epos; |
1da177e4c
|
349 350 |
int8_t etype; int i; |
48d6d8ff7
|
351 |
struct udf_inode_info *iinfo; |
1da177e4c
|
352 |
|
1e7933def
|
353 |
mutex_lock(&sbi->s_alloc_mutex); |
97e961fdb
|
354 |
partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; |
69ecbbeda
|
355 356 |
if (bloc->logicalBlockNum + count < count || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { |
28de7948a
|
357 358 |
udf_debug("%d < %d || %d + %d > %d ", |
1fefd086d
|
359 |
bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, |
97e961fdb
|
360 |
partmap->s_partition_len); |
1da177e4c
|
361 362 |
goto error_return; } |
48d6d8ff7
|
363 |
iinfo = UDF_I(table); |
146bca72c
|
364 |
udf_add_free_space(sb, sbi->s_partition, count); |
1da177e4c
|
365 |
|
97e961fdb
|
366 367 |
start = bloc->logicalBlockNum + offset; end = bloc->logicalBlockNum + offset + count - 1; |
1da177e4c
|
368 |
|
ff116fc8d
|
369 |
epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); |
1da177e4c
|
370 |
elen = 0; |
48d6d8ff7
|
371 |
epos.block = oepos.block = iinfo->i_location; |
ff116fc8d
|
372 |
epos.bh = oepos.bh = NULL; |
1da177e4c
|
373 |
|
28de7948a
|
374 375 |
while (count && (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { |
4b11111ab
|
376 377 378 379 380 381 382 383 384 385 |
if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == start)) { if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) { uint32_t tmp = ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); count -= tmp; start += tmp; elen = (etype << 30) | (0x40000000 - sb->s_blocksize); |
cb00ea352
|
386 |
} else { |
4b11111ab
|
387 388 389 |
elen = (etype << 30) | (elen + (count << sb->s_blocksize_bits)); |
1da177e4c
|
390 391 392 |
start += count; count = 0; } |
97e961fdb
|
393 |
udf_write_aext(table, &oepos, &eloc, elen, 1); |
cb00ea352
|
394 |
} else if (eloc.logicalBlockNum == (end + 1)) { |
4b11111ab
|
395 396 397 398 399 400 401 402 403 |
if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) { uint32_t tmp = ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); count -= tmp; end -= tmp; eloc.logicalBlockNum -= tmp; elen = (etype << 30) | (0x40000000 - sb->s_blocksize); |
cb00ea352
|
404 |
} else { |
1da177e4c
|
405 |
eloc.logicalBlockNum = start; |
4b11111ab
|
406 407 408 |
elen = (etype << 30) | (elen + (count << sb->s_blocksize_bits)); |
1da177e4c
|
409 410 411 |
end -= count; count = 0; } |
97e961fdb
|
412 |
udf_write_aext(table, &oepos, &eloc, elen, 1); |
1da177e4c
|
413 |
} |
cb00ea352
|
414 |
if (epos.bh != oepos.bh) { |
1da177e4c
|
415 |
i = -1; |
ff116fc8d
|
416 |
oepos.block = epos.block; |
3bf25cb40
|
417 418 |
brelse(oepos.bh); get_bh(epos.bh); |
ff116fc8d
|
419 420 |
oepos.bh = epos.bh; oepos.offset = 0; |
28de7948a
|
421 |
} else { |
ff116fc8d
|
422 |
oepos.offset = epos.offset; |
28de7948a
|
423 |
} |
1da177e4c
|
424 |
} |
cb00ea352
|
425 |
if (count) { |
28de7948a
|
426 |
/* |
4b11111ab
|
427 428 429 |
* NOTE: we CANNOT use udf_add_aext here, as it can try to * allocate a new block, and since we hold the super block * lock already very bad things would happen :) |
28de7948a
|
430 431 432 433 434 435 436 |
* * We copy the behavior of udf_add_aext, but instead of * trying to allocate a new block close to the existing one, * we just steal a block from the extent we are trying to add. * * It would be nice if the blocks were close together, but it * isn't required. |
cb00ea352
|
437 |
*/ |
1da177e4c
|
438 439 |
int adsize; |
5ca4e4be8
|
440 441 |
struct short_ad *sad = NULL; struct long_ad *lad = NULL; |
1da177e4c
|
442 443 444 |
struct allocExtDesc *aed; eloc.logicalBlockNum = start; |
28de7948a
|
445 446 |
elen = EXT_RECORDED_ALLOCATED | (count << sb->s_blocksize_bits); |
1da177e4c
|
447 |
|
48d6d8ff7
|
448 |
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
5ca4e4be8
|
449 |
adsize = sizeof(struct short_ad); |
48d6d8ff7
|
450 |
else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
5ca4e4be8
|
451 |
adsize = sizeof(struct long_ad); |
48d6d8ff7
|
452 |
else { |
3bf25cb40
|
453 454 |
brelse(oepos.bh); brelse(epos.bh); |
1da177e4c
|
455 456 |
goto error_return; } |
cb00ea352
|
457 |
if (epos.offset + (2 * adsize) > sb->s_blocksize) { |
391e8bbd3
|
458 |
unsigned char *sptr, *dptr; |
1da177e4c
|
459 |
int loffset; |
cb00ea352
|
460 |
|
3bf25cb40
|
461 |
brelse(oepos.bh); |
ff116fc8d
|
462 |
oepos = epos; |
1da177e4c
|
463 464 |
/* Steal a block from the extent being free'd */ |
ff116fc8d
|
465 |
epos.block.logicalBlockNum = eloc.logicalBlockNum; |
cb00ea352
|
466 |
eloc.logicalBlockNum++; |
1da177e4c
|
467 |
elen -= sb->s_blocksize; |
4b11111ab
|
468 |
epos.bh = udf_tread(sb, |
97e961fdb
|
469 |
udf_get_lb_pblock(sb, &epos.block, 0)); |
4b11111ab
|
470 |
if (!epos.bh) { |
3bf25cb40
|
471 |
brelse(oepos.bh); |
1da177e4c
|
472 473 |
goto error_return; } |
ff116fc8d
|
474 |
aed = (struct allocExtDesc *)(epos.bh->b_data); |
4b11111ab
|
475 476 |
aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum); |
cb00ea352
|
477 |
if (epos.offset + adsize > sb->s_blocksize) { |
ff116fc8d
|
478 |
loffset = epos.offset; |
1da177e4c
|
479 |
aed->lengthAllocDescs = cpu_to_le32(adsize); |
48d6d8ff7
|
480 |
sptr = iinfo->i_ext.i_data + epos.offset |
c0b344385
|
481 |
- adsize; |
4b11111ab
|
482 483 |
dptr = epos.bh->b_data + sizeof(struct allocExtDesc); |
1da177e4c
|
484 |
memcpy(dptr, sptr, adsize); |
4b11111ab
|
485 486 |
epos.offset = sizeof(struct allocExtDesc) + adsize; |
cb00ea352
|
487 |
} else { |
ff116fc8d
|
488 |
loffset = epos.offset + adsize; |
1da177e4c
|
489 |
aed->lengthAllocDescs = cpu_to_le32(0); |
cb00ea352
|
490 |
if (oepos.bh) { |
f5cc15dac
|
491 |
sptr = oepos.bh->b_data + epos.offset; |
4b11111ab
|
492 493 |
aed = (struct allocExtDesc *) oepos.bh->b_data; |
c2104fda5
|
494 495 |
le32_add_cpu(&aed->lengthAllocDescs, adsize); |
cb00ea352
|
496 |
} else { |
48d6d8ff7
|
497 |
sptr = iinfo->i_ext.i_data + |
c0b344385
|
498 |
epos.offset; |
48d6d8ff7
|
499 |
iinfo->i_lenAlloc += adsize; |
1da177e4c
|
500 501 |
mark_inode_dirty(table); } |
f5cc15dac
|
502 |
epos.offset = sizeof(struct allocExtDesc); |
1da177e4c
|
503 |
} |
6c79e987d
|
504 |
if (sbi->s_udfrev >= 0x0200) |
4b11111ab
|
505 506 |
udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1, epos.block.logicalBlockNum, |
5ca4e4be8
|
507 |
sizeof(struct tag)); |
1da177e4c
|
508 |
else |
4b11111ab
|
509 510 |
udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1, epos.block.logicalBlockNum, |
5ca4e4be8
|
511 |
sizeof(struct tag)); |
28de7948a
|
512 |
|
48d6d8ff7
|
513 |
switch (iinfo->i_alloc_type) { |
4b11111ab
|
514 |
case ICBTAG_FLAG_AD_SHORT: |
5ca4e4be8
|
515 |
sad = (struct short_ad *)sptr; |
4b11111ab
|
516 517 518 519 520 521 522 |
sad->extLength = cpu_to_le32( EXT_NEXT_EXTENT_ALLOCDECS | sb->s_blocksize); sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum); break; case ICBTAG_FLAG_AD_LONG: |
5ca4e4be8
|
523 |
lad = (struct long_ad *)sptr; |
4b11111ab
|
524 525 526 527 528 529 |
lad->extLength = cpu_to_le32( EXT_NEXT_EXTENT_ALLOCDECS | sb->s_blocksize); lad->extLocation = cpu_to_lelb(epos.block); break; |
1da177e4c
|
530 |
} |
cb00ea352
|
531 |
if (oepos.bh) { |
ff116fc8d
|
532 533 |
udf_update_tag(oepos.bh->b_data, loffset); mark_buffer_dirty(oepos.bh); |
28de7948a
|
534 |
} else { |
1da177e4c
|
535 |
mark_inode_dirty(table); |
28de7948a
|
536 |
} |
1da177e4c
|
537 |
} |
4b11111ab
|
538 539 |
/* It's possible that stealing the block emptied the extent */ if (elen) { |
97e961fdb
|
540 |
udf_write_aext(table, &epos, &eloc, elen, 1); |
1da177e4c
|
541 |
|
cb00ea352
|
542 |
if (!epos.bh) { |
48d6d8ff7
|
543 |
iinfo->i_lenAlloc += adsize; |
1da177e4c
|
544 |
mark_inode_dirty(table); |
cb00ea352
|
545 |
} else { |
ff116fc8d
|
546 |
aed = (struct allocExtDesc *)epos.bh->b_data; |
c2104fda5
|
547 |
le32_add_cpu(&aed->lengthAllocDescs, adsize); |
ff116fc8d
|
548 549 |
udf_update_tag(epos.bh->b_data, epos.offset); mark_buffer_dirty(epos.bh); |
1da177e4c
|
550 551 552 |
} } } |
3bf25cb40
|
553 554 |
brelse(epos.bh); brelse(oepos.bh); |
1da177e4c
|
555 |
|
28de7948a
|
556 |
error_return: |
1e7933def
|
557 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
558 559 |
return; } |
cb00ea352
|
560 561 562 563 |
static int udf_table_prealloc_blocks(struct super_block *sb, struct inode *inode, struct inode *table, uint16_t partition, uint32_t first_block, uint32_t block_count) |
1da177e4c
|
564 565 566 |
{ struct udf_sb_info *sbi = UDF_SB(sb); int alloc_count = 0; |
ff116fc8d
|
567 |
uint32_t elen, adsize; |
5ca4e4be8
|
568 |
struct kernel_lb_addr eloc; |
ff116fc8d
|
569 |
struct extent_position epos; |
1da177e4c
|
570 |
int8_t etype = -1; |
48d6d8ff7
|
571 |
struct udf_inode_info *iinfo; |
1da177e4c
|
572 |
|
3391faa4f
|
573 |
if (first_block >= sbi->s_partmaps[partition].s_partition_len) |
1da177e4c
|
574 |
return 0; |
48d6d8ff7
|
575 576 |
iinfo = UDF_I(table); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
5ca4e4be8
|
577 |
adsize = sizeof(struct short_ad); |
48d6d8ff7
|
578 |
else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
5ca4e4be8
|
579 |
adsize = sizeof(struct long_ad); |
1da177e4c
|
580 581 |
else return 0; |
1e7933def
|
582 |
mutex_lock(&sbi->s_alloc_mutex); |
ff116fc8d
|
583 |
epos.offset = sizeof(struct unallocSpaceEntry); |
48d6d8ff7
|
584 |
epos.block = iinfo->i_location; |
ff116fc8d
|
585 |
epos.bh = NULL; |
1da177e4c
|
586 |
eloc.logicalBlockNum = 0xFFFFFFFF; |
28de7948a
|
587 588 |
while (first_block != eloc.logicalBlockNum && (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { |
1da177e4c
|
589 590 |
udf_debug("eloc=%d, elen=%d, first_block=%d ", |
cb00ea352
|
591 |
eloc.logicalBlockNum, elen, first_block); |
28de7948a
|
592 |
; /* empty loop body */ |
1da177e4c
|
593 |
} |
cb00ea352
|
594 |
if (first_block == eloc.logicalBlockNum) { |
ff116fc8d
|
595 |
epos.offset -= adsize; |
1da177e4c
|
596 597 |
alloc_count = (elen >> sb->s_blocksize_bits); |
363504628
|
598 |
if (alloc_count > block_count) { |
1da177e4c
|
599 600 601 |
alloc_count = block_count; eloc.logicalBlockNum += alloc_count; elen -= (alloc_count << sb->s_blocksize_bits); |
97e961fdb
|
602 |
udf_write_aext(table, &epos, &eloc, |
4b11111ab
|
603 604 605 606 |
(etype << 30) | elen, 1); } else udf_delete_aext(table, epos, eloc, (etype << 30) | elen); |
28de7948a
|
607 |
} else { |
1da177e4c
|
608 |
alloc_count = 0; |
28de7948a
|
609 |
} |
1da177e4c
|
610 |
|
3bf25cb40
|
611 |
brelse(epos.bh); |
1da177e4c
|
612 |
|
146bca72c
|
613 614 |
if (alloc_count) udf_add_free_space(sb, partition, -alloc_count); |
1e7933def
|
615 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
616 617 |
return alloc_count; } |
cb00ea352
|
618 619 620 621 |
static int udf_table_new_block(struct super_block *sb, struct inode *inode, struct inode *table, uint16_t partition, uint32_t goal, int *err) |
1da177e4c
|
622 623 624 625 |
{ struct udf_sb_info *sbi = UDF_SB(sb); uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; uint32_t newblock = 0, adsize; |
ff116fc8d
|
626 |
uint32_t elen, goal_elen = 0; |
5ca4e4be8
|
627 |
struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); |
ff116fc8d
|
628 |
struct extent_position epos, goal_epos; |
1da177e4c
|
629 |
int8_t etype; |
48d6d8ff7
|
630 |
struct udf_inode_info *iinfo = UDF_I(table); |
1da177e4c
|
631 632 |
*err = -ENOSPC; |
48d6d8ff7
|
633 |
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
5ca4e4be8
|
634 |
adsize = sizeof(struct short_ad); |
48d6d8ff7
|
635 |
else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
5ca4e4be8
|
636 |
adsize = sizeof(struct long_ad); |
1da177e4c
|
637 638 |
else return newblock; |
1e7933def
|
639 |
mutex_lock(&sbi->s_alloc_mutex); |
3391faa4f
|
640 |
if (goal >= sbi->s_partmaps[partition].s_partition_len) |
1da177e4c
|
641 |
goal = 0; |
4b11111ab
|
642 643 644 645 |
/* We search for the closest matching block to goal. If we find a exact hit, we stop. Otherwise we keep going till we run out of extents. We store the buffer_head, bloc, and extoffset of the current closest match and use that when we are done. |
cb00ea352
|
646 |
*/ |
ff116fc8d
|
647 |
epos.offset = sizeof(struct unallocSpaceEntry); |
48d6d8ff7
|
648 |
epos.block = iinfo->i_location; |
ff116fc8d
|
649 |
epos.bh = goal_epos.bh = NULL; |
1da177e4c
|
650 |
|
28de7948a
|
651 652 |
while (spread && (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { |
cb00ea352
|
653 |
if (goal >= eloc.logicalBlockNum) { |
4b11111ab
|
654 655 |
if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) |
1da177e4c
|
656 657 658 |
nspread = 0; else nspread = goal - eloc.logicalBlockNum - |
28de7948a
|
659 660 |
(elen >> sb->s_blocksize_bits); } else { |
1da177e4c
|
661 |
nspread = eloc.logicalBlockNum - goal; |
28de7948a
|
662 |
} |
1da177e4c
|
663 |
|
cb00ea352
|
664 |
if (nspread < spread) { |
1da177e4c
|
665 |
spread = nspread; |
cb00ea352
|
666 |
if (goal_epos.bh != epos.bh) { |
3bf25cb40
|
667 |
brelse(goal_epos.bh); |
ff116fc8d
|
668 |
goal_epos.bh = epos.bh; |
3bf25cb40
|
669 |
get_bh(goal_epos.bh); |
1da177e4c
|
670 |
} |
ff116fc8d
|
671 672 |
goal_epos.block = epos.block; goal_epos.offset = epos.offset - adsize; |
1da177e4c
|
673 674 675 676 |
goal_eloc = eloc; goal_elen = (etype << 30) | elen; } } |
3bf25cb40
|
677 |
brelse(epos.bh); |
1da177e4c
|
678 |
|
cb00ea352
|
679 |
if (spread == 0xFFFFFFFF) { |
3bf25cb40
|
680 |
brelse(goal_epos.bh); |
1e7933def
|
681 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
682 683 684 685 686 687 688 689 690 |
return 0; } /* Only allocate blocks from the beginning of the extent. That way, we only delete (empty) extents, never have to insert an extent because of splitting */ /* This works, but very poorly.... */ newblock = goal_eloc.logicalBlockNum; |
cb00ea352
|
691 |
goal_eloc.logicalBlockNum++; |
1da177e4c
|
692 |
goal_elen -= sb->s_blocksize; |
1da177e4c
|
693 694 |
if (goal_elen) |
97e961fdb
|
695 |
udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1); |
1da177e4c
|
696 |
else |
ff116fc8d
|
697 |
udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); |
3bf25cb40
|
698 |
brelse(goal_epos.bh); |
1da177e4c
|
699 |
|
146bca72c
|
700 |
udf_add_free_space(sb, partition, -1); |
1da177e4c
|
701 |
|
1e7933def
|
702 |
mutex_unlock(&sbi->s_alloc_mutex); |
1da177e4c
|
703 704 705 |
*err = 0; return newblock; } |
97e961fdb
|
706 707 708 |
void udf_free_blocks(struct super_block *sb, struct inode *inode, struct kernel_lb_addr *bloc, uint32_t offset, uint32_t count) |
1da177e4c
|
709 |
{ |
97e961fdb
|
710 |
uint16_t partition = bloc->partitionReferenceNum; |
6c79e987d
|
711 |
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
1da177e4c
|
712 |
|
6c79e987d
|
713 |
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { |
e650b94ad
|
714 715 |
udf_bitmap_free_blocks(sb, inode, map->s_uspace.s_bitmap, bloc, offset, count); |
6c79e987d
|
716 |
} else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { |
e650b94ad
|
717 718 |
udf_table_free_blocks(sb, inode, map->s_uspace.s_table, bloc, offset, count); |
6c79e987d
|
719 |
} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { |
e650b94ad
|
720 721 |
udf_bitmap_free_blocks(sb, inode, map->s_fspace.s_bitmap, bloc, offset, count); |
6c79e987d
|
722 |
} else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { |
e650b94ad
|
723 724 |
udf_table_free_blocks(sb, inode, map->s_fspace.s_table, bloc, offset, count); |
28de7948a
|
725 |
} |
1da177e4c
|
726 |
} |
cb00ea352
|
727 728 729 730 |
inline int udf_prealloc_blocks(struct super_block *sb, struct inode *inode, uint16_t partition, uint32_t first_block, uint32_t block_count) |
1da177e4c
|
731 |
{ |
6c79e987d
|
732 |
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
4b11111ab
|
733 |
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) |
1da177e4c
|
734 |
return udf_bitmap_prealloc_blocks(sb, inode, |
6c79e987d
|
735 |
map->s_uspace.s_bitmap, |
4b11111ab
|
736 737 738 |
partition, first_block, block_count); else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) |
1da177e4c
|
739 |
return udf_table_prealloc_blocks(sb, inode, |
6c79e987d
|
740 |
map->s_uspace.s_table, |
4b11111ab
|
741 742 743 |
partition, first_block, block_count); else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) |
1da177e4c
|
744 |
return udf_bitmap_prealloc_blocks(sb, inode, |
6c79e987d
|
745 |
map->s_fspace.s_bitmap, |
4b11111ab
|
746 747 748 |
partition, first_block, block_count); else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) |
1da177e4c
|
749 |
return udf_table_prealloc_blocks(sb, inode, |
6c79e987d
|
750 |
map->s_fspace.s_table, |
4b11111ab
|
751 752 753 |
partition, first_block, block_count); else |
1da177e4c
|
754 755 |
return 0; } |
cb00ea352
|
756 757 758 |
inline int udf_new_block(struct super_block *sb, struct inode *inode, uint16_t partition, uint32_t goal, int *err) |
1da177e4c
|
759 |
{ |
6c79e987d
|
760 |
struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
3bf25cb40
|
761 |
|
4b11111ab
|
762 763 |
if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) return udf_bitmap_new_block(sb, inode, |
6c79e987d
|
764 |
map->s_uspace.s_bitmap, |
28de7948a
|
765 |
partition, goal, err); |
4b11111ab
|
766 |
else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) |
1da177e4c
|
767 |
return udf_table_new_block(sb, inode, |
6c79e987d
|
768 |
map->s_uspace.s_table, |
28de7948a
|
769 |
partition, goal, err); |
4b11111ab
|
770 |
else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) |
1da177e4c
|
771 |
return udf_bitmap_new_block(sb, inode, |
6c79e987d
|
772 |
map->s_fspace.s_bitmap, |
28de7948a
|
773 |
partition, goal, err); |
4b11111ab
|
774 |
else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) |
1da177e4c
|
775 |
return udf_table_new_block(sb, inode, |
6c79e987d
|
776 |
map->s_fspace.s_table, |
28de7948a
|
777 |
partition, goal, err); |
4b11111ab
|
778 |
else { |
1da177e4c
|
779 780 781 782 |
*err = -EIO; return 0; } } |