Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 54816
b: refs/heads/master
c: 31170b6
h: refs/heads/master
v: v3
  • Loading branch information
Jan Kara authored and Linus Torvalds committed May 8, 2007
1 parent 1340df0 commit 1cb8c2a
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 83 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 948b9b2c967c3bec6136b2dbb9e1c12f62e03efa
refs/heads/master: 31170b6ad4ebe6c43c1cc3b8112274cf59474de0
192 changes: 157 additions & 35 deletions trunk/fs/udf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,106 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
return NULL;
}

/* Extend the file by 'blocks' blocks, return the number of extents added */
int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
kernel_long_ad *last_ext, sector_t blocks)
{
sector_t add;
int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
struct super_block *sb = inode->i_sb;
kernel_lb_addr prealloc_loc = {0, 0};
int prealloc_len = 0;

/* The previous extent is fake and we should not extend by anything
* - there's nothing to do... */
if (!blocks && fake)
return 0;
/* Round the last extent up to a multiple of block size */
if (last_ext->extLength & (sb->s_blocksize - 1)) {
last_ext->extLength =
(last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
(((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
UDF_I_LENEXTENTS(inode) =
(UDF_I_LENEXTENTS(inode) + sb->s_blocksize - 1) &
~(sb->s_blocksize - 1);
}
/* Last extent are just preallocated blocks? */
if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_ALLOCATED) {
/* Save the extent so that we can reattach it to the end */
prealloc_loc = last_ext->extLocation;
prealloc_len = last_ext->extLength;
/* Mark the extent as a hole */
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
last_ext->extLocation.logicalBlockNum = 0;
last_ext->extLocation.partitionReferenceNum = 0;
}
/* Can we merge with the previous extent? */
if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) {
add = ((1<<30) - sb->s_blocksize - (last_ext->extLength &
UDF_EXTENT_LENGTH_MASK)) >> sb->s_blocksize_bits;
if (add > blocks)
add = blocks;
blocks -= add;
last_ext->extLength += add << sb->s_blocksize_bits;
}

if (fake) {
udf_add_aext(inode, last_pos, last_ext->extLocation,
last_ext->extLength, 1);
count++;
}
else
udf_write_aext(inode, last_pos, last_ext->extLocation, last_ext->extLength, 1);
/* Managed to do everything necessary? */
if (!blocks)
goto out;

/* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
last_ext->extLocation.logicalBlockNum = 0;
last_ext->extLocation.partitionReferenceNum = 0;
add = (1 << (30-sb->s_blocksize_bits)) - 1;
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | (add << sb->s_blocksize_bits);
/* Create enough extents to cover the whole hole */
while (blocks > add) {
blocks -= add;
if (udf_add_aext(inode, last_pos, last_ext->extLocation,
last_ext->extLength, 1) == -1)
return -1;
count++;
}
if (blocks) {
last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
(blocks << sb->s_blocksize_bits);
if (udf_add_aext(inode, last_pos, last_ext->extLocation,
last_ext->extLength, 1) == -1)
return -1;
count++;
}
out:
/* Do we have some preallocated blocks saved? */
if (prealloc_len) {
if (udf_add_aext(inode, last_pos, prealloc_loc, prealloc_len, 1) == -1)
return -1;
last_ext->extLocation = prealloc_loc;
last_ext->extLength = prealloc_len;
count++;
}
/* last_pos should point to the last written extent... */
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
last_pos->offset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
last_pos->offset -= sizeof(long_ad);
else
return -1;
return count;
}

static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
int *err, long *phys, int *new)
{
static sector_t last_block;
struct buffer_head *result = NULL;
kernel_long_ad laarr[EXTENT_MERGE_SIZE];
struct extent_position prev_epos, cur_epos, next_epos;
Expand All @@ -371,7 +468,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
sector_t offset = 0;
int8_t etype;
int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
char lastblock = 0;
int lastblock = 0;

prev_epos.offset = udf_file_entry_alloc_offset(inode);
prev_epos.block = UDF_I_LOCATION(inode);
Expand Down Expand Up @@ -423,6 +520,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,

b_off -= lbcount;
offset = b_off >> inode->i_sb->s_blocksize_bits;
/* Move into indirect extent if we are at a pointer to it */
udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);

/* if the extent is allocated and recorded, return the block
if the extent is not a multiple of the blocksize, round up */
Expand All @@ -444,43 +543,66 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
return NULL;
}

last_block = block;
/* Are we beyond EOF? */
if (etype == -1)
{
endnum = startnum = ((count > 1) ? 1 : count);
if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
{
laarr[c].extLength =
(laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
(((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
UDF_I_LENEXTENTS(inode) =
(UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1);
int ret;

if (count) {
if (c)
laarr[0] = laarr[1];
startnum = 1;
}
else {
/* Create a fake extent when there's not one */
memset(&laarr[0].extLocation, 0x00, sizeof(kernel_lb_addr));
laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
/* Will udf_extend_file() create real extent from a fake one? */
startnum = (offset > 0);
}
/* Create extents for the hole between EOF and offset */
ret = udf_extend_file(inode, &prev_epos, laarr, offset);
if (ret == -1) {
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
/* We don't really know the error here so we just make
* something up */
*err = -ENOSPC;
return NULL;
}
c = !c;
laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
((offset + 1) << inode->i_sb->s_blocksize_bits);
memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
count ++;
endnum ++;
c = 0;
offset = 0;
count += ret;
/* We are not covered by a preallocated extent? */
if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != EXT_NOT_RECORDED_ALLOCATED) {
/* Is there any real extent? - otherwise we overwrite
* the fake one... */
if (count)
c = !c;
laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
inode->i_sb->s_blocksize;
memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
count ++;
endnum ++;
}
endnum = c+1;
lastblock = 1;
}
else
else {
endnum = startnum = ((count > 2) ? 2 : count);

/* if the current extent is in position 0, swap it with the previous */
if (!c && count != 1)
{
laarr[2] = laarr[0];
laarr[0] = laarr[1];
laarr[1] = laarr[2];
c = 1;
}
/* if the current extent is in position 0, swap it with the previous */
if (!c && count != 1)
{
laarr[2] = laarr[0];
laarr[0] = laarr[1];
laarr[1] = laarr[2];
c = 1;
}

/* if the current block is located in a extent, read the next extent */
if (etype != -1)
{
/* if the current block is located in an extent, read the next extent */
if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
{
laarr[c+1].extLength = (etype << 30) | elen;
Expand All @@ -489,11 +611,10 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
startnum ++;
endnum ++;
}
else
else {
lastblock = 1;
}
}
brelse(cur_epos.bh);
brelse(next_epos.bh);

/* if the current extent is not recorded but allocated, get the
block in the extent corresponding to the requested block */
Expand Down Expand Up @@ -534,8 +655,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
udf_merge_extents(inode, laarr, &endnum);

/* 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 */
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, &prev_epos);

brelse(prev_epos.bh);
Expand Down Expand Up @@ -991,6 +1112,7 @@ __udf_read_inode(struct inode *inode)
return;
}
udf_fill_inode(inode, bh);

brelse(bh);
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/udf/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
iput(inode);
goto error_out;
}
sb->s_maxbytes = 1<<30;
sb->s_maxbytes = MAX_LFS_FILESIZE;
return 0;

error_out:
Expand Down
Loading

0 comments on commit 1cb8c2a

Please sign in to comment.