diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 11:26:52 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 11:26:52 -0700 |
commit | 5f248c9c251c60af3403902b26e08de43964ea0b (patch) | |
tree | 6d3328e72a7e4015a64017eb30be18095c6a3c64 /fs/exofs/inode.c | |
parent | f6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff) | |
parent | dca332528bc69e05f67161e1ed59929633d5e63d (diff) | |
download | blackbird-op-linux-5f248c9c251c60af3403902b26e08de43964ea0b.tar.gz blackbird-op-linux-5f248c9c251c60af3403902b26e08de43964ea0b.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (96 commits)
no need for list_for_each_entry_safe()/resetting with superblock list
Fix sget() race with failing mount
vfs: don't hold s_umount over close_bdev_exclusive() call
sysv: do not mark superblock dirty on remount
sysv: do not mark superblock dirty on mount
btrfs: remove junk sb_dirt change
BFS: clean up the superblock usage
AFFS: wait for sb synchronization when needed
AFFS: clean up dirty flag usage
cifs: truncate fallout
mbcache: fix shrinker function return value
mbcache: Remove unused features
add f_flags to struct statfs(64)
pass a struct path to vfs_statfs
update VFS documentation for method changes.
All filesystems that need invalidate_inode_buffers() are doing that explicitly
convert remaining ->clear_inode() to ->evict_inode()
Make ->drop_inode() just return whether inode needs to be dropped
fs/inode.c:clear_inode() is gone
fs/inode.c:evict() doesn't care about delete vs. non-delete paths now
...
Fix up trivial conflicts in fs/nilfs2/super.c
Diffstat (limited to 'fs/exofs/inode.c')
-rw-r--r-- | fs/exofs/inode.c | 127 |
1 files changed, 53 insertions, 74 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 4bb6ef822e46..088cb476b68a 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -697,6 +697,13 @@ static int exofs_writepage(struct page *page, struct writeback_control *wbc) return write_exec(&pcol); } +/* i_mutex held using inode->i_size directly */ +static void _write_failed(struct inode *inode, loff_t to) +{ + if (to > inode->i_size) + truncate_pagecache(inode, to, inode->i_size); +} + int exofs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -710,7 +717,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,6 +732,9 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, EXOFS_DBGMSG("__readpage_filler faild\n"); } } +out: + if (unlikely(ret)) + _write_failed(mapping->host, pos + len); 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)) + _write_failed(inode, pos + len); + + /* TODO: once simple_write_end marks inode dirty remove */ if (i_size != inode->i_size) mark_inode_dirty(inode); return ret; @@ -808,87 +822,55 @@ 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)newsize); + if (likely(!ret)) + truncate_setsize(inode, newsize); - ret = exofs_oi_truncate(oi, (u64)isize); - EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize); + EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n", + inode->i_ino, newsize, ret); return ret; } /* - * 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) -{ - struct exofs_i_info *oi = exofs_i(inode); - int ret; - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) - || S_ISLNK(inode->i_mode))) - return; - if (exofs_inode_is_fast_symlink(inode)) - return; - 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; - - ret = _do_truncate(inode); - if (ret) - goto fail; - -out: - mark_inode_dirty(inode); - return; -fail: - make_bad_inode(inode); - goto out; -} - -/* - * Set inode attributes - just call generic functions. + * Set inode attributes - update size attribute on OSD if needed, + * otherwise just call generic functions. */ 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) + if (unlikely(error)) return error; - error = inode_setattr(inode, iattr); - return error; + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(inode)) { + error = _do_truncate(inode, iattr->ia_size); + if (unlikely(error)) + return error; + } + + setattr_copy(inode, iattr); + mark_inode_dirty(inode); + return 0; } static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( @@ -1325,7 +1307,7 @@ static void delete_done(struct exofs_io_state *ios, void *p) * from the OSD here. We make sure the object was created before we try and * delete it. */ -void exofs_delete_inode(struct inode *inode) +void exofs_evict_inode(struct inode *inode) { struct exofs_i_info *oi = exofs_i(inode); struct super_block *sb = inode->i_sb; @@ -1335,30 +1317,27 @@ void exofs_delete_inode(struct inode *inode) truncate_inode_pages(&inode->i_data, 0); - if (is_bad_inode(inode)) + /* TODO: should do better here */ + if (inode->i_nlink || 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); + end_writeback(inode); - clear_inode(inode); + /* 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; } - /* 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)); - } - ios->obj.id = exofs_oi_objno(oi); ios->done = delete_done; ios->private = sbi; @@ -1374,5 +1353,5 @@ void exofs_delete_inode(struct inode *inode) return; no_delete: - clear_inode(inode); + end_writeback(inode); } |