UDF: introduce struct extent_position

Introduce a structure extent_position to store a position of an extent and
the corresponding buffer_head in one place.

Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Jan Kara 2007-05-08 00:35:14 -07:00 committed by Linus Torvalds
parent 60448b1d6d
commit ff116fc8d1
8 changed files with 434 additions and 445 deletions

View File

@ -427,9 +427,9 @@ static void udf_table_free_blocks(struct super_block * sb,
{
struct udf_sb_info *sbi = UDF_SB(sb);
uint32_t start, end;
uint32_t nextoffset, oextoffset, elen;
kernel_lb_addr nbloc, obloc, eloc;
struct buffer_head *obh, *nbh;
uint32_t elen;
kernel_lb_addr eloc;
struct extent_position oepos, epos;
int8_t etype;
int i;
@ -457,14 +457,13 @@ static void udf_table_free_blocks(struct super_block * sb,
start = bloc.logicalBlockNum + offset;
end = bloc.logicalBlockNum + offset + count - 1;
oextoffset = nextoffset = sizeof(struct unallocSpaceEntry);
epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
elen = 0;
obloc = nbloc = UDF_I_LOCATION(table);
obh = nbh = NULL;
epos.block = oepos.block = UDF_I_LOCATION(table);
epos.bh = oepos.bh = NULL;
while (count && (etype =
udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
{
if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
start))
@ -482,7 +481,7 @@ static void udf_table_free_blocks(struct super_block * sb,
start += count;
count = 0;
}
udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(table, &oepos, eloc, elen, 1);
}
else if (eloc.logicalBlockNum == (end + 1))
{
@ -502,20 +501,20 @@ static void udf_table_free_blocks(struct super_block * sb,
end -= count;
count = 0;
}
udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(table, &oepos, eloc, elen, 1);
}
if (nbh != obh)
if (epos.bh != oepos.bh)
{
i = -1;
obloc = nbloc;
udf_release_data(obh);
atomic_inc(&nbh->b_count);
obh = nbh;
oextoffset = 0;
oepos.block = epos.block;
udf_release_data(oepos.bh);
atomic_inc(&epos.bh->b_count);
oepos.bh = epos.bh;
oepos.offset = 0;
}
else
oextoffset = nextoffset;
oepos.offset = epos.offset;
}
if (count)
@ -547,55 +546,53 @@ static void udf_table_free_blocks(struct super_block * sb,
adsize = sizeof(long_ad);
else
{
udf_release_data(obh);
udf_release_data(nbh);
udf_release_data(oepos.bh);
udf_release_data(epos.bh);
goto error_return;
}
if (nextoffset + (2 * adsize) > sb->s_blocksize)
if (epos.offset + (2 * adsize) > sb->s_blocksize)
{
char *sptr, *dptr;
int loffset;
udf_release_data(obh);
obh = nbh;
obloc = nbloc;
oextoffset = nextoffset;
udf_release_data(oepos.bh);
oepos = epos;
/* Steal a block from the extent being free'd */
nbloc.logicalBlockNum = eloc.logicalBlockNum;
epos.block.logicalBlockNum = eloc.logicalBlockNum;
eloc.logicalBlockNum ++;
elen -= sb->s_blocksize;
if (!(nbh = udf_tread(sb,
udf_get_lb_pblock(sb, nbloc, 0))))
if (!(epos.bh = udf_tread(sb,
udf_get_lb_pblock(sb, epos.block, 0))))
{
udf_release_data(obh);
udf_release_data(oepos.bh);
goto error_return;
}
aed = (struct allocExtDesc *)(nbh->b_data);
aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
if (nextoffset + adsize > sb->s_blocksize)
aed = (struct allocExtDesc *)(epos.bh->b_data);
aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum);
if (epos.offset + adsize > sb->s_blocksize)
{
loffset = nextoffset;
loffset = epos.offset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
sptr = UDF_I_DATA(inode) + nextoffset -
sptr = UDF_I_DATA(inode) + epos.offset -
udf_file_entry_alloc_offset(inode) +
UDF_I_LENEATTR(inode) - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
dptr = epos.bh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
nextoffset = sizeof(struct allocExtDesc) + adsize;
epos.offset = sizeof(struct allocExtDesc) + adsize;
}
else
{
loffset = nextoffset + adsize;
loffset = epos.offset + adsize;
aed->lengthAllocDescs = cpu_to_le32(0);
sptr = (obh)->b_data + nextoffset;
nextoffset = sizeof(struct allocExtDesc);
sptr = oepos.bh->b_data + epos.offset;
epos.offset = sizeof(struct allocExtDesc);
if (obh)
if (oepos.bh)
{
aed = (struct allocExtDesc *)(obh)->b_data;
aed = (struct allocExtDesc *)oepos.bh->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
}
@ -606,11 +603,11 @@ static void udf_table_free_blocks(struct super_block * sb,
}
}
if (UDF_SB_UDFREV(sb) >= 0x0200)
udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
nbloc.logicalBlockNum, sizeof(tag));
udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1,
epos.block.logicalBlockNum, sizeof(tag));
else
udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
nbloc.logicalBlockNum, sizeof(tag));
udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1,
epos.block.logicalBlockNum, sizeof(tag));
switch (UDF_I_ALLOCTYPE(table))
{
case ICBTAG_FLAG_AD_SHORT:
@ -619,7 +616,7 @@ static void udf_table_free_blocks(struct super_block * sb,
sad->extLength = cpu_to_le32(
EXT_NEXT_EXTENT_ALLOCDECS |
sb->s_blocksize);
sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum);
break;
}
case ICBTAG_FLAG_AD_LONG:
@ -628,14 +625,14 @@ static void udf_table_free_blocks(struct super_block * sb,
lad->extLength = cpu_to_le32(
EXT_NEXT_EXTENT_ALLOCDECS |
sb->s_blocksize);
lad->extLocation = cpu_to_lelb(nbloc);
lad->extLocation = cpu_to_lelb(epos.block);
break;
}
}
if (obh)
if (oepos.bh)
{
udf_update_tag(obh->b_data, loffset);
mark_buffer_dirty(obh);
udf_update_tag(oepos.bh->b_data, loffset);
mark_buffer_dirty(oepos.bh);
}
else
mark_inode_dirty(table);
@ -643,26 +640,26 @@ static void udf_table_free_blocks(struct super_block * sb,
if (elen) /* It's possible that stealing the block emptied the extent */
{
udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
udf_write_aext(table, &epos, eloc, elen, 1);
if (!nbh)
if (!epos.bh)
{
UDF_I_LENALLOC(table) += adsize;
mark_inode_dirty(table);
}
else
{
aed = (struct allocExtDesc *)nbh->b_data;
aed = (struct allocExtDesc *)epos.bh->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_update_tag(epos.bh->b_data, epos.offset);
mark_buffer_dirty(epos.bh);
}
}
}
udf_release_data(nbh);
udf_release_data(obh);
udf_release_data(epos.bh);
udf_release_data(oepos.bh);
error_return:
sb->s_dirt = 1;
@ -677,9 +674,9 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
{
struct udf_sb_info *sbi = UDF_SB(sb);
int alloc_count = 0;
uint32_t extoffset, elen, adsize;
kernel_lb_addr bloc, eloc;
struct buffer_head *bh;
uint32_t elen, adsize;
kernel_lb_addr eloc;
struct extent_position epos;
int8_t etype = -1;
if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
@ -693,14 +690,13 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
return 0;
mutex_lock(&sbi->s_alloc_mutex);
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
bh = NULL;
epos.offset = sizeof(struct unallocSpaceEntry);
epos.block = UDF_I_LOCATION(table);
epos.bh = NULL;
eloc.logicalBlockNum = 0xFFFFFFFF;
while (first_block != eloc.logicalBlockNum && (etype =
udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
{
udf_debug("eloc=%d, elen=%d, first_block=%d\n",
eloc.logicalBlockNum, elen, first_block);
@ -709,7 +705,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
if (first_block == eloc.logicalBlockNum)
{
extoffset -= adsize;
epos.offset -= adsize;
alloc_count = (elen >> sb->s_blocksize_bits);
if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
@ -719,15 +715,15 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
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);
udf_write_aext(table, &epos, eloc, (etype << 30) | elen, 1);
}
else
udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
udf_delete_aext(table, epos, eloc, (etype << 30) | elen);
}
else
alloc_count = 0;
udf_release_data(bh);
udf_release_data(epos.bh);
if (alloc_count && UDF_SB_LVIDBH(sb))
{
@ -747,9 +743,9 @@ static int udf_table_new_block(struct super_block * sb,
struct udf_sb_info *sbi = UDF_SB(sb);
uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
uint32_t newblock = 0, adsize;
uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
struct buffer_head *bh, *goal_bh;
uint32_t elen, goal_elen = 0;
kernel_lb_addr eloc, goal_eloc;
struct extent_position epos, goal_epos;
int8_t etype;
*err = -ENOSPC;
@ -770,14 +766,12 @@ static int udf_table_new_block(struct super_block * sb,
We store the buffer_head, bloc, and extoffset of the current closest
match and use that when we are done.
*/
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
goal_bh = bh = NULL;
epos.offset = sizeof(struct unallocSpaceEntry);
epos.block = UDF_I_LOCATION(table);
epos.bh = goal_epos.bh = NULL;
while (spread && (etype =
udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
{
if (goal >= eloc.logicalBlockNum)
{
@ -793,24 +787,24 @@ static int udf_table_new_block(struct super_block * sb,
if (nspread < spread)
{
spread = nspread;
if (goal_bh != bh)
if (goal_epos.bh != epos.bh)
{
udf_release_data(goal_bh);
goal_bh = bh;
atomic_inc(&goal_bh->b_count);
udf_release_data(goal_epos.bh);
goal_epos.bh = epos.bh;
atomic_inc(&goal_epos.bh->b_count);
}
goal_bloc = bloc;
goal_extoffset = extoffset - adsize;
goal_epos.block = epos.block;
goal_epos.offset = epos.offset - adsize;
goal_eloc = eloc;
goal_elen = (etype << 30) | elen;
}
}
udf_release_data(bh);
udf_release_data(epos.bh);
if (spread == 0xFFFFFFFF)
{
udf_release_data(goal_bh);
udf_release_data(goal_epos.bh);
mutex_unlock(&sbi->s_alloc_mutex);
return 0;
}
@ -826,17 +820,17 @@ static int udf_table_new_block(struct super_block * sb,
if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
{
udf_release_data(goal_bh);
udf_release_data(goal_epos.bh);
mutex_unlock(&sbi->s_alloc_mutex);
*err = -EDQUOT;
return 0;
}
if (goal_elen)
udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1);
else
udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);
udf_release_data(goal_bh);
udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
udf_release_data(goal_epos.bh);
if (UDF_SB_LVIDBH(sb))
{

View File

@ -111,12 +111,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
uint16_t liu;
uint8_t lfi;
loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
struct buffer_head * bh = NULL, * tmp, * bha[16];
kernel_lb_addr bloc, eloc;
uint32_t extoffset, elen;
struct buffer_head *tmp, *bha[16];
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
int i, num;
unsigned int dt_type;
struct extent_position epos = { NULL, 0, {0, 0}};
if (nf_pos >= size)
return 0;
@ -128,22 +129,22 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
fibh.sbh = fibh.ebh = NULL;
else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
epos.offset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
extoffset -= sizeof(long_ad);
epos.offset -= sizeof(long_ad);
}
else
offset = 0;
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
udf_release_data(epos.bh);
return -EIO;
}
@ -171,7 +172,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
}
else
{
udf_release_data(bh);
udf_release_data(epos.bh);
return -ENOENT;
}
@ -179,14 +180,14 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
{
filp->f_pos = nf_pos + 1;
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
if (!fi)
{
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
@ -246,7 +247,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
}
@ -257,7 +258,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}

View File

@ -75,9 +75,9 @@ struct fileIdentDesc *
udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
struct fileIdentDesc *cfi,
kernel_lb_addr *bloc, uint32_t *extoffset,
struct extent_position *epos,
kernel_lb_addr *eloc, uint32_t *elen,
sector_t *offset, struct buffer_head **bh)
sector_t *offset)
{
struct fileIdentDesc *fi;
int i, num, block;
@ -105,13 +105,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
if (fibh->eoffset == dir->i_sb->s_blocksize)
{
int lextoffset = *extoffset;
int lextoffset = epos->offset;
if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
if (udf_next_aext(dir, epos, eloc, elen, 1) !=
(EXT_RECORDED_ALLOCATED >> 30))
{
return NULL;
}
block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
@ -120,7 +118,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
*offset = 0;
else
*extoffset = lextoffset;
epos->offset = lextoffset;
udf_release_data(fibh->sbh);
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
@ -169,13 +167,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
}
else if (fibh->eoffset > dir->i_sb->s_blocksize)
{
int lextoffset = *extoffset;
int lextoffset = epos->offset;
if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
if (udf_next_aext(dir, epos, eloc, elen, 1) !=
(EXT_RECORDED_ALLOCATED >> 30))
{
return NULL;
}
block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
@ -184,7 +180,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
*offset = 0;
else
*extoffset = lextoffset;
epos->offset = lextoffset;
fibh->soffset -= dir->i_sb->s_blocksize;
fibh->eoffset -= dir->i_sb->s_blocksize;

View File

@ -51,8 +51,8 @@ static int udf_update_inode(struct inode *, int);
static void udf_fill_inode(struct inode *, struct buffer_head *);
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
long *, int *);
static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
kernel_lb_addr, uint32_t, struct buffer_head *);
static int8_t udf_insert_aext(struct inode *, struct extent_position,
kernel_lb_addr, uint32_t);
static void udf_split_extents(struct inode *, int *, int, int,
kernel_long_ad [EXTENT_MERGE_SIZE], int *);
static void udf_prealloc_extents(struct inode *, int, int,
@ -61,7 +61,7 @@ static void udf_merge_extents(struct inode *,
kernel_long_ad [EXTENT_MERGE_SIZE], int *);
static void udf_update_extents(struct inode *,
kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
kernel_lb_addr, uint32_t, struct buffer_head **);
struct extent_position *);
static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
/*
@ -194,10 +194,11 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
{
int newblock;
struct buffer_head *sbh = NULL, *dbh = NULL;
kernel_lb_addr bloc, eloc;
uint32_t elen, extoffset;
struct buffer_head *dbh = NULL;
kernel_lb_addr eloc;
uint32_t elen;
uint8_t alloctype;
struct extent_position epos;
struct udf_fileident_bh sfibh, dfibh;
loff_t f_pos = udf_ext0_offset(inode) >> 2;
@ -237,13 +238,13 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
mark_buffer_dirty_inode(dbh, inode);
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
sbh = sfibh.sbh = sfibh.ebh = NULL;
sfibh.sbh = sfibh.ebh = NULL;
dfibh.soffset = dfibh.eoffset = 0;
dfibh.sbh = dfibh.ebh = dbh;
while ( (f_pos < size) )
{
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
if (!sfi)
{
udf_release_data(dbh);
@ -266,16 +267,17 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
bloc = UDF_I_LOCATION(inode);
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);
epos.bh = NULL;
epos.block = UDF_I_LOCATION(inode);
epos.offset = udf_file_entry_alloc_offset(inode);
udf_add_aext(inode, &epos, eloc, elen, 0);
/* UniqueID stuff */
udf_release_data(sbh);
udf_release_data(epos.bh);
mark_inode_dirty(inode);
return dbh;
}
@ -357,12 +359,12 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
int *err, long *phys, int *new)
{
struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
struct buffer_head *result = NULL;
kernel_long_ad laarr[EXTENT_MERGE_SIZE];
uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
struct extent_position prev_epos, cur_epos, next_epos;
int count = 0, startnum = 0, endnum = 0;
uint32_t elen = 0;
kernel_lb_addr eloc, pbloc, cbloc, nbloc;
kernel_lb_addr eloc;
int c = 1;
loff_t lbcount = 0, b_off = 0;
uint32_t newblocknum, newblock;
@ -371,37 +373,39 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
char lastblock = 0;
pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
prev_epos.offset = udf_file_entry_alloc_offset(inode);
prev_epos.block = UDF_I_LOCATION(inode);
prev_epos.bh = NULL;
cur_epos = next_epos = prev_epos;
b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
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
current extent, and the previous extent */
do
{
if (pbh != cbh)
if (prev_epos.bh != cur_epos.bh)
{
udf_release_data(pbh);
atomic_inc(&cbh->b_count);
pbh = cbh;
udf_release_data(prev_epos.bh);
atomic_inc(&cur_epos.bh->b_count);
prev_epos.bh = cur_epos.bh;
}
if (cbh != nbh)
if (cur_epos.bh != next_epos.bh)
{
udf_release_data(cbh);
atomic_inc(&nbh->b_count);
cbh = nbh;
udf_release_data(cur_epos.bh);
atomic_inc(&next_epos.bh->b_count);
cur_epos.bh = next_epos.bh;
}
lbcount += elen;
pbloc = cbloc;
cbloc = nbloc;
prev_epos.block = cur_epos.block;
cur_epos.block = next_epos.block;
pextoffset = cextoffset;
cextoffset = nextoffset;
prev_epos.offset = cur_epos.offset;
cur_epos.offset = next_epos.offset;
if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1)
if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1)) == -1)
break;
c = !c;
@ -430,11 +434,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
elen = EXT_RECORDED_ALLOCATED |
((elen + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1);
etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
}
udf_release_data(pbh);
udf_release_data(cbh);
udf_release_data(nbh);
udf_release_data(prev_epos.bh);
udf_release_data(cur_epos.bh);
udf_release_data(next_epos.bh);
newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
*phys = newblock;
return NULL;
@ -477,7 +481,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
/* if the current block is located in a extent, read the next extent */
if (etype != -1)
{
if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1)
if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
{
laarr[c+1].extLength = (etype << 30) | elen;
laarr[c+1].extLocation = eloc;
@ -488,8 +492,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
else
lastblock = 1;
}
udf_release_data(cbh);
udf_release_data(nbh);
udf_release_data(cur_epos.bh);
udf_release_data(next_epos.bh);
/* if the current extent is not recorded but allocated, get the
block in the extent corresponding to the requested block */
@ -509,7 +513,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
if (!(newblocknum = udf_new_block(inode->i_sb, inode,
UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
{
udf_release_data(pbh);
udf_release_data(prev_epos.bh);
*err = -ENOSPC;
return NULL;
}
@ -532,9 +536,9 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
/* write back the new extents, inserting new extents if the new number
of extents is greater than the old number, and deleting extents if
the new number of extents is less than the old number */
udf_update_extents(inode, laarr, startnum, endnum, pbloc, pextoffset, &pbh);
udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
udf_release_data(pbh);
udf_release_data(prev_epos.bh);
if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@ -796,7 +800,7 @@ static void udf_merge_extents(struct inode *inode,
static void udf_update_extents(struct inode *inode,
kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
struct extent_position *epos)
{
int start = 0, i;
kernel_lb_addr tmploc;
@ -805,28 +809,26 @@ static void udf_update_extents(struct inode *inode,
if (startnum > endnum)
{
for (i=0; i<(startnum-endnum); i++)
{
udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
laarr[i].extLength, *pbh);
}
udf_delete_aext(inode, *epos, laarr[i].extLocation,
laarr[i].extLength);
}
else if (startnum < endnum)
{
for (i=0; i<(endnum-startnum); i++)
{
udf_insert_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
laarr[i].extLength, *pbh);
udf_next_aext(inode, &pbloc, &pextoffset, &laarr[i].extLocation,
&laarr[i].extLength, pbh, 1);
udf_insert_aext(inode, *epos, laarr[i].extLocation,
laarr[i].extLength);
udf_next_aext(inode, epos, &laarr[i].extLocation,
&laarr[i].extLength, 1);
start ++;
}
}
for (i=start; i<endnum; i++)
{
udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
laarr[i].extLength, *pbh, 1);
udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
udf_write_aext(inode, epos, laarr[i].extLocation,
laarr[i].extLength, 1);
}
}
@ -1557,8 +1559,8 @@ udf_iget(struct super_block *sb, kernel_lb_addr ino)
return NULL;
}
int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
kernel_lb_addr eloc, uint32_t elen, int inc)
{
int adsize;
short_ad *sad = NULL;
@ -1567,10 +1569,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
int8_t etype;
uint8_t *ptr;
if (!*bh)
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
if (!epos->bh)
ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
else
ptr = (*bh)->b_data + *extoffset;
ptr = epos->bh->b_data + epos->offset;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
@ -1579,20 +1581,20 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
else
return -1;
if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize)
{
char *sptr, *dptr;
struct buffer_head *nbh;
int err, loffset;
kernel_lb_addr obloc = *bloc;
kernel_lb_addr obloc = epos->block;
if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
if (!(epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
{
return -1;
}
if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
*bloc, 0))))
epos->block, 0))))
{
return -1;
}
@ -1605,25 +1607,25 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
aed = (struct allocExtDesc *)(nbh->b_data);
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
if (*extoffset + adsize > inode->i_sb->s_blocksize)
if (epos->offset + adsize > inode->i_sb->s_blocksize)
{
loffset = *extoffset;
loffset = epos->offset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
sptr = ptr - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
*extoffset = sizeof(struct allocExtDesc) + adsize;
epos->offset = sizeof(struct allocExtDesc) + adsize;
}
else
{
loffset = *extoffset + adsize;
loffset = epos->offset + adsize;
aed->lengthAllocDescs = cpu_to_le32(0);
sptr = ptr;
*extoffset = sizeof(struct allocExtDesc);
epos->offset = sizeof(struct allocExtDesc);
if (*bh)
if (epos->bh)
{
aed = (struct allocExtDesc *)(*bh)->b_data;
aed = (struct allocExtDesc *)epos->bh->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
}
@ -1635,10 +1637,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
}
if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
bloc->logicalBlockNum, sizeof(tag));
epos->block.logicalBlockNum, sizeof(tag));
else
udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
bloc->logicalBlockNum, sizeof(tag));
epos->block.logicalBlockNum, sizeof(tag));
switch (UDF_I_ALLOCTYPE(inode))
{
case ICBTAG_FLAG_AD_SHORT:
@ -1647,7 +1649,7 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
sad->extLength = cpu_to_le32(
EXT_NEXT_EXTENT_ALLOCDECS |
inode->i_sb->s_blocksize);
sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);
sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum);
break;
}
case ICBTAG_FLAG_AD_LONG:
@ -1656,60 +1658,57 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
lad->extLength = cpu_to_le32(
EXT_NEXT_EXTENT_ALLOCDECS |
inode->i_sb->s_blocksize);
lad->extLocation = cpu_to_lelb(*bloc);
lad->extLocation = cpu_to_lelb(epos->block);
memset(lad->impUse, 0x00, sizeof(lad->impUse));
break;
}
}
if (*bh)
if (epos->bh)
{
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag((*bh)->b_data, loffset);
udf_update_tag(epos->bh->b_data, loffset);
else
udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(*bh, inode);
udf_release_data(*bh);
udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos->bh, inode);
udf_release_data(epos->bh);
}
else
mark_inode_dirty(inode);
*bh = nbh;
epos->bh = nbh;
}
etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
etype = udf_write_aext(inode, epos, eloc, elen, inc);
if (!*bh)
if (!epos->bh)
{
UDF_I_LENALLOC(inode) += adsize;
mark_inode_dirty(inode);
}
else
{
aed = (struct allocExtDesc *)(*bh)->b_data;
aed = (struct allocExtDesc *)epos->bh->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));
udf_update_tag(epos->bh->b_data, epos->offset + (inc ? 0 : adsize));
else
udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(*bh, inode);
udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos->bh, inode);
}
return etype;
}
int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
kernel_lb_addr eloc, uint32_t elen, int inc)
{
int adsize;
uint8_t *ptr;
if (!bh)
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
if (!epos->bh)
ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
else
{
ptr = bh->b_data + *extoffset;
atomic_inc(&bh->b_count);
}
ptr = epos->bh->b_data + epos->offset;
switch (UDF_I_ALLOCTYPE(inode))
{
@ -1734,40 +1733,39 @@ int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
return -1;
}
if (bh)
if (epos->bh)
{
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
{
struct allocExtDesc *aed = (struct allocExtDesc *)(bh)->b_data;
udf_update_tag((bh)->b_data,
struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data;
udf_update_tag(epos->bh->b_data,
le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
}
mark_buffer_dirty_inode(bh, inode);
udf_release_data(bh);
mark_buffer_dirty_inode(epos->bh, inode);
}
else
mark_inode_dirty(inode);
if (inc)
*extoffset += adsize;
epos->offset += adsize;
return (elen >> 30);
}
int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
kernel_lb_addr *eloc, uint32_t *elen, int inc)
{
int8_t etype;
while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
(EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
*bloc = *eloc;
*extoffset = sizeof(struct allocExtDesc);
udf_release_data(*bh);
if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
epos->block = *eloc;
epos->offset = sizeof(struct allocExtDesc);
udf_release_data(epos->bh);
if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
udf_get_lb_pblock(inode->i_sb, epos->block, 0));
return -1;
}
}
@ -1775,26 +1773,26 @@ int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
return etype;
}
int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
kernel_lb_addr *eloc, uint32_t *elen, int inc)
{
int alen;
int8_t etype;
uint8_t *ptr;
if (!*bh)
if (!epos->bh)
{
if (!(*extoffset))
*extoffset = udf_file_entry_alloc_offset(inode);
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
if (!epos->offset)
epos->offset = udf_file_entry_alloc_offset(inode);
ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
}
else
{
if (!(*extoffset))
*extoffset = sizeof(struct allocExtDesc);
ptr = (*bh)->b_data + *extoffset;
alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
if (!epos->offset)
epos->offset = sizeof(struct allocExtDesc);
ptr = epos->bh->b_data + epos->offset;
alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs);
}
switch (UDF_I_ALLOCTYPE(inode))
@ -1803,7 +1801,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
{
short_ad *sad;
if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc)))
return -1;
etype = le32_to_cpu(sad->extLength) >> 30;
@ -1816,7 +1814,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
{
long_ad *lad;
if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc)))
return -1;
etype = le32_to_cpu(lad->extLength) >> 30;
@ -1835,41 +1833,40 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
}
static int8_t
udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
udf_insert_aext(struct inode *inode, struct extent_position epos,
kernel_lb_addr neloc, uint32_t nelen)
{
kernel_lb_addr oeloc;
uint32_t oelen;
int8_t etype;
if (bh)
atomic_inc(&bh->b_count);
if (epos.bh)
atomic_inc(&epos.bh->b_count);
while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1)
{
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
udf_write_aext(inode, &epos, neloc, nelen, 1);
neloc = oeloc;
nelen = (etype << 30) | oelen;
}
udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
udf_release_data(bh);
udf_add_aext(inode, &epos, neloc, nelen, 1);
udf_release_data(epos.bh);
return (nelen >> 30);
}
int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
kernel_lb_addr eloc, uint32_t elen)
{
struct buffer_head *obh;
kernel_lb_addr obloc;
int oextoffset, adsize;
struct extent_position oepos;
int adsize;
int8_t etype;
struct allocExtDesc *aed;
if (nbh)
if (epos.bh)
{
atomic_inc(&nbh->b_count);
atomic_inc(&nbh->b_count);
atomic_inc(&epos.bh->b_count);
atomic_inc(&epos.bh->b_count);
}
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@ -1879,78 +1876,75 @@ int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset
else
adsize = 0;
obh = nbh;
obloc = nbloc;
oextoffset = nextoffset;
if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
oepos = epos;
if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
return -1;
while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
{
udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
if (obh != nbh)
udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);
if (oepos.bh != epos.bh)
{
obloc = nbloc;
udf_release_data(obh);
atomic_inc(&nbh->b_count);
obh = nbh;
oextoffset = nextoffset - adsize;
oepos.block = epos.block;
udf_release_data(oepos.bh);
atomic_inc(&epos.bh->b_count);
oepos.bh = epos.bh;
oepos.offset = epos.offset - adsize;
}
}
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = 0;
if (nbh != obh)
if (epos.bh != oepos.bh)
{
udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!obh)
udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);
udf_write_aext(inode, &oepos, eloc, elen, 1);
udf_write_aext(inode, &oepos, eloc, elen, 1);
if (!oepos.bh)
{
UDF_I_LENALLOC(inode) -= (adsize * 2);
mark_inode_dirty(inode);
}
else
{
aed = (struct allocExtDesc *)(obh)->b_data;
aed = (struct allocExtDesc *)oepos.bh->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag((obh)->b_data, oextoffset - (2*adsize));
udf_update_tag(oepos.bh->b_data, oepos.offset - (2*adsize));
else
udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(obh, inode);
udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(oepos.bh, inode);
}
}
else
{
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!obh)
udf_write_aext(inode, &oepos, eloc, elen, 1);
if (!oepos.bh)
{
UDF_I_LENALLOC(inode) -= adsize;
mark_inode_dirty(inode);
}
else
{
aed = (struct allocExtDesc *)(obh)->b_data;
aed = (struct allocExtDesc *)oepos.bh->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag((obh)->b_data, oextoffset - adsize);
udf_update_tag(oepos.bh->b_data, epos.offset - adsize);
else
udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(obh, inode);
udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(oepos.bh, inode);
}
}
udf_release_data(nbh);
udf_release_data(obh);
udf_release_data(epos.bh);
udf_release_data(oepos.bh);
return (elen >> 30);
}
int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uint32_t *extoffset,
kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset, struct buffer_head **bh)
int8_t inode_bmap(struct inode *inode, sector_t block, struct extent_position *pos,
kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset)
{
loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
int8_t etype;
@ -1961,13 +1955,14 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
return -1;
}
*extoffset = 0;
pos->offset = 0;
pos->block = UDF_I_LOCATION(inode);
pos->bh = NULL;
*elen = 0;
*bloc = UDF_I_LOCATION(inode);
do
{
if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1)
{
*offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
UDF_I_LENEXTENTS(inode) = lbcount;
@ -1983,21 +1978,21 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
long udf_block_map(struct inode *inode, sector_t block)
{
kernel_lb_addr eloc, bloc;
uint32_t extoffset, elen;
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
struct buffer_head *bh = NULL;
struct extent_position epos = { NULL, 0, { 0, 0}};
int ret;
lock_kernel();
if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
else
ret = 0;
unlock_kernel();
udf_release_data(bh);
udf_release_data(epos.bh);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
return udf_fixed_to_variable(ret);

View File

@ -155,10 +155,10 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
uint8_t lfi;
uint16_t liu;
loff_t size;
kernel_lb_addr bloc, eloc;
uint32_t extoffset, elen;
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
struct buffer_head *bh = NULL;
struct extent_position epos = { NULL, 0, { 0, 0}};
size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
f_pos = (udf_ext0_offset(dir) >> 2);
@ -167,41 +167,41 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
fibh->sbh = fibh->ebh = NULL;
else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
epos.offset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
extoffset -= sizeof(long_ad);
epos.offset -= sizeof(long_ad);
}
else
offset = 0;
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
udf_release_data(epos.bh);
return NULL;
}
}
else
{
udf_release_data(bh);
udf_release_data(epos.bh);
return NULL;
}
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
if (!fi)
{
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return NULL;
}
@ -247,7 +247,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
{
if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
{
udf_release_data(bh);
udf_release_data(epos.bh);
return fi;
}
}
@ -255,7 +255,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return NULL;
}
@ -353,10 +353,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
uint8_t lfi;
uint16_t liu;
int block;
kernel_lb_addr bloc, eloc;
uint32_t extoffset, elen;
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
struct buffer_head *bh = NULL;
struct extent_position epos = { NULL, 0, { 0, 0 }};
sb = dir->i_sb;
@ -385,22 +385,22 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
fibh->sbh = fibh->ebh = NULL;
else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
epos.offset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
extoffset -= sizeof(long_ad);
epos.offset -= sizeof(long_ad);
}
else
offset = 0;
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
udf_release_data(epos.bh);
*err = -EIO;
return NULL;
}
@ -418,14 +418,14 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
if (!fi)
{
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
*err = -EIO;
return NULL;
}
@ -455,7 +455,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
{
if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
{
udf_release_data(bh);
udf_release_data(epos.bh);
cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
@ -480,7 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
*err = -EEXIST;
return NULL;
}
@ -492,8 +492,8 @@ add:
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
sb->s_blocksize - fibh->eoffset < nfidlen)
{
udf_release_data(bh);
bh = NULL;
udf_release_data(epos.bh);
epos.bh = NULL;
fibh->soffset -= udf_ext0_offset(dir);
fibh->eoffset -= udf_ext0_offset(dir);
f_pos -= (udf_ext0_offset(dir) >> 2);
@ -502,15 +502,15 @@ add:
udf_release_data(fibh->sbh);
if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
return NULL;
bloc = UDF_I_LOCATION(dir);
epos.block = UDF_I_LOCATION(dir);
eloc.logicalBlockNum = block;
eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
elen = dir->i_sb->s_blocksize;
extoffset = udf_file_entry_alloc_offset(dir);
epos.offset = udf_file_entry_alloc_offset(dir);
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
extoffset += sizeof(short_ad);
epos.offset += sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
extoffset += sizeof(long_ad);
epos.offset += sizeof(long_ad);
}
if (sb->s_blocksize - fibh->eoffset >= nfidlen)
@ -550,14 +550,14 @@ add:
if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
{
udf_release_data(bh);
udf_release_data(epos.bh);
udf_release_data(fibh->sbh);
return NULL;
}
if (!(fibh->soffset))
{
if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
(EXT_RECORDED_ALLOCATED >> 30))
{
block = eloc.logicalBlockNum + ((elen - 1) >>
@ -587,7 +587,7 @@ add:
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
{
udf_release_data(bh);
udf_release_data(epos.bh);
dir->i_size += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
UDF_I_LENALLOC(dir) += nfidlen;
@ -596,7 +596,7 @@ add:
}
else
{
udf_release_data(bh);
udf_release_data(epos.bh);
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
@ -781,10 +781,10 @@ static int empty_dir(struct inode *dir)
loff_t f_pos;
loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
int block;
kernel_lb_addr bloc, eloc;
uint32_t extoffset, elen;
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
struct buffer_head *bh = NULL;
struct extent_position epos = { NULL, 0, { 0, 0}};
f_pos = (udf_ext0_offset(dir) >> 2);
@ -793,42 +793,42 @@ static int empty_dir(struct inode *dir)
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
fibh.sbh = fibh.ebh = NULL;
else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
epos.offset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
extoffset -= sizeof(long_ad);
epos.offset -= sizeof(long_ad);
}
else
offset = 0;
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
}
else
{
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
if (!fi)
{
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
@ -837,14 +837,14 @@ static int empty_dir(struct inode *dir)
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 0;
}
}
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
udf_release_data(epos.bh);
return 1;
}
@ -941,7 +941,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
struct pathComponent *pc;
char *compstart;
struct udf_fileident_bh fibh;
struct buffer_head *bh = NULL;
struct extent_position epos = { NULL, 0, {0, 0}};
int eoffset, elen = 0;
struct fileIdentDesc *fi;
struct fileIdentDesc cfi;
@ -961,33 +961,33 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
{
struct buffer_head *bh = NULL;
kernel_lb_addr bloc, eloc;
uint32_t elen, extoffset;
kernel_lb_addr eloc;
uint32_t elen;
block = udf_new_block(inode->i_sb, inode,
UDF_I_LOCATION(inode).partitionReferenceNum,
UDF_I_LOCATION(inode).logicalBlockNum, &err);
if (!block)
goto out_no_entry;
bloc = UDF_I_LOCATION(inode);
epos.block = UDF_I_LOCATION(inode);
epos.offset = udf_file_entry_alloc_offset(inode);
epos.bh = NULL;
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);
udf_add_aext(inode, &epos, eloc, elen, 0);
udf_release_data(epos.bh);
block = udf_get_pblock(inode->i_sb, block,
UDF_I_LOCATION(inode).partitionReferenceNum, 0);
bh = udf_tread(inode->i_sb, block);
lock_buffer(bh);
memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
set_buffer_uptodate(bh);
unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode);
ea = bh->b_data + udf_ext0_offset(inode);
epos.bh = udf_tread(inode->i_sb, block);
lock_buffer(epos.bh);
memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
set_buffer_uptodate(epos.bh);
unlock_buffer(epos.bh);
mark_buffer_dirty_inode(epos.bh, inode);
ea = epos.bh->b_data + udf_ext0_offset(inode);
}
else
ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
@ -1060,7 +1060,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
}
}
udf_release_data(bh);
udf_release_data(epos.bh);
inode->i_size = elen;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
UDF_I_LENALLOC(inode) = inode->i_size;

View File

@ -1883,21 +1883,20 @@ static unsigned int
udf_count_free_table(struct super_block *sb, struct inode * table)
{
unsigned int accum = 0;
uint32_t extoffset, elen;
kernel_lb_addr bloc, eloc;
uint32_t elen;
kernel_lb_addr eloc;
int8_t etype;
struct buffer_head *bh = NULL;
struct extent_position epos;
lock_kernel();
bloc = UDF_I_LOCATION(table);
extoffset = sizeof(struct unallocSpaceEntry);
epos.block = UDF_I_LOCATION(table);
epos.offset = sizeof(struct unallocSpaceEntry);
epos.bh = NULL;
while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
{
while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
accum += (elen >> table->i_sb->s_blocksize_bits);
}
udf_release_data(bh);
udf_release_data(epos.bh);
unlock_kernel();

View File

@ -28,8 +28,8 @@
#include "udf_i.h"
#include "udf_sb.h"
static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
static void extent_trunc(struct inode * inode, struct extent_position *epos,
kernel_lb_addr eloc, int8_t etype, uint32_t elen, uint32_t nelen)
{
kernel_lb_addr neloc = { 0, 0 };
int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
@ -49,7 +49,7 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
if (elen != nelen)
{
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
udf_write_aext(inode, epos, neloc, nelen, 0);
if (last_block - first_block > 0)
{
if (etype == (EXT_RECORDED_ALLOCATED >> 30))
@ -63,18 +63,16 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
void udf_discard_prealloc(struct inode * inode)
{
kernel_lb_addr bloc, eloc;
uint32_t extoffset = 0, elen, nelen;
struct extent_position epos = { NULL, 0, {0, 0}};
kernel_lb_addr eloc;
uint32_t elen, nelen;
uint64_t lbcount = 0;
int8_t etype = -1, netype;
struct buffer_head *bh = NULL;
int adsize;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
inode->i_size == UDF_I_LENEXTENTS(inode))
{
return;
}
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
@ -83,53 +81,55 @@ void udf_discard_prealloc(struct inode * inode)
else
adsize = 0;
bloc = UDF_I_LOCATION(inode);
epos.block = UDF_I_LOCATION(inode);
while ((netype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
/* Find the last extent in the file */
while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
{
etype = netype;
lbcount += elen;
if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
{
nelen = elen - (lbcount - inode->i_size);
extent_trunc(inode, bloc, extoffset-adsize, eloc, etype, elen, bh, nelen);
epos.offset -= adsize;
extent_trunc(inode, &epos, eloc, etype, elen, nelen);
epos.offset += adsize;
lbcount = inode->i_size;
}
}
if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
{
extoffset -= adsize;
if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
epos.offset -= adsize;
lbcount -= elen;
extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
if (!bh)
extent_trunc(inode, &epos, eloc, etype, elen, 0);
if (!epos.bh)
{
UDF_I_LENALLOC(inode) = extoffset - udf_file_entry_alloc_offset(inode);
UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode);
mark_inode_dirty(inode);
}
else
{
struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(extoffset - sizeof(struct allocExtDesc));
struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc));
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag(bh->b_data, extoffset);
udf_update_tag(epos.bh->b_data, epos.offset);
else
udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(bh, inode);
udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos.bh, inode);
}
}
UDF_I_LENEXTENTS(inode) = lbcount;
udf_release_data(bh);
udf_release_data(epos.bh);
}
void udf_truncate_extents(struct inode * inode)
{
kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
uint32_t extoffset, elen, nelen = 0, lelen = 0, lenalloc;
struct extent_position epos;
kernel_lb_addr eloc, neloc = { 0, 0 };
uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
int8_t etype;
sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
loff_t byte_offset;
struct buffer_head *bh = NULL;
int adsize;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@ -137,102 +137,98 @@ void udf_truncate_extents(struct inode * inode)
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
adsize = sizeof(long_ad);
else
adsize = 0;
BUG();
etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1));
if (etype != -1)
{
extoffset -= adsize;
extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, byte_offset);
extoffset += adsize;
epos.offset -= adsize;
extent_trunc(inode, &epos, eloc, etype, elen, byte_offset);
epos.offset += adsize;
if (byte_offset)
lenalloc = extoffset;
lenalloc = epos.offset;
else
lenalloc = extoffset - adsize;
lenalloc = epos.offset - adsize;
if (!bh)
if (!epos.bh)
lenalloc -= udf_file_entry_alloc_offset(inode);
else
lenalloc -= sizeof(struct allocExtDesc);
while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
while ((etype = udf_current_aext(inode, &epos, &eloc, &elen, 0)) != -1)
{
if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
extoffset = 0;
if (lelen)
udf_write_aext(inode, &epos, neloc, nelen, 0);
if (indirect_ext_len)
{
if (!bh)
/* We managed to free all extents in the
* indirect extent - free it too */
if (!epos.bh)
BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
}
else
{
if (!bh)
if (!epos.bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
}
else
{
struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag(bh->b_data, lenalloc +
udf_update_tag(epos.bh->b_data, lenalloc +
sizeof(struct allocExtDesc));
else
udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(bh, inode);
udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos.bh, inode);
}
}
udf_release_data(bh);
extoffset = sizeof(struct allocExtDesc);
bloc = eloc;
bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
brelse(epos.bh);
epos.offset = sizeof(struct allocExtDesc);
epos.block = eloc;
epos.bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, eloc, 0));
if (elen)
lelen = (elen + inode->i_sb->s_blocksize - 1) >>
indirect_ext_len = (elen +
inode->i_sb->s_blocksize - 1) >>
inode->i_sb->s_blocksize_bits;
else
lelen = 1;
indirect_ext_len = 1;
}
else
{
extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
extoffset += adsize;
extent_trunc(inode, &epos, eloc, etype, elen, 0);
epos.offset += adsize;
}
}
if (lelen)
if (indirect_ext_len)
{
if (!bh)
if (!epos.bh)
BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
}
else
{
if (!bh)
if (!epos.bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
}
else
{
struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag(bh->b_data, lenalloc +
udf_update_tag(epos.bh->b_data, lenalloc +
sizeof(struct allocExtDesc));
else
udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(bh, inode);
udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(epos.bh, inode);
}
}
}
@ -245,50 +241,51 @@ void udf_truncate_extents(struct inode * inode)
* no extent above inode->i_size => truncate is
* extending the file by 'offset'.
*/
if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
(bh && extoffset == sizeof(struct allocExtDesc))) {
if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
(epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
/* File has no extents at all! */
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
udf_add_aext(inode, &epos, eloc, elen, 1);
}
else {
extoffset -= adsize;
etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
epos.offset -= adsize;
etype = udf_next_aext(inode, &epos, &eloc, &elen, 1);
if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
{
extoffset -= adsize;
epos.offset -= adsize;
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset);
udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
udf_write_aext(inode, &epos, eloc, elen, 0);
}
else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
{
kernel_lb_addr neloc = { 0, 0 };
extoffset -= adsize;
epos.offset -= adsize;
nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
udf_write_aext(inode, &epos, neloc, nelen, 1);
udf_add_aext(inode, &epos, eloc, (etype << 30) | elen, 1);
}
else
{
if (elen & (inode->i_sb->s_blocksize - 1))
{
extoffset -= adsize;
epos.offset -= adsize;
elen = EXT_RECORDED_ALLOCATED |
((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, &epos, eloc, elen, 1);
}
memset(&eloc, 0x00, sizeof(kernel_lb_addr));
elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
udf_add_aext(inode, &epos, eloc, elen, 1);
}
}
}
}
UDF_I_LENEXTENTS(inode) = inode->i_size;
udf_release_data(bh);
udf_release_data(epos.bh);
}

View File

@ -77,6 +77,13 @@ struct ustr
uint8_t u_len;
};
struct extent_position {
struct buffer_head *bh;
uint32_t offset;
kernel_lb_addr block;
};
/* super.c */
extern void udf_error(struct super_block *, const char *, const char *, ...);
extern void udf_warning(struct super_block *, const char *, const char *, ...);
@ -99,12 +106,12 @@ extern void udf_delete_inode(struct inode *);
extern void udf_clear_inode(struct inode *);
extern int udf_write_inode(struct inode *, int);
extern long udf_block_map(struct inode *, sector_t);
extern int8_t inode_bmap(struct inode *, sector_t, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
extern int8_t udf_add_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
extern int8_t udf_write_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
extern int8_t udf_delete_aext(struct inode *, struct extent_position, kernel_lb_addr, uint32_t);
extern int8_t udf_next_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
extern int8_t udf_current_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
/* misc.c */
extern struct buffer_head *udf_tgetblk(struct super_block *, int);
@ -151,7 +158,7 @@ extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_
extern int udf_fsync_file(struct file *, struct dentry *, int);
/* directory.c */
extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);