diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/balloc.c linux/fs/udf/balloc.c --- linux-2.4.5-pre1/fs/udf/balloc.c Tue Sep 5 23:07:30 2000 +++ linux/fs/udf/balloc.c Tue May 8 17:51:29 2001 @@ -85,14 +85,14 @@ #define find_first_one_bit(addr, size)\ find_next_one_bit((addr), (size), 0) -static int read_block_bitmap(struct super_block * sb, Uint32 bitmap, - unsigned int block, unsigned long bitmap_nr) +static int read_block_bitmap(struct super_block * sb, + struct udf_bitmap *bitmap, unsigned int block, unsigned long bitmap_nr) { struct buffer_head *bh = NULL; int retval = 0; lb_addr loc; - loc.logicalBlockNum = bitmap; + loc.logicalBlockNum = bitmap->s_extPosition; loc.partitionReferenceNum = UDF_SB_PARTITION(sb); bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block), sb->s_blocksize); @@ -100,110 +100,50 @@ { retval = -EIO; } - UDF_SB_BLOCK_BITMAP_NUMBER(sb, bitmap_nr) = block; - UDF_SB_BLOCK_BITMAP(sb, bitmap_nr) = bh; + bitmap->s_block_bitmap[bitmap_nr] = bh; return retval; } -static int __load_block_bitmap(struct super_block * sb, Uint32 bitmap, - unsigned int block_group) +static int __load_block_bitmap(struct super_block * sb, + struct udf_bitmap *bitmap, unsigned int block_group) { - int i, j, retval = 0; - unsigned long block_bitmap_number; - struct buffer_head * block_bitmap = NULL; - int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); + int retval = 0; + int nr_groups = bitmap->s_nr_groups; if (block_group >= nr_groups) { udf_debug("block_group (%d) > nr_groups (%d)\n", block_group, nr_groups); } - if (nr_groups <= UDF_MAX_BLOCK_LOADED) + if (bitmap->s_block_bitmap[block_group]) + return block_group; + else { - if (UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - if (UDF_SB_BLOCK_BITMAP_NUMBER(sb, block_group) == block_group) - return block_group; - } retval = read_block_bitmap(sb, bitmap, block_group, block_group); if (retval < 0) return retval; return block_group; } - - for (i=0; i0; j--) - { - UDF_SB_BLOCK_BITMAP_NUMBER(sb, j) = UDF_SB_BLOCK_BITMAP_NUMBER(sb, j-1); - UDF_SB_BLOCK_BITMAP(sb, j) = UDF_SB_BLOCK_BITMAP(sb, j-1); - } - UDF_SB_BLOCK_BITMAP_NUMBER(sb, 0) = block_bitmap_number; - UDF_SB_BLOCK_BITMAP(sb, 0) = block_bitmap; - - if (!block_bitmap) - retval = read_block_bitmap(sb, bitmap, block_group, 0); - } - else - { - if (UDF_SB_LOADED_BLOCK_BITMAPS(sb) < UDF_MAX_BLOCK_LOADED) - UDF_SB_LOADED_BLOCK_BITMAPS(sb) ++; - else - brelse(UDF_SB_BLOCK_BITMAP(sb, UDF_MAX_BLOCK_LOADED-1)); - for (j=UDF_SB_LOADED_BLOCK_BITMAPS(sb)-1; j>0; j--) - { - UDF_SB_BLOCK_BITMAP_NUMBER(sb, j) = UDF_SB_BLOCK_BITMAP_NUMBER(sb, j-1); - UDF_SB_BLOCK_BITMAP(sb, j) = UDF_SB_BLOCK_BITMAP(sb, j-1); - } - retval = read_block_bitmap(sb, bitmap, block_group, 0); - } - return retval; } -static inline int load_block_bitmap(struct super_block *sb, Uint32 bitmap, - unsigned int block_group) +static inline int load_block_bitmap(struct super_block *sb, + struct udf_bitmap *bitmap, unsigned int block_group) { int slot; - int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); - if (UDF_SB_LOADED_BLOCK_BITMAPS(sb) > 0 && - UDF_SB_BLOCK_BITMAP_NUMBER(sb, 0) == block_group && - UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - return 0; - } - else if (nr_groups <= UDF_MAX_BLOCK_LOADED && - UDF_SB_BLOCK_BITMAP_NUMBER(sb, block_group) == block_group && - UDF_SB_BLOCK_BITMAP(sb, block_group)) - { - slot = block_group; - } - else - { - slot = __load_block_bitmap(sb, bitmap, block_group); - } + slot = __load_block_bitmap(sb, bitmap, block_group); if (slot < 0) return slot; - if (!UDF_SB_BLOCK_BITMAP(sb, slot)) + if (!bitmap->s_block_bitmap[slot]) return -EIO; return slot; } -static void udf_bitmap_free_blocks(const struct inode * inode, Uint32 bitmap, - lb_addr bloc, Uint32 offset, Uint32 count) +static void udf_bitmap_free_blocks(const struct inode * inode, + struct udf_bitmap *bitmap, lb_addr bloc, Uint32 offset, Uint32 count) { struct buffer_head * bh = NULL; unsigned long block; @@ -250,7 +190,7 @@ if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; for (i=0; i < count; i++) { if (udf_set_bit(bit + i, bh->b_data)) @@ -283,8 +223,9 @@ return; } -static int udf_bitmap_prealloc_blocks(const struct inode * inode, Uint32 bitmap, - Uint16 partition, Uint32 first_block, Uint32 block_count) +static int udf_bitmap_prealloc_blocks(const struct inode * inode, + struct udf_bitmap *bitmap, Uint16 partition, Uint32 first_block, + Uint32 block_count) { int alloc_count = 0; int bit, block, block_group, group_start; @@ -303,6 +244,9 @@ if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) goto out; + if (first_block + block_count > UDF_SB_PARTLEN(sb, partition)) + block_count = UDF_SB_PARTLEN(sb, partition) - first_block; + repeat: nr_groups = (UDF_SB_PARTLEN(sb, partition) + (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); @@ -313,7 +257,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto out; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; bit = block % (sb->s_blocksize << 3); @@ -349,8 +293,8 @@ return alloc_count; } -static int udf_bitmap_new_block(const struct inode * inode, Uint32 bitmap, - Uint16 partition, Uint32 goal, int *err) +static int udf_bitmap_new_block(const struct inode * inode, + struct udf_bitmap *bitmap, Uint16 partition, Uint32 goal, int *err) { int tmp, newbit, bit=0, block, block_group, group_start; int end_goal, nr_groups, bitmap_nr, i; @@ -372,8 +316,7 @@ if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) goal = 0; - nr_groups = (UDF_SB_PARTLEN(sb, partition) + - (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8); + 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); @@ -381,7 +324,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); if ((ptr - ((char *)bh->b_data)) < sb->s_blocksize) @@ -421,7 +364,7 @@ bitmap_nr = load_block_bitmap(sb, bitmap, block_group); if (bitmap_nr < 0) goto error_return; - bh = UDF_SB_BLOCK_BITMAP(sb, bitmap_nr); + bh = bitmap->s_block_bitmap[bitmap_nr]; if (i < nr_groups) { ptr = memscan((char *)bh->b_data + group_start, 0xFF, sb->s_blocksize - group_start); @@ -497,19 +440,492 @@ return 0; } +static void udf_table_free_blocks(const struct inode * inode, + struct inode * table, lb_addr bloc, Uint32 offset, Uint32 count) +{ + struct super_block * sb; + Uint32 start, end; + Uint32 nextoffset, oextoffset, elen; + lb_addr nbloc, obloc, eloc; + struct buffer_head *obh, *nbh; + char etype; + int i; + + udf_debug("ino=%ld, bloc=%d, offset=%d, count=%d\n", + inode->i_ino, bloc.logicalBlockNum, offset, count); + + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device"); + return; + } + + if (table == NULL) + return; + + lock_super(sb); + if (bloc.logicalBlockNum < 0 || + (bloc.logicalBlockNum + count) > UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)) + { + udf_debug("%d < %d || %d + %d > %d\n", + bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, + UDF_SB_PARTLEN(sb, bloc.partitionReferenceNum)); + goto error_return; + } + + /* We do this up front - There are some error conditions that could occure, + but.. oh well */ + DQUOT_FREE_BLOCK(sb, inode, count); + if (UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+count); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + + start = bloc.logicalBlockNum + offset; + end = bloc.logicalBlockNum + offset + count - 1; + + oextoffset = nextoffset = sizeof(struct UnallocatedSpaceEntry); + elen = 0; + obloc = nbloc = UDF_I_LOCATION(table); + + obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0), sb->s_blocksize); + atomic_inc(&nbh->b_count); + + while (count && (etype = + udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) + { + if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == + start)) + { + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) + { + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + start += ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + elen = (etype << 30) | (0x40000000 - sb->s_blocksize); + } + else + { + elen = (etype << 30) | + (elen + (count << sb->s_blocksize_bits)); + start += count; + count = 0; + } + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); + } + else if (eloc.logicalBlockNum == (end + 1)) + { + if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) + { + count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + end -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + eloc.logicalBlockNum -= + ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits); + elen = (etype << 30) | (0x40000000 - sb->s_blocksize); + } + else + { + eloc.logicalBlockNum = start; + elen = (etype << 30) | + (elen + (count << sb->s_blocksize_bits)); + end -= count; + count = 0; + } + udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); + } + + if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) + { + i = -1; + obloc = nbloc; + udf_release_data(obh); + atomic_inc(&nbh->b_count); + obh = nbh; + oextoffset = 0; + } + else + oextoffset = nextoffset; + } + + if (count) + { + /* 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 :) + + 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. + */ + + int adsize; + short_ad *sad = NULL; + long_ad *lad = NULL; + struct AllocExtDesc *aed; + + eloc.logicalBlockNum = start; + elen = (EXTENT_RECORDED_ALLOCATED << 30) | + (count << sb->s_blocksize_bits); + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + { + udf_release_data(obh); + udf_release_data(nbh); + goto error_return; + } + + if (nextoffset + (2 * adsize) > sb->s_blocksize) + { + char *sptr, *dptr; + int loffset; + + udf_release_data(obh); + obh = nbh; + obloc = nbloc; + oextoffset = nextoffset; + + /* Steal a block from the extent being free'd */ + nbloc.logicalBlockNum = eloc.logicalBlockNum; + eloc.logicalBlockNum ++; + elen -= sb->s_blocksize; + + if (!(nbh = udf_tread(sb, + udf_get_lb_pblock(sb, nbloc, 0), + sb->s_blocksize))) + { + udf_release_data(obh); + goto error_return; + } + aed = (struct AllocExtDesc *)(nbh->b_data); + aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); + if (nextoffset + adsize > sb->s_blocksize) + { + loffset = nextoffset; + aed->lengthAllocDescs = cpu_to_le32(adsize); + sptr = (obh)->b_data + nextoffset - adsize; + dptr = nbh->b_data + sizeof(struct AllocExtDesc); + memcpy(dptr, sptr, adsize); + nextoffset = sizeof(struct AllocExtDesc) + adsize; + } + else + { + loffset = nextoffset + adsize; + aed->lengthAllocDescs = cpu_to_le32(0); + sptr = (obh)->b_data + nextoffset; + nextoffset = sizeof(struct AllocExtDesc); + + if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr))) + { + aed = (struct AllocExtDesc *)(obh)->b_data; + aed->lengthAllocDescs = + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); + } + else + { + UDF_I_LENALLOC(table) += adsize; + mark_inode_dirty(table); + } + } + udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1, + nbloc.logicalBlockNum, sizeof(tag)); + switch (UDF_I_ALLOCTYPE(table)) + { + case ICB_FLAG_AD_SHORT: + { + sad = (short_ad *)sptr; + sad->extLength = cpu_to_le32( + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | + sb->s_blocksize); + sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum); + break; + } + case ICB_FLAG_AD_LONG: + { + lad = (long_ad *)sptr; + lad->extLength = cpu_to_le32( + EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | + sb->s_blocksize); + lad->extLocation = cpu_to_lelb(nbloc); + break; + } + } + udf_update_tag(obh->b_data, loffset); + mark_buffer_dirty(obh); + } + + if (elen) /* It's possible that stealing the block emptied the extent */ + { + udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1); + + if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr))) + { + UDF_I_LENALLOC(table) += adsize; + mark_inode_dirty(table); + } + else + { + aed = (struct AllocExtDesc *)nbh->b_data; + aed->lengthAllocDescs = + cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); + udf_update_tag(nbh->b_data, nextoffset); + mark_buffer_dirty(nbh); + } + } + } + + udf_release_data(nbh); + udf_release_data(obh); + +error_return: + sb->s_dirt = 1; + unlock_super(sb); + return; +} + +static int udf_table_prealloc_blocks(const struct inode * inode, + struct inode *table, Uint16 partition, Uint32 first_block, + Uint32 block_count) +{ + struct super_block *sb; + int alloc_count = 0; + Uint32 extoffset, elen, adsize; + lb_addr bloc, eloc; + struct buffer_head *bh; + char etype = -1; + + udf_debug("ino=%ld, partition=%d, first_block=%d, block_count=%d\n", + inode->i_ino, partition, first_block, block_count); + + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device\n"); + return 0; + } + + if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) + return 0; + + if (table == NULL) + return 0; + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + return 0; + + lock_super(sb); + + extoffset = sizeof(struct UnallocatedSpaceEntry); + bloc = UDF_I_LOCATION(table); + + bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize); + eloc.logicalBlockNum = 0xFFFFFFFF; + + while (first_block != eloc.logicalBlockNum && (etype = + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) + { + udf_debug("eloc=%d, elen=%d, first_block=%d\n", + eloc.logicalBlockNum, elen, first_block); + ; /* empty loop body */ + } + + if (first_block == eloc.logicalBlockNum) + { + extoffset -= adsize; + + alloc_count = (elen >> sb->s_blocksize_bits); + if (alloc_count > block_count) + { + alloc_count = block_count; + eloc.logicalBlockNum += alloc_count; + elen -= (alloc_count << sb->s_blocksize_bits); + udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1); + } + else + udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh); + } + else + alloc_count = 0; + + udf_release_data(bh); + + if (alloc_count && UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[partition] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-alloc_count); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + sb->s_dirt = 1; + unlock_super(sb); + udf_debug("alloc_count=%d\n", alloc_count); + return alloc_count; +} + +static int udf_table_new_block(const struct inode * inode, + struct inode *table, Uint16 partition, Uint32 goal, int *err) +{ + struct super_block *sb; + Uint32 spread = 0xFFFFFFFF, nspread; + Uint32 newblock = 0, tmp, adsize; + Uint32 extoffset, goal_extoffset, elen, goal_elen = 0; + lb_addr bloc, goal_bloc, eloc, goal_eloc; + struct buffer_head *bh, *goal_bh; + char etype; + + udf_debug("ino=%ld, partition=%d, goal=%d\n", + inode->i_ino, partition, goal); + + *err = -ENOSPC; + sb = inode->i_sb; + if (!sb) + { + udf_debug("nonexistent device\n"); + return newblock; + } + + if (table == NULL) + return newblock; + + if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(table) == ICB_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + return newblock; + + lock_super(sb); + + if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition)) + goal = 0; + + /* 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. + */ + + extoffset = sizeof(struct UnallocatedSpaceEntry); + bloc = UDF_I_LOCATION(table); + + goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0), sb->s_blocksize); + atomic_inc(&goal_bh->b_count); + + while (spread && (etype = + udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) + { + if (goal >= eloc.logicalBlockNum) + { + if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) + nspread = 0; + else + nspread = goal - eloc.logicalBlockNum - + (elen >> sb->s_blocksize_bits); + } + else + nspread = eloc.logicalBlockNum - goal; + + if (nspread < spread) + { + spread = nspread; + if (goal_bh != bh) + { + udf_release_data(goal_bh); + goal_bh = bh; + atomic_inc(&goal_bh->b_count); + } + goal_bloc = bloc; + goal_extoffset = extoffset - adsize; + goal_eloc = eloc; + goal_elen = (etype << 30) | elen; + } + } + + udf_release_data(bh); + + if (spread == 0xFFFFFFFF) + { + udf_release_data(goal_bh); + unlock_super(sb); + 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; + goal_eloc.logicalBlockNum ++; + goal_elen -= sb->s_blocksize; + + tmp = udf_get_pblock(sb, newblock, partition, 0); + if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize))) + { + udf_debug("cannot get block %d\n", tmp); + udf_release_data(bh); + unlock_super(sb); + return 0; + } + memset(bh->b_data, 0, sb->s_blocksize); + mark_buffer_uptodate(bh, 1); + mark_buffer_dirty(bh); + udf_release_data(bh); + + if (goal_elen) + udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1); + else + udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh); + udf_release_data(goal_bh); + + if (UDF_SB_LVIDBH(sb)) + { + UDF_SB_LVID(sb)->freeSpaceTable[partition] = + cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition])-1); + mark_buffer_dirty(UDF_SB_LVIDBH(sb)); + } + + sb->s_dirt = 1; + unlock_super(sb); + *err = 0; + return newblock; +} + inline void udf_free_blocks(const struct inode * inode, lb_addr bloc, - Uint32 offset, Uint32 count) + Uint32 offset, Uint32 count) { if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_free_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_bitmap, + bloc, offset, count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_free_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_uspace.s_table, bloc, offset, count); } else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_free_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_bitmap, + bloc, offset, count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, bloc.partitionReferenceNum) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_free_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[bloc.partitionReferenceNum].s_fspace.s_table, bloc, offset, count); } else @@ -522,13 +938,25 @@ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_prealloc_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap, + partition, first_block, block_count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_prealloc_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table, partition, first_block, block_count); } else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_prealloc_blocks(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap, + partition, first_block, block_count); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_prealloc_blocks(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table, partition, first_block, block_count); } else @@ -541,13 +969,25 @@ if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) { return udf_bitmap_new_block(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_bitmap, + partition, goal, err); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) + { + return udf_table_new_block(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_uspace.s_table, partition, goal, err); } else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_BITMAP) { return udf_bitmap_new_block(inode, - UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.bitmap, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_bitmap, + partition, goal, err); + } + else if (UDF_SB_PARTFLAGS(inode->i_sb, partition) & UDF_PART_FLAG_FREED_TABLE) + { + return udf_table_new_block(inode, + UDF_SB_PARTMAPS(inode->i_sb)[partition].s_fspace.s_table, partition, goal, err); } else @@ -556,4 +996,3 @@ return 0; } } - diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/dir.c linux/fs/udf/dir.c --- linux-2.4.5-pre1/fs/udf/dir.c Fri Feb 9 20:29:44 2001 +++ linux/fs/udf/dir.c Tue May 8 17:51:29 2001 @@ -52,7 +52,7 @@ read: generic_read_dir, readdir: udf_readdir, ioctl: udf_ioctl, - fsync: udf_sync_file, + fsync: udf_fsync_file, }; /* @@ -88,8 +88,9 @@ if ( filp->f_pos == 0 ) { - if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR)) + if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) return 0; + filp->f_pos ++; } result = do_udf_readdir(dir, filp, filldir, dirent); @@ -104,19 +105,21 @@ struct FileIdentDesc *fi=NULL; struct FileIdentDesc cfi; int block, iblock; - loff_t nf_pos = filp->f_pos; + loff_t nf_pos = filp->f_pos - 1; int flen; char fname[255]; char *nameptr; Uint16 liu; Uint8 lfi; loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2; - struct buffer_head * bh = NULL; + struct buffer_head * bh = NULL, * tmp, * bha[16]; lb_addr bloc, eloc; Uint32 extoffset, elen, offset; + int i, num; + unsigned int dt_type; if (nf_pos >= size) - return 1; + return 0; if (nf_pos == 0) nf_pos = (udf_ext0_offset(dir) >> 2); @@ -125,6 +128,7 @@ if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -139,18 +143,40 @@ else { udf_release_data(bh); - return 0; + return -ENOENT; } if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) { udf_release_data(bh); - return 0; + return -EIO; + } + + if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) + { + i = 16 >> (dir->i_sb->s_blocksize_bits - 9); + if (i+offset > (elen >> dir->i_sb->s_blocksize_bits)) + i = (elen >> dir->i_sb->s_blocksize_bits)-offset; + for (num=0; i>0; i--) + { + block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i); + tmp = udf_tgetblk(dir->i_sb, block, dir->i_sb->s_blocksize); + if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) + bha[num++] = tmp; + else + brelse(tmp); + } + if (num) + { + ll_rw_block(READA, num, bha); + for (i=0; if_pos = nf_pos; + filp->f_pos = nf_pos + 1; fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh); @@ -160,7 +186,7 @@ udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - return 1; + return -ENOENT; } liu = le16_to_cpu(cfi.lengthOfImpUse); @@ -196,44 +222,39 @@ continue; } - iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0); - - if (!lfi) /* parent directory */ - { - if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR)) + if ( cfi.fileCharacteristics & FILE_PARENT ) + { + iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0); + flen = 2; + memcpy(fname, "..", flen); + dt_type = DT_DIR; + } + else + { + iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0); + flen = udf_get_filename(nameptr, fname, lfi); + dt_type = DT_UNKNOWN; + } + + if (flen) + { + if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - return 1; - } - } - else - { - if ((flen = udf_get_filename(nameptr, fname, lfi))) - { - if (filldir(dirent, fname, flen, filp->f_pos, iblock, DT_UNKNOWN)) - { - if (fibh.sbh != fibh.ebh) - udf_release_data(fibh.ebh); - udf_release_data(fibh.sbh); - udf_release_data(bh); - return 1; /* halt enum */ - } + return 0; } } } /* end while */ - filp->f_pos = nf_pos; + filp->f_pos = nf_pos + 1; if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); - if ( filp->f_pos >= size) - return 1; - else - return 0; + return 0; } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/directory.c linux/fs/udf/directory.c --- linux-2.4.5-pre1/fs/udf/directory.c Thu Mar 2 20:17:32 2000 +++ linux/fs/udf/directory.c Tue May 8 17:51:29 2001 @@ -92,7 +92,8 @@ Uint32 *offset, struct buffer_head **bh) { struct FileIdentDesc *fi; - int block; + int i, num, block; + struct buffer_head * tmp, * bha[16]; fibh->soffset = fibh->eoffset; @@ -119,6 +120,28 @@ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) return NULL; fibh->soffset = fibh->eoffset = 0; + + if (!(*offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) + { + i = 16 >> (dir->i_sb->s_blocksize_bits - 9); + if (i+*offset > (*elen >> dir->i_sb->s_blocksize_bits)) + i = (*elen >> dir->i_sb->s_blocksize_bits)-*offset; + for (num=0; i>0; i--) + { + block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset+i); + tmp = udf_tgetblk(dir->i_sb, block, dir->i_sb->s_blocksize); + if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) + bha[num++] = tmp; + else + brelse(tmp); + } + if (num) + { + ll_rw_block(READA, num, bha); + for (i=0; isbh != fibh->ebh) { diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/file.c linux/fs/udf/file.c --- linux-2.4.5-pre1/fs/udf/file.c Sun Jan 28 22:28:09 2001 +++ linux/fs/udf/file.c Tue May 8 17:51:29 2001 @@ -43,7 +43,7 @@ #include "udf_i.h" #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page * page) +static int udf_adinicb_writepage(struct page *page) { struct inode *inode = page->mapping->host; @@ -55,10 +55,10 @@ PAGE_BUG(page); kaddr = kmap(page); - memset(kaddr, 0, PAGE_CACHE_SIZE); block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); - memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size); + memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size); + mark_buffer_dirty(bh); brelse(bh); flush_dcache_page(page); SetPageUptodate(page); @@ -67,7 +67,7 @@ return 0; } -static int udf_adinicb_writepage(struct page *page) +static int udf_adinicb_readpage(struct file *file, struct page * page) { struct inode *inode = page->mapping->host; @@ -79,10 +79,10 @@ PAGE_BUG(page); kaddr = kmap(page); + memset(kaddr, 0, PAGE_CACHE_SIZE); block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize); - memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size); - mark_buffer_dirty(bh); + memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size); brelse(bh); SetPageUptodate(page); kunmap(page); @@ -121,7 +121,7 @@ struct address_space_operations udf_adinicb_aops = { readpage: udf_adinicb_readpage, writepage: udf_adinicb_writepage, - sync_page: block_sync_page, + sync_page: block_sync_page, prepare_write: udf_adinicb_prepare_write, commit_write: udf_adinicb_commit_write, }; @@ -208,7 +208,6 @@ { int result = -1; struct buffer_head *bh = NULL; - Uint16 ident; long_ad eaicb; Uint8 *ea = NULL; @@ -236,13 +235,14 @@ } /* ok, we need to read the inode */ - bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident); + bh = udf_tread(inode->i_sb, + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize); - if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)) + if (!bh) { - udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY", - inode->i_ino, ident); - return -EFAULT; + udf_debug("bread failed (inode=%ld)\n", inode->i_ino); + return -EIO; } if (UDF_I_EXTENDED_FE(inode) == 0) @@ -299,7 +299,8 @@ */ static int udf_release_file(struct inode * inode, struct file * filp) { - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE) + { lock_kernel(); udf_discard_prealloc(inode); unlock_kernel(); @@ -322,7 +323,7 @@ */ static int udf_open_file(struct inode * inode, struct file * filp) { - if ((inode->i_size & 0xFFFFFFFF00000000ULL) && !(filp->f_flags & O_LARGEFILE)) + if ((inode->i_size & 0xFFFFFFFF80000000ULL) && !(filp->f_flags & O_LARGEFILE)) return -EFBIG; return 0; } @@ -334,7 +335,7 @@ mmap: generic_file_mmap, write: udf_file_write, release: udf_release_file, - fsync: udf_sync_file, + fsync: udf_fsync_file, }; struct inode_operations udf_file_inode_operations = { diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/fsync.c linux/fs/udf/fsync.c --- linux-2.4.5-pre1/fs/udf/fsync.c Fri Jun 30 01:23:11 2000 +++ linux/fs/udf/fsync.c Tue May 8 17:51:29 2001 @@ -96,7 +96,7 @@ * even pass file to fsync ? */ -int udf_sync_file(struct file * file, struct dentry *dentry, int datasync) +int udf_fsync_file(struct file * file, struct dentry *dentry, int datasync) { int wait, err = 0; struct inode *inode = dentry->d_inode; diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/ialloc.c linux/fs/udf/ialloc.c --- linux-2.4.5-pre1/fs/udf/ialloc.c Fri Nov 17 20:35:27 2000 +++ linux/fs/udf/ialloc.c Tue May 8 17:51:29 2001 @@ -79,6 +79,7 @@ sb = dir->i_sb; inode = new_inode(sb); + if (!inode) { *err = -ENOMEM; @@ -114,7 +115,8 @@ } inode->i_mode = mode; inode->i_uid = current->fsuid; - if (dir->i_mode & S_ISGID) { + if (dir->i_mode & S_ISGID) + { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) mode |= S_ISGID; diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/inode.c linux/fs/udf/inode.c --- linux-2.4.5-pre1/fs/udf/inode.c Sun Jan 28 22:28:09 2001 +++ linux/fs/udf/inode.c Tue May 8 17:51:29 2001 @@ -106,23 +106,27 @@ lock_kernel(); if (is_bad_inode(inode)) - { - clear_inode(inode); - goto out; - } + goto no_delete; inode->i_size = 0; udf_truncate(inode); udf_update_inode(inode, IS_SYNC(inode)); udf_free_inode(inode); -out: + + unlock_kernel(); + return; +no_delete: unlock_kernel(); + clear_inode(inode); } void udf_discard_prealloc(struct inode * inode) { - if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB) - udf_trunc(inode); + if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) && + UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB) + { + udf_truncate_extents(inode); + } } static int udf_writepage(struct page *page) @@ -148,7 +152,7 @@ struct address_space_operations udf_aops = { readpage: udf_readpage, writepage: udf_writepage, - sync_page: block_sync_page, + sync_page: block_sync_page, prepare_write: udf_prepare_write, commit_write: generic_commit_write, bmap: udf_bmap, @@ -158,6 +162,7 @@ { struct buffer_head *bh = NULL; struct page *page; + char *kaddr; int block; /* from now on we have normal address_space methods */ @@ -182,7 +187,7 @@ PAGE_BUG(page); if (!Page_Uptodate(page)) { - char *kaddr = kmap(page); + kaddr = kmap(page); memset(kaddr + UDF_I_LENALLOC(inode), 0x00, PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode)); memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode), @@ -288,6 +293,7 @@ eloc.logicalBlockNum = *block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_size; + UDF_I_LENEXTENTS(inode) = elen; extoffset = udf_file_entry_alloc_offset(inode); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0); /* UniqueID stuff */ @@ -361,13 +367,11 @@ int create, int * err) { struct buffer_head dummy; - int error; dummy.b_state = 0; dummy.b_blocknr = -1000; - error = udf_get_block(inode, block, &dummy, create); - *err = error; - if (!error & buffer_mapped(&dummy)) + *err = udf_get_block(inode, block, &dummy, create); + if (!*err && buffer_mapped(&dummy)) { struct buffer_head *bh; bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); @@ -387,22 +391,22 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block, int *err, long *phys, int *new) { - struct buffer_head *pbh = NULL, *cbh = NULL, *result = NULL; + struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL; long_ad laarr[EXTENT_MERGE_SIZE]; Uint32 pextoffset = 0, cextoffset = 0, nextoffset = 0; int count = 0, startnum = 0, endnum = 0; Uint32 elen = 0; - lb_addr eloc, pbloc = UDF_I_LOCATION(inode), cbloc = UDF_I_LOCATION(inode); + lb_addr eloc, pbloc, cbloc, nbloc; int c = 1; int lbcount = 0, b_off = 0, offset = 0; Uint32 newblocknum, newblock; - int etype; + char etype; int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum; char lastblock = 0; pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode); b_off = block << inode->i_sb->s_blocksize_bits; - pbloc = cbloc = UDF_I_LOCATION(inode); + pbloc = cbloc = nbloc = UDF_I_LOCATION(inode); /* find the extent which contains the block we are looking for. alternate between laarr[0] and laarr[1] for locations of the @@ -412,17 +416,25 @@ if (pbh != cbh) { udf_release_data(pbh); - pbh = cbh; atomic_inc(&cbh->b_count); - pbloc = cbloc; + pbh = cbh; + } + if (cbh != nbh) + { + udf_release_data(cbh); + atomic_inc(&nbh->b_count); + cbh = nbh; } lbcount += elen; + pbloc = cbloc; + cbloc = nbloc; + pextoffset = cextoffset; cextoffset = nextoffset; - if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1) + if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1) break; c = !c; @@ -433,7 +445,7 @@ if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED) pgoal = eloc.logicalBlockNum + ((elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize); + inode->i_sb->s_blocksize_bits); count ++; } while (lbcount + elen <= b_off); @@ -451,10 +463,11 @@ elen = (EXTENT_RECORDED_ALLOCATED << 30) | ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - etype = udf_write_aext(inode, cbloc, &cextoffset, eloc, elen, &cbh, 1); + etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1); } udf_release_data(pbh); udf_release_data(cbh); + udf_release_data(nbh); newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset); *phys = newblock; return NULL; @@ -470,6 +483,9 @@ (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); + UDF_I_LENEXTENTS(inode) = + (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) & + ~(inode->i_sb->s_blocksize - 1); } c = !c; laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | @@ -494,7 +510,7 @@ /* if the current block is located in a extent, read the next extent */ if (etype != -1) { - if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 0)) != -1) + if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1) { laarr[c+1].extLength = (etype << 30) | elen; laarr[c+1].extLocation = eloc; @@ -505,7 +521,11 @@ else lastblock = 1; } - udf_release_data(cbh); + udf_release_data(nbh); + if (!pbh) + pbh = cbh; + else + udf_release_data(cbh); /* if the current extent is not recorded but allocated, get the block in the extent corresponding to the requested block */ @@ -529,6 +549,7 @@ *err = -ENOSPC; return NULL; } + UDF_I_LENEXTENTS(inode) += inode->i_sb->s_blocksize; } /* if the extent the requsted block is located in contains multiple blocks, @@ -629,17 +650,24 @@ { int start, length = 0, currlength = 0, i; - if (*endnum >= (c+1) && !lastblock) - return; - - if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) + if (*endnum >= (c+1)) { - start = c+1; - length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) + - inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits); + if (!lastblock) + return; + else + start = c; } else - start = c; + { + if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) + { + start = c+1; + length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) + + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits); + } + else + start = c; + } for (i=start+1; i<=*endnum; i++) { @@ -667,6 +695,7 @@ if (numalloc) { + UDF_I_LENEXTENTS(inode) += numalloc << inode->i_sb->s_blocksize_bits; if (start == (c+1)) laarr[start].extLength += (numalloc << inode->i_sb->s_blocksize_bits); @@ -784,7 +813,7 @@ { udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0); udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation, - laarr[i].extLength, pbh, 1); + laarr[i].extLength, *pbh, 1); } } @@ -800,29 +829,6 @@ if (!bh) return NULL; -#if 0 - if (create && - S_ISDIR(inode->i_mode) && - inode->i_blocks > prev_blocks) - { - int i; - struct buffer_head *tmp_bh = NULL; - - for (i=1; - i < UDF_DEFAULT_PREALLOC_DIR_BLOCKS; - i++) - { - tmp_bh = udf_getblk(inode, block+i, create, err); - if (!tmp_bh) - { - udf_release_data(bh); - return 0; - } - udf_release_data(tmp_bh); - } - } -#endif - if (buffer_uptodate(bh)) return bh; ll_rw_block(READ, 1, &bh); @@ -834,6 +840,62 @@ return NULL; } +void udf_truncate(struct inode * inode) +{ + int offset; + struct buffer_head *bh; + int err; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + return; + + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) + { + if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + + inode->i_size)) + { + udf_expand_file_adinicb(inode, inode->i_size, &err); + if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) + { + inode->i_size = UDF_I_LENALLOC(inode); + return; + } + else + udf_truncate_extents(inode); + } + else + { + offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) + + udf_file_entry_alloc_offset(inode); + + if ((bh = udf_tread(inode->i_sb, + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize))) + { + memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset); + mark_buffer_dirty(bh); + udf_release_data(bh); + } + UDF_I_LENALLOC(inode) = inode->i_size; + } + } + else + { + block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block); + udf_truncate_extents(inode); + } + + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME; + if (IS_SYNC(inode)) + udf_sync_inode (inode); + else + mark_inode_dirty(inode); +} + /* * udf_read_inode * @@ -891,7 +953,8 @@ return; } - if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY) + if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY && + ident != TID_UNALLOCATED_SPACE_ENTRY) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n", inode->i_ino, ident); @@ -969,16 +1032,24 @@ fe = (struct FileEntry *)bh->b_data; efe = (struct ExtendedFileEntry *)bh->b_data; - if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) - UDF_I_EXTENDED_FE(inode) = 1; - else /* fe->descTag.tagIdent == TID_FILE_ENTRY */ - UDF_I_EXTENDED_FE(inode) = 0; - if (le16_to_cpu(fe->icbTag.strategyType) == 4) UDF_I_STRAT4096(inode) = 0; else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */ UDF_I_STRAT4096(inode) = 1; + UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK; + if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) + UDF_I_EXTENDED_FE(inode) = 1; + else if (fe->descTag.tagIdent == TID_FILE_ENTRY) + UDF_I_EXTENDED_FE(inode) = 0; + else if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + UDF_I_LENALLOC(inode) = + le32_to_cpu( + ((struct UnallocatedSpaceEntry *)bh->b_data)->lengthAllocDescs); + return; + } + inode->i_uid = le32_to_cpu(fe->uid); if ( inode->i_uid == -1 ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid; @@ -990,6 +1061,7 @@ inode->i_nlink = 1; inode->i_size = le64_to_cpu(fe->informationLength); + UDF_I_LENEXTENTS(inode) = inode->i_size; inode->i_mode = udf_convert_permissions(fe); inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; @@ -997,8 +1069,6 @@ UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; UDF_I_NEXT_ALLOC_GOAL(inode) = 0; - UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK; - if (UDF_I_EXTENDED_FE(inode) == 0) { inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << @@ -1221,8 +1291,9 @@ int err = 0; bh = udf_tread(inode->i_sb, - udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), - inode->i_sb->s_blocksize); + udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0), + inode->i_sb->s_blocksize); + if (!bh) { udf_debug("bread failure\n"); @@ -1242,6 +1313,27 @@ UDF_I_NEW_INODE(inode) = 0; } + if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + struct UnallocatedSpaceEntry *use = + (struct UnallocatedSpaceEntry *)bh->b_data; + + use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); + crclen = sizeof(struct UnallocatedSpaceEntry) + UDF_I_LENALLOC(inode) - + sizeof(tag); + use->descTag.descCRCLength = cpu_to_le16(crclen); + use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0)); + + use->descTag.tagChecksum = 0; + for (i=0; i<16; i++) + if (i != 4) + use->descTag.tagChecksum += ((Uint8 *)&(use->descTag))[i]; + + mark_buffer_dirty(bh); + udf_release_data(bh); + return err; + } + if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid) fe->uid = cpu_to_le32(inode->i_uid); @@ -1305,7 +1397,10 @@ if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode))) fe->accessTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode))) + { fe->modificationTime = cpu_to_lets(cpu_time); + fe->attrTime = cpu_to_lets(cpu_time); + } memset(&(fe->impIdent), 0, sizeof(EntityID)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1327,7 +1422,10 @@ if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode))) efe->modificationTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode))) + { efe->createTime = cpu_to_lets(cpu_time); + efe->attrTime = cpu_to_lets(cpu_time); + } memset(&(efe->impIdent), 0, sizeof(EntityID)); strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1444,12 +1542,19 @@ { memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr)); __udf_read_inode(inode); + if (is_bad_inode(inode)) + { + iput(inode); + return NULL; + } } if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) ) { udf_debug("block=%d, partition=%d out of range\n", ino.logicalBlockNum, ino.partitionReferenceNum); + make_bad_inode(inode); + iput(inode); return NULL; } @@ -1551,6 +1656,7 @@ EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | inode->i_sb->s_blocksize); lad->extLocation = cpu_to_lelb(*bloc); + memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } } @@ -1560,7 +1666,7 @@ *bh = nbh; } - ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, bh, inc); + ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc); if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { @@ -1580,15 +1686,15 @@ } int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset, - lb_addr eloc, Uint32 elen, struct buffer_head **bh, int inc) + lb_addr eloc, Uint32 elen, struct buffer_head *bh, int inc) { int adsize; short_ad *sad = NULL; long_ad *lad = NULL; - if (!(*bh)) + if (!(bh)) { - if (!(*bh = udf_tread(inode->i_sb, + if (!(bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0), inode->i_sb->s_blocksize))) { @@ -1597,6 +1703,8 @@ return -1; } } + else + atomic_inc(&bh->b_count); if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT) adsize = sizeof(short_ad); @@ -1609,39 +1717,42 @@ { case ICB_FLAG_AD_SHORT: { - sad = (short_ad *)((*bh)->b_data + *extoffset); + sad = (short_ad *)((bh)->b_data + *extoffset); sad->extLength = cpu_to_le32(elen); sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); break; } case ICB_FLAG_AD_LONG: { - lad = (long_ad *)((*bh)->b_data + *extoffset); + lad = (long_ad *)((bh)->b_data + *extoffset); lad->extLength = cpu_to_le32(elen); lad->extLocation = cpu_to_lelb(eloc); + memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } } if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) { - struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data; - udf_update_tag((*bh)->b_data, + struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh)->b_data; + udf_update_tag((bh)->b_data, le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc)); } else mark_inode_dirty(inode); - mark_buffer_dirty(*bh); + mark_buffer_dirty(bh); if (inc) *extoffset += adsize; + udf_release_data(bh); return (elen >> 30); } int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset, lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc) { + Uint16 tagIdent; int pos, alen; Uint8 etype; @@ -1657,18 +1768,33 @@ } } + tagIdent = ((tag *)(*bh)->b_data)->tagIdent; + if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { - pos = udf_file_entry_alloc_offset(inode); - alen = UDF_I_LENALLOC(inode) + pos; + if (tagIdent == TID_FILE_ENTRY || tagIdent == TID_EXTENDED_FILE_ENTRY || + UDF_I_NEW_INODE(inode)) + { + pos = udf_file_entry_alloc_offset(inode); + alen = UDF_I_LENALLOC(inode) + pos; + } + else if (tagIdent == TID_UNALLOCATED_SPACE_ENTRY) + { + pos = sizeof(struct UnallocatedSpaceEntry); + alen = UDF_I_LENALLOC(inode) + pos; + } + else + return -1; } - else + else if (tagIdent == TID_ALLOC_EXTENT_DESC) { struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data; pos = sizeof(struct AllocExtDesc); alen = le32_to_cpu(aed->lengthAllocDescs) + pos; } + else + return -1; if (!(*extoffset)) *extoffset = pos; @@ -1851,7 +1977,7 @@ while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1) { - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); neloc = oeloc; nelen = (type << 30) | oelen; @@ -1867,7 +1993,7 @@ struct buffer_head *obh; lb_addr obloc; int oextoffset, adsize; - int type; + char type; struct AllocExtDesc *aed; if (!(nbh)) @@ -1901,7 +2027,7 @@ while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) { - udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1); if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { obloc = nbloc; @@ -1917,8 +2043,8 @@ if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { udf_free_blocks(inode, nbloc, 0, 1); - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) -= (adsize * 2); @@ -1935,7 +2061,7 @@ } else { - udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1); + udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1); if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) -= adsize; @@ -1959,7 +2085,8 @@ int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset, lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh) { - int etype, lbcount = 0; + Uint64 lbcount = 0, bcount = block << inode->i_sb->s_blocksize_bits; + char etype; if (block < 0) { @@ -1980,31 +2107,34 @@ { if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1) { - *offset = block - lbcount; + *offset = bcount - lbcount; + UDF_I_LENEXTENTS(inode) = lbcount; return -1; } - lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits); - } while (lbcount <= block); + lbcount += *elen; + } while (lbcount <= bcount); - *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits) - lbcount; + *offset = bcount + *elen - lbcount; return etype; } -long udf_locked_block_map(struct inode *inode, long block) +long udf_block_map(struct inode *inode, long block) { lb_addr eloc, bloc; Uint32 offset, extoffset, elen; struct buffer_head *bh = NULL; int ret; + lock_kernel(); + if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) - ret = udf_get_lb_pblock(inode->i_sb, eloc, offset); + ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits); else ret = 0; + unlock_kernel(); + if (bh) udf_release_data(bh); @@ -2012,14 +2142,4 @@ return udf_fixed_to_variable(ret); else return ret; -} - -long udf_block_map(struct inode *inode, long block) -{ - int ret; - - lock_kernel(); - ret = udf_locked_block_map(inode, block); - unlock_kernel(); - return ret; } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/misc.c linux/fs/udf/misc.c --- linux-2.4.5-pre1/fs/udf/misc.c Mon Mar 20 17:17:43 2000 +++ linux/fs/udf/misc.c Tue May 8 17:51:29 2001 @@ -67,6 +67,15 @@ #if defined(__linux__) && defined(__KERNEL__) extern struct buffer_head * +udf_tgetblk(struct super_block *sb, int block, int size) +{ + if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) + return getblk(sb->s_dev, udf_fixed_to_variable(block), size); + else + return getblk(sb->s_dev, block, size); +} + +extern struct buffer_head * udf_tread(struct super_block *sb, int block, int size) { if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV)) @@ -309,7 +318,7 @@ if ( location != le32_to_cpu(tag_p->tagLocation) ) { - udf_debug("location mismatch block %d, tag %d != %d\n", + udf_debug("location mismatch block %u, tag %u != %u\n", block, le32_to_cpu(tag_p->tagLocation), location); goto error_out; } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/namei.c linux/fs/udf/namei.c --- linux-2.4.5-pre1/fs/udf/namei.c Fri Feb 9 20:29:44 2001 +++ linux/fs/udf/namei.c Tue May 8 17:51:29 2001 @@ -43,8 +43,7 @@ } int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi, - struct udf_fileident_bh *fibh, - Uint8 *impuse, Uint8 *fileident) + struct udf_fileident_bh *fibh, Uint8 *impuse, Uint8 *fileident) { Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag); Uint16 crc; @@ -164,6 +163,7 @@ if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -348,6 +348,12 @@ if (dentry) { + if (!dentry->d_name.len) + { + *err = -EINVAL; + return NULL; + } + if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) ) { *err = -ENAMETOOLONG; @@ -360,16 +366,10 @@ return NULL; } } - else if (dir->i_size != 0) - { - /* WTF??? */ - *err = -ENOENT; - return NULL; - } - else /* .. */ + else namelen = 0; - nfidlen = (sizeof(struct FileIdentDesc) + 0 + namelen + 3) & ~3; + nfidlen = (sizeof(struct FileIdentDesc) + namelen + 3) & ~3; f_pos = (udf_ext0_offset(dir) >> 2); @@ -377,6 +377,7 @@ if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -391,6 +392,7 @@ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize))) { udf_release_data(bh); + *err = -EIO; return NULL; } @@ -406,6 +408,7 @@ udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); udf_release_data(bh); + *err = -EIO; return NULL; } @@ -443,15 +446,19 @@ if (!udf_write_fi(cfi, fi, fibh, NULL, name)) return fi; else + { + *err = -EIO; return NULL; + } } } - + if (!lfi || !dentry) continue; - + if ((flen = udf_get_filename(nameptr, fname, lfi)) && - udf_match(flen, fname, &(dentry->d_name))) { + udf_match(flen, fname, &(dentry->d_name))) + { if (fibh->sbh != fibh->ebh) udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); @@ -533,7 +540,6 @@ block = eloc.logicalBlockNum + ((elen - 1) >> dir->i_sb->s_blocksize_bits); - *err = -ENOSPC; if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err))) { udf_release_data(bh); @@ -584,15 +590,16 @@ if (fibh->sbh != fibh->ebh) udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); + *err = -EIO; return NULL; } } static int udf_delete_entry(struct FileIdentDesc *fi, - struct udf_fileident_bh *fibh, - struct FileIdentDesc *cfi) + struct udf_fileident_bh *fibh, struct FileIdentDesc *cfi) { cfi->fileCharacteristics |= FILE_DELETED; + memset(&(cfi->icb), 0x00, sizeof(long_ad)); return udf_write_fi(cfi, fi, fibh, NULL, NULL); } @@ -700,7 +707,6 @@ inode->i_op = &udf_dir_inode_operations; inode->i_fop = &udf_dir_operations; - inode->i_size = 0; if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err))) { inode->i_nlink--; @@ -762,7 +768,8 @@ fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2; if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED) - { + { + offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { @@ -940,6 +947,7 @@ eloc.logicalBlockNum = block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_sb->s_blocksize; + UDF_I_LENEXTENTS(inode) = elen; extoffset = udf_file_entry_alloc_offset(inode); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0); udf_release_data(bh); @@ -1216,8 +1224,8 @@ if (dir_bh) { dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir)); - udf_update_tag((char *)dir_fi, sizeof(struct FileIdentDesc) + - cpu_to_le16(dir_fi->lengthOfImpUse)); + udf_update_tag((char *)dir_fi, (sizeof(struct FileIdentDesc) + + cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3); if (UDF_I_ALLOCTYPE(old_inode) == ICB_FLAG_AD_IN_ICB) { mark_inode_dirty(old_inode); diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/partition.c linux/fs/udf/partition.c --- linux-2.4.5-pre1/fs/udf/partition.c Sat Apr 14 05:26:07 2001 +++ linux/fs/udf/partition.c Tue May 8 17:51:29 2001 @@ -74,7 +74,7 @@ index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block; } - loc = udf_locked_block_map(UDF_SB_VAT(sb), newblock); + loc = udf_block_map(UDF_SB_VAT(sb), newblock); if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize))) { @@ -162,10 +162,6 @@ mapsize = (rtl * sizeof(Uint32)) + ((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num); sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL); - if (!sdata->s_spar_map) { - printk("couldnt allocate UDF s_spar_map!\n"); - return; - } sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl]; memset(sdata->s_spar_map, 0xFF, mapsize); } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/super.c linux/fs/udf/super.c --- linux-2.4.5-pre1/fs/udf/super.c Mon Apr 23 19:00:21 2001 +++ linux/fs/udf/super.c Tue May 8 17:51:29 2001 @@ -100,14 +100,14 @@ /* Superblock operations */ static struct super_operations udf_sb_ops = { - read_inode: udf_read_inode, + read_inode: udf_read_inode, write_inode: udf_write_inode, - put_inode: udf_put_inode, + put_inode: udf_put_inode, delete_inode: udf_delete_inode, - put_super: udf_put_super, + put_super: udf_put_super, write_super: udf_write_super, - statfs: udf_statfs, - remount_fs: udf_remount_fs, + statfs: udf_statfs, + remount_fs: udf_remount_fs, }; struct udf_options @@ -139,6 +139,8 @@ unregister_filesystem(&udf_fstype); } +EXPORT_NO_SYMBOLS; + module_init(init_udf_fs) module_exit(exit_udf_fs) @@ -280,7 +282,7 @@ udf_open_lvid(sb); sb->s_dirt = 0; } - + static int udf_remount_fs(struct super_block *sb, int *flags, char *options) { @@ -299,7 +301,7 @@ UDF_SB(sb)->s_gid = uopt.gid; UDF_SB(sb)->s_umask = uopt.umask; -#if CONFIG_UDF_RW != 1 +#if UDFFS_RW != 1 *flags |= MS_RDONLY; #endif @@ -343,13 +345,20 @@ static int udf_set_blocksize(struct super_block *sb, int bsize) { - /* Use specified block size if specified */ - sb->s_blocksize = get_hardsect_size(sb->s_dev); - if (bsize > sb->s_blocksize) - sb->s_blocksize = bsize; + int hard_size = get_hardsect_size(sb->s_dev); + + /* we will have defaulted to 2048b blocksize, but the user can + * override it with the -o bs=xx mount option. sanity check and + * make sure that it is at least as big as the hardware sector + * size */ + if (bsize < hard_size) + bsize = hard_size; + + sb->s_blocksize = bsize; /* Block size must be an even multiple of 512 */ - switch (sb->s_blocksize) { + switch (sb->s_blocksize) + { case 512: sb->s_blocksize_bits = 9; break; case 1024: sb->s_blocksize_bits = 10; break; case 2048: sb->s_blocksize_bits = 11; break; @@ -373,6 +382,7 @@ { struct VolStructDesc *vsd = NULL; int sector = 32768; + int sectorsize; struct buffer_head *bh = NULL; int iso9660=0; int nsr02=0; @@ -380,14 +390,19 @@ /* Block size must be a multiple of 512 */ if (sb->s_blocksize & 511) - return sector; + return 0; + + if (sb->s_blocksize < sizeof(struct VolStructDesc)) + sectorsize = sizeof(struct VolStructDesc); + else + sectorsize = sb->s_blocksize; sector += (UDF_SB_SESSION(sb) << sb->s_blocksize_bits); udf_debug("Starting at sector %u (%ld byte sectors)\n", (sector >> sb->s_blocksize_bits), sb->s_blocksize); /* Process the sequence (if applicable) */ - for (;!nsr02 && !nsr03; sector += 2048) + for (;!nsr02 && !nsr03; sector += sectorsize) { /* Read a block */ bh = udf_tread(sb, sector >> sb->s_blocksize_bits, sb->s_blocksize); @@ -504,7 +519,7 @@ for (i=0; (!lastblock && is_dev, last[i], sb->s_blocksize))) + if (last[i] < 0 || !(bh = bread(sb->s_dev, last[i], sb->s_blocksize))) { ident = location = 0; } @@ -777,7 +792,7 @@ struct PartitionDesc *p; int i; - p=(struct PartitionDesc *)bh->b_data; + p = (struct PartitionDesc *)bh->b_data; for (i=0; ipartitionContentsUse); if (phd->unallocatedSpaceTable.extLength) - udf_debug("unallocatedSpaceTable (part %d)\n", i); + { + lb_addr loc = { le32_to_cpu(phd->unallocatedSpaceTable.extPosition), i }; + + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table = + udf_iget(sb, loc); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_TABLE; + udf_debug("unallocatedSpaceTable (part %d) @ %ld\n", + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table->i_ino); + } if (phd->unallocatedSpaceBitmap.extLength) { - UDF_SB_PARTMAPS(sb)[i].s_uspace.bitmap = + UDF_SB_ALLOC_BITMAP(sb, i, s_uspace); + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extLength = + le32_to_cpu(phd->unallocatedSpaceBitmap.extLength); + UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition = le32_to_cpu(phd->unallocatedSpaceBitmap.extPosition); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_UNALLOC_BITMAP; udf_debug("unallocatedSpaceBitmap (part %d) @ %d\n", - i, UDF_SB_PARTMAPS(sb)[i].s_uspace.bitmap); + i, UDF_SB_PARTMAPS(sb)[i].s_uspace.s_bitmap->s_extPosition); } if (phd->partitionIntegrityTable.extLength) udf_debug("partitionIntegrityTable (part %d)\n", i); if (phd->freedSpaceTable.extLength) - udf_debug("freedSpaceTable (part %d)\n", i); + { + lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i }; + + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table = + udf_iget(sb, loc); + UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_TABLE; + udf_debug("freedSpaceTable (part %d) @ %ld\n", + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table->i_ino); + } if (phd->freedSpaceBitmap.extLength) { - UDF_SB_PARTMAPS(sb)[i].s_fspace.bitmap = + UDF_SB_ALLOC_BITMAP(sb, i, s_fspace); + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extLength = + le32_to_cpu(phd->freedSpaceBitmap.extLength); + UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition = le32_to_cpu(phd->freedSpaceBitmap.extPosition); UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_FREED_BITMAP; udf_debug("freedSpaceBitmap (part %d) @ %d\n", - i, UDF_SB_PARTMAPS(sb)[i].s_fspace.bitmap); + i, UDF_SB_PARTMAPS(sb)[i].s_fspace.s_bitmap->s_extPosition); } } break; @@ -852,7 +889,6 @@ i++,offset+=((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapLength) { type = ((struct GenericPartitionMap *)&(lvd->partitionMaps[offset]))->partitionMapType; - udf_debug("Partition (%d) type %d\n", i, type); if (type == 1) { struct GenericPartitionMap1 *gpm1 = (struct GenericPartitionMap1 *)&(lvd->partitionMaps[offset]); @@ -899,6 +935,8 @@ UDF_SB_PARTVSN(sb,i) = le16_to_cpu(upm2->volSeqNum); UDF_SB_PARTNUM(sb,i) = le16_to_cpu(upm2->partitionNum); } + udf_debug("Partition (%d:%d) type %d on volume %d\n", + i, UDF_SB_PARTNUM(sb,i), type, UDF_SB_PARTVSN(sb,i)); } if (fileset) @@ -963,10 +1001,12 @@ struct buffer_head *bh = NULL; struct udf_vds_record vds[VDS_POS_LENGTH]; struct GenericDesc *gd; + struct VolDescPtr *vdp; int done=0; int i,j; Uint32 vdsn; Uint16 ident; + long next_s = 0, next_e = 0; memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); @@ -995,6 +1035,12 @@ { vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn; vds[VDS_POS_VOL_DESC_PTR].block = block; + + vdp = (struct VolDescPtr *)bh->b_data; + next_s = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation); + next_e = le32_to_cpu(vdp->nextVolDescSeqExt.extLength); + next_e = next_e >> sb->s_blocksize_bits; + next_e += next_s; } break; case TID_IMP_USE_VOL_DESC: /* ISO 13346 3/10.4 */ @@ -1024,7 +1070,14 @@ break; case TID_TERMINATING_DESC: /* ISO 13346 3/10.9 */ vds[VDS_POS_TERMINATING_DESC].block = block; - done = 1; + if (next_e) + { + block = next_s; + lastblock = next_e; + next_s = next_e = 0; + } + else + done = 1; break; } udf_release_data(bh); @@ -1098,7 +1151,7 @@ for (i=0; ib_data; @@ -1155,10 +1208,10 @@ UDF_SB_PARTVSN(sb,i) == UDF_SB_PARTVSN(sb,j) && UDF_SB_PARTNUM(sb,i) == UDF_SB_PARTNUM(sb,j)) { - ino.partitionReferenceNum = j; - ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - - UDF_SB_PARTROOT(sb,j); - break; + ino.partitionReferenceNum = j; + ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - + UDF_SB_PARTROOT(sb,j); + break; } } @@ -1219,7 +1272,6 @@ ((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i]; mark_buffer_dirty(UDF_SB_LVIDBH(sb)); - sb->s_dirt = 0; } } @@ -1279,7 +1331,6 @@ struct inode *inode=NULL; struct udf_options uopt; lb_addr rootdir, fileset; - int i; uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB); uopt.uid = -1; @@ -1288,7 +1339,7 @@ memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info)); -#if CONFIG_UDF_RW != 1 +#if UDFFS_RW != 1 sb->s_flags |= MS_RDONLY; #endif @@ -1335,13 +1386,6 @@ sb->s_dirt = 0; sb->s_magic = UDF_SUPER_MAGIC; - for (i=0; is_flags & MS_RDONLY)) udf_close_lvid(sb); udf_release_data(UDF_SB_LVIDBH(sb)); @@ -1476,11 +1531,34 @@ if (UDF_SB_VAT(sb)) iput(UDF_SB_VAT(sb)); + if (UDF_SB_NUMPARTS(sb)) + { + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE) + iput(UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table); + if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP) + { + for (i=0; is_flags & MS_RDONLY)) udf_close_lvid(sb); udf_release_data(UDF_SB_LVIDBH(sb)); - for (i=0; is_extPosition; + loc.partitionReferenceNum = UDF_SB_PARTITION(sb); + bh = udf_read_ptagged(sb, loc, 0, &ident); - if (bitmap != 0xFFFFFFFF) + if (!bh) { - struct SpaceBitmapDesc *bm; - int block = 0, newblock, index; - Uint16 ident; - Uint32 bytes; - Uint8 value; - Uint8 * ptr; - - loc.logicalBlockNum = bitmap; - loc.partitionReferenceNum = UDF_SB_PARTITION(sb); - bh = udf_read_ptagged(sb, loc, 0, &ident); + printk(KERN_ERR "udf: udf_count_free failed\n"); + return 0; + } + else if (ident != TID_SPACE_BITMAP_DESC) + { + udf_release_data(bh); + printk(KERN_ERR "udf: udf_count_free failed\n"); + return 0; + } - if (!bh) - { - printk(KERN_ERR "udf: udf_count_free failed\n"); - return 0; + bm = (struct SpaceBitmapDesc *)bh->b_data; + bytes = bm->numOfBytes; + index = sizeof(struct SpaceBitmapDesc); /* offset in first block only */ + ptr = (Uint8 *)bh->b_data; + + while ( bytes > 0 ) + { + while ((bytes > 0) && (index < sb->s_blocksize)) + { + value = ptr[index]; + accum += udf_bitmap_lookup[ value & 0x0f ]; + accum += udf_bitmap_lookup[ value >> 4 ]; + index++; + bytes--; } - else if (ident != TID_SPACE_BITMAP_DESC) + if ( bytes ) { udf_release_data(bh); - printk(KERN_ERR "udf: udf_count_free failed\n"); - return 0; - } - - bm = (struct SpaceBitmapDesc *)bh->b_data; - bytes = bm->numOfBytes; - index = sizeof(struct SpaceBitmapDesc); /* offset in first block only */ - ptr = (Uint8 *)bh->b_data; - - while ( bytes > 0 ) - { - while ((bytes > 0) && (index < sb->s_blocksize)) + newblock = udf_get_lb_pblock(sb, loc, ++block); + bh = udf_tread(sb, newblock, sb->s_blocksize); + if (!bh) { - value = ptr[index]; - accum += udf_bitmap_lookup[ value & 0x0f ]; - accum += udf_bitmap_lookup[ value >> 4 ]; - index++; - bytes--; - } - if ( bytes ) - { - udf_release_data(bh); - newblock = udf_get_lb_pblock(sb, loc, ++block); - bh = udf_tread(sb, newblock, sb->s_blocksize); - if (!bh) - { - udf_debug("read failed\n"); - return accum; - } - index = 0; - ptr = (Uint8 *)bh->b_data; + udf_debug("read failed\n"); + return accum; } + index = 0; + ptr = (Uint8 *)bh->b_data; } - udf_release_data(bh); } - else + udf_release_data(bh); + return accum; +} + +static unsigned int +udf_count_free_table(struct super_block *sb, struct inode * table) +{ + unsigned int accum = 0; + Uint32 extoffset, elen; + lb_addr bloc, eloc; + char etype; + struct buffer_head *bh = NULL; + + bloc = UDF_I_LOCATION(table); + extoffset = sizeof(struct UnallocatedSpaceEntry); + + while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) + { + accum += (elen >> table->i_sb->s_blocksize_bits); + } + udf_release_data(bh); + return accum; +} + +static unsigned int +udf_count_free(struct super_block *sb) +{ + unsigned int accum = 0; + + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_BITMAP) { - if (UDF_SB_LVIDBH(sb)) + accum += udf_count_free_bitmap(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_bitmap); + } + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_BITMAP) + { + accum += udf_count_free_bitmap(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_bitmap); + } + if (accum) + return accum; + + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_UNALLOC_TABLE) + { + accum += udf_count_free_table(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_uspace.s_table); + } + if (UDF_SB_PARTFLAGS(sb,UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_FREED_TABLE) + { + accum += udf_count_free_table(sb, + UDF_SB_PARTMAPS(sb)[UDF_SB_PARTITION(sb)].s_fspace.s_table); + } + if (accum) + return accum; + + if (UDF_SB_LVIDBH(sb)) + { + if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb)) { - if (le32_to_cpu(UDF_SB_LVID(sb)->numOfPartitions) > UDF_SB_PARTITION(sb)) - accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]); + accum = le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]); if (accum == 0xFFFFFFFF) accum = 0; } } - return accum; } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/truncate.c linux/fs/udf/truncate.c --- linux-2.4.5-pre1/fs/udf/truncate.c Tue Sep 5 23:07:30 2000 +++ linux/fs/udf/truncate.c Tue May 8 17:51:29 2001 @@ -33,7 +33,7 @@ #include "udf_sb.h" static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset, - lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head **bh, Uint32 nelen) + lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head *bh, Uint32 nelen) { lb_addr neloc = { 0, 0 }; int blocks = inode->i_sb->s_blocksize / 512; @@ -62,7 +62,7 @@ } } -void udf_trunc(struct inode * inode) +void udf_truncate_extents(struct inode * inode) { lb_addr bloc, eloc, neloc = { 0, 0 }; Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc; @@ -79,12 +79,11 @@ adsize = 0; etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh); - offset = (offset << inode->i_sb->s_blocksize_bits) | - (inode->i_size & (inode->i_sb->s_blocksize - 1)); + offset += (inode->i_size & (inode->i_sb->s_blocksize - 1)); if (etype != -1) { extoffset -= adsize; - extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, offset); + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset); extoffset += adsize; if (offset) @@ -101,7 +100,7 @@ { if (etype == EXTENT_NEXT_EXTENT_ALLOCDECS) { - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 0); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0); extoffset = 0; if (lelen) { @@ -140,7 +139,7 @@ } else { - extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, 0); + extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0); extoffset += adsize; } } @@ -180,7 +179,7 @@ { extoffset -= adsize; elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 0); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); } else if (etype == EXTENT_NOT_RECORDED_ALLOCATED) { @@ -189,7 +188,7 @@ nelen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | ((elen + offset + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); } else @@ -200,7 +199,7 @@ elen = (EXTENT_RECORDED_ALLOCATED << 30) | ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); } memset(&eloc, 0x00, sizeof(lb_addr)); elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | offset; @@ -208,40 +207,7 @@ } } } + UDF_I_LENEXTENTS(inode) = inode->i_size; udf_release_data(bh); -} - -void udf_truncate(struct inode * inode) -{ - int err; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - - if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - { - if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + - inode->i_size)) - { - udf_expand_file_adinicb(inode, inode->i_size, &err); - if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) - { - inode->i_size = UDF_I_LENALLOC(inode); - return; - } - else - udf_trunc(inode); - } - else - UDF_I_LENALLOC(inode) = inode->i_size; - } - else - udf_trunc(inode); - - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); } diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/udf_i.h linux/fs/udf/udf_i.h --- linux-2.4.5-pre1/fs/udf/udf_i.h Thu Mar 2 20:17:32 2000 +++ linux/fs/udf/udf_i.h Tue May 8 17:51:31 2001 @@ -6,6 +6,7 @@ #define UDF_I_LOCATION(X) ( UDF_I(X)->i_location ) #define UDF_I_LENEATTR(X) ( UDF_I(X)->i_lenEAttr ) #define UDF_I_LENALLOC(X) ( UDF_I(X)->i_lenAlloc ) +#define UDF_I_LENEXTENTS(X) ( UDF_I(X)->i_lenExtents ) #define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique ) #define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type ) #define UDF_I_EXTENDED_FE(X)( UDF_I(X)->i_extended_fe ) diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/udf_sb.h linux/fs/udf/udf_sb.h --- linux-2.4.5-pre1/fs/udf/udf_sb.h Mon Mar 20 17:17:43 2000 +++ linux/fs/udf/udf_sb.h Tue May 8 17:51:31 2001 @@ -23,7 +23,7 @@ #define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 #define UDF_PART_FLAG_FREED_BITMAP 0x0004 #define UDF_PART_FLAG_FREED_TABLE 0x0008 - + #define UDF_SB_FREE(X)\ {\ if (UDF_SB(X))\ @@ -42,6 +42,21 @@ memset(UDF_SB_PARTMAPS(X), 0x00, sizeof(struct udf_part_map) * Y);\ } +#define UDF_SB_ALLOC_BITMAP(X,Y,Z)\ +{\ + int nr_groups = ((UDF_SB_PARTLEN((X),(Y)) + (sizeof(struct SpaceBitmapDesc) << 3) +\ + ((X)->s_blocksize * 8) - 1) / ((X)->s_blocksize * 8));\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap = kmalloc(sizeof(struct udf_bitmap) +\ + sizeof(struct buffer_head *) * nr_groups,\ + GFP_KERNEL);\ + memset(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap, 0x00,\ + sizeof(struct udf_bitmap) + sizeof(struct buffer_head *) * nr_groups);\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap =\ + (struct buffer_head **)(UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap + 1);\ + UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups = nr_groups;\ +} + + #define UDF_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) ) #define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) ) #define UDF_CLEAR_FLAG(X,Y) ( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) ) @@ -58,6 +73,8 @@ #define UDF_SB_TYPEVIRT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_virtual ) #define UDF_SB_PARTFUNC(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func ) #define UDF_SB_PARTFLAGS(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_flags ) +#define UDF_SB_BITMAP(X,Y,Z,I) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_block_bitmap[I] ) +#define UDF_SB_BITMAP_NR_GROUPS(X,Y,Z) ( UDF_SB_PARTMAPS(X)[(Y)].Z.s_bitmap->s_nr_groups ) #define UDF_SB_VOLIDENT(X) ( UDF_SB(X)->s_volident ) #define UDF_SB_NUMPARTS(X) ( UDF_SB(X)->s_partitions ) @@ -69,9 +86,6 @@ #define UDF_SB_LVID(X) ( (struct LogicalVolIntegrityDesc *)UDF_SB_LVIDBH(X)->b_data ) #define UDF_SB_LVIDIU(X) ( (struct LogicalVolIntegrityDescImpUse *)&(UDF_SB_LVID(X)->impUse[UDF_SB_LVID(X)->numOfPartitions * 2 * sizeof(Uint32)/sizeof(Uint8)]) ) -#define UDF_SB_LOADED_BLOCK_BITMAPS(X) ( UDF_SB(X)->s_loaded_block_bitmaps ) -#define UDF_SB_BLOCK_BITMAP_NUMBER(X,Y) ( UDF_SB(X)->s_block_bitmap_number[(Y)] ) -#define UDF_SB_BLOCK_BITMAP(X,Y) ( UDF_SB(X)->s_block_bitmap[(Y)] ) #define UDF_SB_UMASK(X) ( UDF_SB(X)->s_umask ) #define UDF_SB_GID(X) ( UDF_SB(X)->s_gid ) #define UDF_SB_UID(X) ( UDF_SB(X)->s_uid ) diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h --- linux-2.4.5-pre1/fs/udf/udfdecl.h Mon Dec 11 22:27:05 2000 +++ linux/fs/udf/udfdecl.h Tue May 8 17:51:31 2001 @@ -131,15 +131,15 @@ extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head * udf_getblk(struct inode *, long, int, int *); extern struct buffer_head * udf_bread(struct inode *, int, int, int *); +extern void udf_truncate(struct inode *); extern void udf_read_inode(struct inode *); extern void udf_put_inode(struct inode *); extern void udf_delete_inode(struct inode *); extern void udf_write_inode(struct inode *, int); -extern long udf_locked_block_map(struct inode *, long); extern long udf_block_map(struct inode *, long); extern int inode_bmap(struct inode *, int, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **); extern int udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, Uint32, struct buffer_head **, int); -extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head **, int); +extern int udf_write_aext(struct inode *, lb_addr, int *, lb_addr, Uint32, struct buffer_head *, int); extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *); extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *); extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int); @@ -148,6 +148,7 @@ /* misc.c */ extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref); +extern struct buffer_head *udf_tgetblk(struct super_block *, int, int); extern struct buffer_head *udf_tread(struct super_block *, int, int); extern struct GenericAttrFormat *udf_add_extendedattr(struct inode *, Uint32, Uint32, Uint8, struct buffer_head **); extern struct GenericAttrFormat *udf_get_extendedattr(struct inode *, Uint32, Uint8, struct buffer_head **); @@ -175,8 +176,7 @@ extern struct inode * udf_new_inode (const struct inode *, int, int *); /* truncate.c */ -extern void udf_trunc(struct inode *); -extern void udf_truncate(struct inode *); +extern void udf_truncate_extents(struct inode *); /* balloc.c */ extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32); @@ -184,7 +184,8 @@ extern int udf_new_block(const struct inode *, Uint16, Uint32, int *); /* fsync.c */ -extern int udf_sync_file(struct file *, struct dentry *, int); +extern int udf_fsync_file(struct file *, struct dentry *, int); +extern int udf_fsync_inode(struct inode *, int); /* directory.c */ extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *); diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/udfend.h linux/fs/udf/udfend.h --- linux-2.4.5-pre1/fs/udf/udfend.h Mon Dec 11 22:27:05 2000 +++ linux/fs/udf/udfend.h Tue May 8 17:51:31 2001 @@ -80,6 +80,22 @@ return out; } +static inline short_ad lesa_to_cpu(short_ad in) +{ + short_ad out; + out.extLength = le32_to_cpu(in.extLength); + out.extPosition = le32_to_cpu(in.extPosition); + return out; +} + +static inline short_ad cpu_to_lesa(short_ad in) +{ + short_ad out; + out.extLength = cpu_to_le32(in.extLength); + out.extPosition = cpu_to_le32(in.extPosition); + return out; +} + static inline long_ad lela_to_cpu(long_ad in) { long_ad out; diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/fs/udf/udftime.c linux/fs/udf/udftime.c --- linux-2.4.5-pre1/fs/udf/udftime.c Thu Mar 2 20:17:32 2000 +++ linux/fs/udf/udftime.c Tue May 8 17:51:29 2001 @@ -105,6 +105,8 @@ offset = src.typeAndTimezone << 4; /* sign extent offset */ offset = (offset >> 4); + if (offset == -2047) /* unspecified offset */ + offset = 0; } else offset = 0; diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/include/linux/udf_167.h linux/include/linux/udf_167.h --- linux-2.4.5-pre1/include/linux/udf_167.h Mon Dec 11 22:27:05 2000 +++ linux/include/linux/udf_167.h Tue May 8 17:50:13 2001 @@ -31,7 +31,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/include/linux/udf_fs.h linux/include/linux/udf_fs.h --- linux-2.4.5-pre1/include/linux/udf_fs.h Mon Jan 1 18:57:08 2001 +++ linux/include/linux/udf_fs.h Tue May 8 17:50:13 2001 @@ -16,7 +16,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -37,8 +37,18 @@ #define UDF_PREALLOCATE #define UDF_DEFAULT_PREALLOC_BLOCKS 8 -#define UDFFS_DATE "2000/02/29" -#define UDFFS_VERSION "0.9.1" +#define UDFFS_DATE "2000/12/25" +#define UDFFS_VERSION "0.9.3" + +#if !defined(UDFFS_RW) + +#if defined(CONFIG_UDF_RW) +#define UDFFS_RW 1 +#else /* !defined(CONFIG_UDF_RW) */ +#define UDFFS_RW 0 +#endif /* defined(CONFIG_UDF_RW) */ + +#endif /* !defined(UDFFS_RW) */ #define UDFFS_DEBUG @@ -55,5 +65,17 @@ #define udf_info(f, a...) \ printk (KERN_INFO "UDF-fs INFO " f, ##a); + +#ifdef __KERNEL__ + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) +extern int init_udf_fs(void); +#endif /* 2.2.XX */ + +#endif /* __KERNEL__ */ #endif /* !defined(_LINUX_UDF_FS_H) */ diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/include/linux/udf_fs_i.h linux/include/linux/udf_fs_i.h --- linux-2.4.5-pre1/include/linux/udf_fs_i.h Thu Mar 2 20:17:32 2000 +++ linux/include/linux/udf_fs_i.h Tue May 8 17:48:12 2001 @@ -6,7 +6,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -38,6 +38,7 @@ __u64 i_unique; __u32 i_lenEAttr; __u32 i_lenAlloc; + __u64 i_lenExtents; __u32 i_next_alloc_block; __u32 i_next_alloc_goal; unsigned i_alloc_type : 3; diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/include/linux/udf_fs_sb.h linux/include/linux/udf_fs_sb.h --- linux-2.4.5-pre1/include/linux/udf_fs_sb.h Mon Mar 20 17:17:43 2000 +++ linux/include/linux/udf_fs_sb.h Tue May 8 17:49:52 2001 @@ -6,7 +6,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public @@ -18,6 +18,10 @@ #if !defined(_LINUX_UDF_FS_SB_H) #define _LINUX_UDF_FS_SB_H +#ifndef LINUX_VERSION_CODE +#include +#endif + #pragma pack(1) #define UDF_MAX_BLOCK_LOADED 8 @@ -47,17 +51,25 @@ __u16 s_start_offset; }; +struct udf_bitmap +{ + __u32 s_extLength; + __u32 s_extPosition; + __u16 s_nr_groups; + struct buffer_head **s_block_bitmap; +}; + struct udf_part_map { union { - __u32 bitmap; - struct inode *table; + struct udf_bitmap *s_bitmap; + struct inode *s_table; } s_uspace; union { - __u32 bitmap; - struct inode *table; + struct udf_bitmap *s_bitmap; + struct inode *s_table; } s_fspace; __u32 s_partition_root; __u32 s_partition_len; @@ -77,43 +89,44 @@ struct udf_sb_info { - struct udf_part_map *s_partmaps; - __u8 s_volident[32]; + struct udf_part_map *s_partmaps; + __u8 s_volident[32]; /* Overall info */ - __u16 s_partitions; - __u16 s_partition; + __u16 s_partitions; + __u16 s_partition; /* Sector headers */ - __u32 s_session; - __u32 s_anchor[4]; - __u32 s_lastblock; - - struct buffer_head *s_lvidbh; - - __u16 s_loaded_block_bitmaps; - __u32 s_block_bitmap_number[UDF_MAX_BLOCK_LOADED]; - struct buffer_head *s_block_bitmap[UDF_MAX_BLOCK_LOADED]; + __u32 s_session; + __u32 s_anchor[4]; + __u32 s_lastblock; + + struct buffer_head *s_lvidbh; /* Default permissions */ - mode_t s_umask; - gid_t s_gid; - uid_t s_uid; + mode_t s_umask; + gid_t s_gid; + uid_t s_uid; /* Root Info */ - time_t s_recordtime; + time_t s_recordtime; /* Fileset Info */ - __u16 s_serialnum; + __u16 s_serialnum; /* highest UDF revision we have recorded to this media */ - __u16 s_udfrev; + __u16 s_udfrev; /* Miscellaneous flags */ - __u32 s_flags; + __u32 s_flags; /* VAT inode */ - struct inode *s_vat; + struct inode *s_vat; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) + int s_rename_lock; + struct wait_queue *s_rename_wait; +#endif }; #endif /* !defined(_LINUX_UDF_FS_SB_H) */ diff -ur --exclude-from /home/axboe/exclude linux-2.4.5-pre1/include/linux/udf_udf.h linux/include/linux/udf_udf.h --- linux-2.4.5-pre1/include/linux/udf_udf.h Mon Dec 11 22:27:05 2000 +++ linux/include/linux/udf_udf.h Tue May 8 17:50:13 2001 @@ -10,7 +10,7 @@ * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): - * linux_udf@hootie.lvld.hp.com + * linux_udf@hpesjro.fc.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public