diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/aops.c | 10 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 27 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 18 | ||||
-rw-r--r-- | fs/gfs2/super.c | 43 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 24 |
5 files changed, 71 insertions, 51 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 5e96cbd8a454..194fe16d8418 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -697,12 +697,12 @@ out: page_cache_release(page); /* - * XXX(hch): the call below should probably be replaced with + * XXX(truncate): the call below should probably be replaced with * a call to the gfs2-specific truncate blocks helper to actually * release disk blocks.. */ if (pos + len > ip->i_inode.i_size) - simple_setsize(&ip->i_inode, ip->i_inode.i_size); + truncate_setsize(&ip->i_inode, ip->i_inode.i_size); out_endtrans: gfs2_trans_end(sdp); out_trans_fail: @@ -1042,9 +1042,9 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, if (rv != 1) goto out; /* dio not valid, fall back to buffered i/o */ - rv = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev, - iov, offset, nr_segs, - gfs2_get_block_direct, NULL); + rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, gfs2_get_block_direct, + NULL, NULL, 0); out: gfs2_glock_dq_m(1, &gh); gfs2_holder_uninit(&gh); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index f03afd9c44bc..08140f185a37 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -84,7 +84,7 @@ static int iget_skip_test(struct inode *inode, void *opaque) struct gfs2_skip_data *data = opaque; if (ip->i_no_addr == data->no_addr) { - if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ + if (inode->i_state & (I_FREEING|I_WILL_FREE)){ data->skipped = 1; return 0; } @@ -991,18 +991,29 @@ fail: static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { + struct inode *inode = &ip->i_inode; struct buffer_head *dibh; int error; error = gfs2_meta_inode_buffer(ip, &dibh); - if (!error) { - error = inode_setattr(&ip->i_inode, attr); - gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); + if (error) + return error; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + error = vmtruncate(inode, attr->ia_size); + if (error) + return error; } - return error; + + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + gfs2_assert_warn(GFS2_SB(inode), !error); + gfs2_trans_add_bh(ip->i_gl, dibh, 1); + gfs2_dinode_out(ip, dibh->b_data); + brelse(dibh); + return 0; } /** diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 98cdd05f3316..1009be2c9737 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -1072,7 +1072,7 @@ int gfs2_permission(struct inode *inode, int mask) } /* - * XXX: should be changed to have proper ordering by opencoding simple_setsize + * XXX(truncate): the truncate_setsize calls should be moved to the end. */ static int setattr_size(struct inode *inode, struct iattr *attr) { @@ -1084,10 +1084,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr) error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); if (error) return error; - error = simple_setsize(inode, attr->ia_size); + truncate_setsize(inode, attr->ia_size); gfs2_trans_end(sdp); - if (error) - return error; } error = gfs2_truncatei(ip, attr->ia_size); @@ -1136,8 +1134,16 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) if (error) goto out_end_trans; - error = inode_setattr(inode, attr); - gfs2_assert_warn(sdp, !error); + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, attr->ia_size); + gfs2_assert_warn(sdp, !error); + } + + setattr_copy(inode, attr); + mark_inode_dirty(inode); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 4140811a921c..77cb9f830ee4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1188,7 +1188,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) * node for later deallocation. */ -static void gfs2_drop_inode(struct inode *inode) +static int gfs2_drop_inode(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); @@ -1197,26 +1197,7 @@ static void gfs2_drop_inode(struct inode *inode) if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) clear_nlink(inode); } - generic_drop_inode(inode); -} - -/** - * gfs2_clear_inode - Deallocate an inode when VFS is done with it - * @inode: The VFS inode - * - */ - -static void gfs2_clear_inode(struct inode *inode) -{ - struct gfs2_inode *ip = GFS2_I(inode); - - ip->i_gl->gl_object = NULL; - gfs2_glock_put(ip->i_gl); - ip->i_gl = NULL; - if (ip->i_iopen_gh.gh_gl) { - ip->i_iopen_gh.gh_gl->gl_object = NULL; - gfs2_glock_dq_uninit(&ip->i_iopen_gh); - } + return generic_drop_inode(inode); } static int is_ancestor(const struct dentry *d1, const struct dentry *d2) @@ -1344,13 +1325,16 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) * is safe, just less efficient. */ -static void gfs2_delete_inode(struct inode *inode) +static void gfs2_evict_inode(struct inode *inode) { struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int error; + if (inode->i_nlink) + goto out; + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); if (unlikely(error)) { gfs2_glock_dq_uninit(&ip->i_iopen_gh); @@ -1404,10 +1388,18 @@ out_unlock: gfs2_holder_uninit(&ip->i_iopen_gh); gfs2_glock_dq_uninit(&gh); if (error && error != GLR_TRYFAILED && error != -EROFS) - fs_warn(sdp, "gfs2_delete_inode: %d\n", error); + fs_warn(sdp, "gfs2_evict_inode: %d\n", error); out: truncate_inode_pages(&inode->i_data, 0); - clear_inode(inode); + end_writeback(inode); + + ip->i_gl->gl_object = NULL; + gfs2_glock_put(ip->i_gl); + ip->i_gl = NULL; + if (ip->i_iopen_gh.gh_gl) { + ip->i_iopen_gh.gh_gl->gl_object = NULL; + gfs2_glock_dq_uninit(&ip->i_iopen_gh); + } } static struct inode *gfs2_alloc_inode(struct super_block *sb) @@ -1431,14 +1423,13 @@ const struct super_operations gfs2_super_ops = { .alloc_inode = gfs2_alloc_inode, .destroy_inode = gfs2_destroy_inode, .write_inode = gfs2_write_inode, - .delete_inode = gfs2_delete_inode, + .evict_inode = gfs2_evict_inode, .put_super = gfs2_put_super, .sync_fs = gfs2_sync_fs, .freeze_fs = gfs2_freeze, .unfreeze_fs = gfs2_unfreeze, .statfs = gfs2_statfs, .remount_fs = gfs2_remount_fs, - .clear_inode = gfs2_clear_inode, .drop_inode = gfs2_drop_inode, .show_options = gfs2_show_options, }; diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 82f93da00d1b..776af6eb4bcb 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -1296,6 +1296,7 @@ fail: int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) { + struct inode *inode = &ip->i_inode; struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_ea_location el; struct buffer_head *dibh; @@ -1321,14 +1322,25 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) return error; error = gfs2_meta_inode_buffer(ip, &dibh); - if (!error) { - error = inode_setattr(&ip->i_inode, attr); - gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); + if (error) + goto out_trans_end; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + int error; + + error = vmtruncate(inode, attr->ia_size); + gfs2_assert_warn(GFS2_SB(inode), !error); } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + gfs2_trans_add_bh(ip->i_gl, dibh, 1); + gfs2_dinode_out(ip, dibh->b_data); + brelse(dibh); + +out_trans_end: gfs2_trans_end(sdp); return error; } |