mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
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:
parent
60448b1d6d
commit
ff116fc8d1
172
fs/udf/balloc.c
172
fs/udf/balloc.c
@ -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))
|
||||
{
|
||||
|
25
fs/udf/dir.c
25
fs/udf/dir.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
343
fs/udf/inode.c
343
fs/udf/inode.c
@ -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);
|
||||
|
122
fs/udf/namei.c
122
fs/udf/namei.c
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user