Commit 7e49b6f2 authored by Jan Kara's avatar Jan Kara

udf: Convert UDF to new truncate calling sequence

Use new truncation sequence in UDF and fix up error handling in the
code.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 4a508dd2
...@@ -123,8 +123,8 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -123,8 +123,8 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (inode->i_sb->s_blocksize < if (inode->i_sb->s_blocksize <
(udf_file_entry_alloc_offset(inode) + (udf_file_entry_alloc_offset(inode) +
pos + count)) { pos + count)) {
udf_expand_file_adinicb(inode, pos + count, &err); err = udf_expand_file_adinicb(inode);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (err) {
udf_debug("udf_expand_adinicb: err=%d\n", err); udf_debug("udf_expand_adinicb: err=%d\n", err);
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
return err; return err;
...@@ -237,7 +237,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -237,7 +237,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) && if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) { attr->ia_size != i_size_read(inode)) {
error = vmtruncate(inode, attr->ia_size); error = udf_setsize(inode, attr->ia_size);
if (error) if (error)
return error; return error;
} }
...@@ -249,5 +249,4 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -249,5 +249,4 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
const struct inode_operations udf_file_inode_operations = { const struct inode_operations udf_file_inode_operations = {
.setattr = udf_setattr, .setattr = udf_setattr,
.truncate = udf_truncate,
}; };
This diff is collapsed.
...@@ -197,6 +197,11 @@ static void udf_update_alloc_ext_desc(struct inode *inode, ...@@ -197,6 +197,11 @@ static void udf_update_alloc_ext_desc(struct inode *inode,
mark_buffer_dirty_inode(epos->bh, inode); mark_buffer_dirty_inode(epos->bh, inode);
} }
/*
* Truncate extents of inode to inode->i_size. This function can be used only
* for making file shorter. For making file longer, udf_extend_file() has to
* be used.
*/
void udf_truncate_extents(struct inode *inode) void udf_truncate_extents(struct inode *inode)
{ {
struct extent_position epos; struct extent_position epos;
...@@ -219,96 +224,65 @@ void udf_truncate_extents(struct inode *inode) ...@@ -219,96 +224,65 @@ void udf_truncate_extents(struct inode *inode)
etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
byte_offset = (offset << sb->s_blocksize_bits) + byte_offset = (offset << sb->s_blocksize_bits) +
(inode->i_size & (sb->s_blocksize - 1)); (inode->i_size & (sb->s_blocksize - 1));
if (etype != -1) { if (etype == -1) {
epos.offset -= adsize; /* We should extend the file? */
extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); WARN_ON(byte_offset);
epos.offset += adsize; return;
if (byte_offset) }
lenalloc = epos.offset; epos.offset -= adsize;
else extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
lenalloc = epos.offset - adsize; epos.offset += adsize;
if (byte_offset)
if (!epos.bh) lenalloc = epos.offset;
lenalloc -= udf_file_entry_alloc_offset(inode); else
else lenalloc = epos.offset - adsize;
lenalloc -= sizeof(struct allocExtDesc);
while ((etype = udf_current_aext(inode, &epos, &eloc,
&elen, 0)) != -1) {
if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
udf_write_aext(inode, &epos, &neloc, nelen, 0);
if (indirect_ext_len) {
/* We managed to free all extents in the
* indirect extent - free it too */
BUG_ON(!epos.bh);
udf_free_blocks(sb, inode, &epos.block,
0, indirect_ext_len);
} else if (!epos.bh) {
iinfo->i_lenAlloc = lenalloc;
mark_inode_dirty(inode);
} else
udf_update_alloc_ext_desc(inode,
&epos, lenalloc);
brelse(epos.bh);
epos.offset = sizeof(struct allocExtDesc);
epos.block = eloc;
epos.bh = udf_tread(sb,
udf_get_lb_pblock(sb, &eloc, 0));
if (elen)
indirect_ext_len =
(elen + sb->s_blocksize - 1) >>
sb->s_blocksize_bits;
else
indirect_ext_len = 1;
} else {
extent_trunc(inode, &epos, &eloc, etype,
elen, 0);
epos.offset += adsize;
}
}
if (indirect_ext_len) { if (!epos.bh)
BUG_ON(!epos.bh); lenalloc -= udf_file_entry_alloc_offset(inode);
udf_free_blocks(sb, inode, &epos.block, 0, else
indirect_ext_len); lenalloc -= sizeof(struct allocExtDesc);
} else if (!epos.bh) {
iinfo->i_lenAlloc = lenalloc;
mark_inode_dirty(inode);
} else
udf_update_alloc_ext_desc(inode, &epos, lenalloc);
} else if (inode->i_size) {
if (byte_offset) {
struct kernel_long_ad extent;
/* while ((etype = udf_current_aext(inode, &epos, &eloc,
* OK, there is not extent covering inode->i_size and &elen, 0)) != -1) {
* no extent above inode->i_size => truncate is if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
* extending the file by 'offset' blocks. udf_write_aext(inode, &epos, &neloc, nelen, 0);
*/ if (indirect_ext_len) {
if ((!epos.bh && /* We managed to free all extents in the
epos.offset == * indirect extent - free it too */
udf_file_entry_alloc_offset(inode)) || BUG_ON(!epos.bh);
(epos.bh && epos.offset == udf_free_blocks(sb, inode, &epos.block,
sizeof(struct allocExtDesc))) { 0, indirect_ext_len);
/* File has no extents at all or has empty last } else if (!epos.bh) {
* indirect extent! Create a fake extent... */ iinfo->i_lenAlloc = lenalloc;
extent.extLocation.logicalBlockNum = 0; mark_inode_dirty(inode);
extent.extLocation.partitionReferenceNum = 0; } else
extent.extLength = udf_update_alloc_ext_desc(inode,
EXT_NOT_RECORDED_NOT_ALLOCATED; &epos, lenalloc);
} else { brelse(epos.bh);
epos.offset -= adsize; epos.offset = sizeof(struct allocExtDesc);
etype = udf_next_aext(inode, &epos, epos.block = eloc;
&extent.extLocation, epos.bh = udf_tread(sb,
&extent.extLength, 0); udf_get_lb_pblock(sb, &eloc, 0));
extent.extLength |= etype << 30; if (elen)
} indirect_ext_len =
udf_extend_file(inode, &epos, &extent, (elen + sb->s_blocksize - 1) >>
offset + sb->s_blocksize_bits;
((inode->i_size & else
(sb->s_blocksize - 1)) != 0)); indirect_ext_len = 1;
} else {
extent_trunc(inode, &epos, &eloc, etype, elen, 0);
epos.offset += adsize;
} }
} }
if (indirect_ext_len) {
BUG_ON(!epos.bh);
udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len);
} else if (!epos.bh) {
iinfo->i_lenAlloc = lenalloc;
mark_inode_dirty(inode);
} else
udf_update_alloc_ext_desc(inode, &epos, lenalloc);
iinfo->i_lenExtents = inode->i_size; iinfo->i_lenExtents = inode->i_size;
brelse(epos.bh); brelse(epos.bh);
......
...@@ -136,22 +136,20 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, ...@@ -136,22 +136,20 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
extern long udf_ioctl(struct file *, unsigned int, unsigned long); extern long udf_ioctl(struct file *, unsigned int, unsigned long);
/* inode.c */ /* inode.c */
extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
extern void udf_expand_file_adinicb(struct inode *, int, int *); extern int udf_expand_file_adinicb(struct inode *);
extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
extern struct buffer_head *udf_bread(struct inode *, int, int, int *); extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
extern void udf_truncate(struct inode *); extern int udf_setsize(struct inode *, loff_t);
extern void udf_read_inode(struct inode *); extern void udf_read_inode(struct inode *);
extern void udf_evict_inode(struct inode *); extern void udf_evict_inode(struct inode *);
extern int udf_write_inode(struct inode *, struct writeback_control *wbc); extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
extern long udf_block_map(struct inode *, sector_t); extern long udf_block_map(struct inode *, sector_t);
extern int udf_extend_file(struct inode *, struct extent_position *,
struct kernel_long_ad *, sector_t);
extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *,
struct kernel_lb_addr *, uint32_t *, sector_t *); struct kernel_lb_addr *, uint32_t *, sector_t *);
extern int8_t udf_add_aext(struct inode *, struct extent_position *, extern int udf_add_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t, int);
extern void udf_write_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t, int); struct kernel_lb_addr *, uint32_t, int);
extern int8_t udf_write_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t, int);
extern int8_t udf_delete_aext(struct inode *, struct extent_position, extern int8_t udf_delete_aext(struct inode *, struct extent_position,
struct kernel_lb_addr, uint32_t); struct kernel_lb_addr, uint32_t);
extern int8_t udf_next_aext(struct inode *, struct extent_position *, extern int8_t udf_next_aext(struct inode *, struct extent_position *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment