These changes are crafted based on the similar conversion done to ext2 by Nick Piggin. Please check me out I bound to have miss-looked something. - Remove the deprecated ->truncate vector, call a new exofs_setsize for on-disk size update, from exofs_setattr - Call truncate_pagecache on the unused pages if write_begin/end fails. - Cleanup exofs_delete_inode that did stupid inode writes and updates on an inode that will be removed. - And finally get rid of exofs_get_block. We never had any blocks it was all for calling nobh_truncate_page. nobh_truncate_page is not actually needed in exofs since the last page is complete and gone just like all the other pages. There is no partial blocks in exofs. [OK do I might need a partial read here upto i_size ???] I've tested with this patch, and there are no apparent failures, so far. These patches are based on Al's vfs for-next branch, which contain Nick's last patches. But they do not contain, (and will lightly conflict with) latest Christoph's patches. Christoph do you have a tree I can rebase on? or maybe you want to take this patch into your patchset? CC: Christoph Hellwig <hch@xxxxxx> CC: Nick Piggin <npiggin@xxxxxxx> Signed-off-by: Boaz Harrosh <bharrosh@xxxxxxxxxxx> --- fs/exofs/exofs.h | 1 - fs/exofs/file.c | 1 - fs/exofs/inode.c | 115 +++++++++++++++++++++++++++--------------------------- 3 files changed, 58 insertions(+), 59 deletions(-) diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 22721b2..0706ce9 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -256,7 +256,6 @@ static inline int exofs_oi_read(struct exofs_i_info *oi, } /* inode.c */ -void exofs_truncate(struct inode *inode); int exofs_setattr(struct dentry *, struct iattr *); int exofs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, diff --git a/fs/exofs/file.c b/fs/exofs/file.c index fef6899..f9bfe2b 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -86,6 +86,5 @@ const struct file_operations exofs_file_operations = { }; const struct inode_operations exofs_file_inode_operations = { - .truncate = exofs_truncate, .setattr = exofs_setattr, }; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 4bb6ef8..1c2666c 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -710,7 +710,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, fsdata); if (ret) { EXOFS_DBGMSG("simple_write_begin faild\n"); - return ret; + goto out; } page = *pagep; @@ -725,7 +725,17 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, EXOFS_DBGMSG("__readpage_filler faild\n"); } } +out: + if (unlikely(ret)) { + struct inode *inode = mapping->host; + loff_t to = pos + len; + if (to > inode->i_size) + truncate_pagecache(inode, to, inode->i_size); + + mark_inode_dirty(inode); /* write the new size */ + return ret; + } return ret; } @@ -750,6 +760,10 @@ static int exofs_write_end(struct file *file, struct address_space *mapping, int ret; ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); + if (unlikely(ret && pos + len > inode->i_size)) + truncate_pagecache(inode, pos + len, inode->i_size); + + /* TODO: once simple_write_end marks inode dirty remove */ if (i_size != inode->i_size) mark_inode_dirty(inode); return ret; @@ -808,35 +822,18 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode) return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); } -/* - * get_block_t - Fill in a buffer_head - * An OSD takes care of block allocation so we just fake an allocation by - * putting in the inode's sector_t in the buffer_head. - * TODO: What about the case of create==0 and @iblock does not exist in the - * object? - */ -static int exofs_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh_result, int create) -{ - map_bh(bh_result, inode->i_sb, iblock); - return 0; -} - const struct osd_attr g_attr_logical_length = ATTR_DEF( OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); -static int _do_truncate(struct inode *inode) +static int _do_truncate(struct inode *inode, loff_t newsize) { struct exofs_i_info *oi = exofs_i(inode); - loff_t isize = i_size_read(inode); int ret; inode->i_mtime = inode->i_ctime = CURRENT_TIME; - nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); - - ret = exofs_oi_truncate(oi, (u64)isize); - EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize); + ret = exofs_oi_truncate(oi, (u64)newsize); + EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, newsize); return ret; } @@ -844,35 +841,28 @@ static int _do_truncate(struct inode *inode) * Truncate a file to the specified size - all we have to do is set the size * attribute. We make sure the object exists first. */ -void exofs_truncate(struct inode *inode) +static int exofs_setsize(struct inode *inode, loff_t newsize) { - struct exofs_i_info *oi = exofs_i(inode); - int ret; + loff_t oldsize; + int error; - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) - || S_ISLNK(inode->i_mode))) - return; + error = inode_newsize_ok(inode, newsize); + if (error) + return error; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return -EINVAL; if (exofs_inode_is_fast_symlink(inode)) - return; + return -EINVAL; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - - /* if we are about to truncate an object, and it hasn't been - * created yet, wait - */ - if (unlikely(wait_obj_created(oi))) - goto fail; + return -EPERM; - ret = _do_truncate(inode); - if (ret) - goto fail; + oldsize = inode->i_size; + i_size_write(inode, newsize); + truncate_pagecache(inode, oldsize, newsize); -out: - mark_inode_dirty(inode); - return; -fail: - make_bad_inode(inode); - goto out; + return _do_truncate(inode, newsize); } /* @@ -883,11 +873,25 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr) struct inode *inode = dentry->d_inode; int error; + /* if we are about to modify an object, and it hasn't been + * created yet, wait + */ + error = wait_obj_created(exofs_i(inode)); + if (unlikely(error)) + return error; + error = inode_change_ok(inode, iattr); if (error) return error; - error = inode_setattr(inode, iattr); + if (iattr->ia_valid & ATTR_SIZE) { + error = exofs_setsize(inode, iattr->ia_size); + if (error) + return error; + } + generic_setattr(inode, iattr); + mark_inode_dirty(inode); + return error; } @@ -1335,28 +1339,25 @@ void exofs_delete_inode(struct inode *inode) truncate_inode_pages(&inode->i_data, 0); + /* TODO: should do better here */ if (is_bad_inode(inode)) goto no_delete; - mark_inode_dirty(inode); - exofs_update_inode(inode, inode_needs_sync(inode)); - inode->i_size = 0; - if (inode->i_blocks) - exofs_truncate(inode); - clear_inode(inode); - ret = exofs_get_io_state(&sbi->layout, &ios); - if (unlikely(ret)) { - EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); - return; - } - /* if we are deleting an obj that hasn't been created yet, wait */ if (!obj_created(oi)) { BUG_ON(!obj_2bcreated(oi)); wait_event(oi->i_wq, obj_created(oi)); + /* ignore the error attempt a remove anyway */ + } + + /* Now Remove the OSD objects */ + ret = exofs_get_io_state(&sbi->layout, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); + return; } ios->obj.id = exofs_oi_objno(oi); -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html