diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/acl.c | 77 | ||||
-rw-r--r-- | fs/ocfs2/acl.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 41 | ||||
-rw-r--r-- | fs/ocfs2/file.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 1 | ||||
-rw-r--r-- | fs/ocfs2/refcounttree.c | 49 |
7 files changed, 69 insertions, 113 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index e913ad130fdd..783c58d9daf1 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -290,47 +290,32 @@ static int ocfs2_set_acl(handle_t *handle, return ret; } -int ocfs2_check_acl(struct inode *inode, int mask, unsigned int flags) +struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type) { struct ocfs2_super *osb; struct buffer_head *di_bh = NULL; struct posix_acl *acl; int ret = -EAGAIN; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - osb = OCFS2_SB(inode->i_sb); if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) - return ret; + return NULL; ret = ocfs2_read_inode_block(inode, &di_bh); - if (ret < 0) { - mlog_errno(ret); - return ret; - } + if (ret < 0) + return ERR_PTR(ret); - acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh); + acl = ocfs2_get_acl_nolock(inode, type, di_bh); brelse(di_bh); - if (IS_ERR(acl)) { - mlog_errno(PTR_ERR(acl)); - return PTR_ERR(acl); - } - if (acl) { - ret = posix_acl_permission(inode, acl, mask); - posix_acl_release(acl); - return ret; - } - - return -EAGAIN; + return acl; } int ocfs2_acl_chmod(struct inode *inode) { struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct posix_acl *acl, *clone; + struct posix_acl *acl; int ret; if (S_ISLNK(inode->i_mode)) @@ -342,15 +327,12 @@ int ocfs2_acl_chmod(struct inode *inode) acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS); if (IS_ERR(acl) || !acl) return PTR_ERR(acl); - clone = posix_acl_clone(acl, GFP_KERNEL); + ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); + if (ret) + return ret; + ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, + acl, NULL, NULL); posix_acl_release(acl); - if (!clone) - return -ENOMEM; - ret = posix_acl_chmod_masq(clone, inode->i_mode); - if (!ret) - ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS, - clone, NULL, NULL); - posix_acl_release(clone); return ret; } @@ -388,8 +370,6 @@ int ocfs2_init_acl(handle_t *handle, } } if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { - struct posix_acl *clone; - if (S_ISDIR(inode->i_mode)) { ret = ocfs2_set_acl(handle, inode, di_bh, ACL_TYPE_DEFAULT, acl, @@ -397,27 +377,22 @@ int ocfs2_init_acl(handle_t *handle, if (ret) goto cleanup; } - clone = posix_acl_clone(acl, GFP_NOFS); - ret = -ENOMEM; - if (!clone) - goto cleanup; - mode = inode->i_mode; - ret = posix_acl_create_masq(clone, &mode); - if (ret >= 0) { - ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); - if (ret2) { - mlog_errno(ret2); - ret = ret2; - goto cleanup; - } - if (ret > 0) { - ret = ocfs2_set_acl(handle, inode, - di_bh, ACL_TYPE_ACCESS, - clone, meta_ac, data_ac); - } + ret = posix_acl_create(&acl, GFP_NOFS, &mode); + if (ret < 0) + return ret; + + ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); + if (ret2) { + mlog_errno(ret2); + ret = ret2; + goto cleanup; + } + if (ret > 0) { + ret = ocfs2_set_acl(handle, inode, + di_bh, ACL_TYPE_ACCESS, + acl, meta_ac, data_ac); } - posix_acl_release(clone); } cleanup: posix_acl_release(acl); diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h index 4fe7c9cf4bfb..071fbd380f2f 100644 --- a/fs/ocfs2/acl.h +++ b/fs/ocfs2/acl.h @@ -26,7 +26,7 @@ struct ocfs2_acl_entry { __le32 e_id; }; -extern int ocfs2_check_acl(struct inode *, int, unsigned int); +struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type); extern int ocfs2_acl_chmod(struct inode *); extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *, struct buffer_head *, struct buffer_head *, diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index ac97bca282d2..c1efe939c774 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -551,9 +551,8 @@ bail: /* * ocfs2_dio_end_io is called by the dio core when a dio is finished. We're - * particularly interested in the aio/dio case. Like the core uses - * i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from - * truncation on another. + * particularly interested in the aio/dio case. We use the rw_lock DLM lock + * to protect io on one node from truncation on another. */ static void ocfs2_dio_end_io(struct kiocb *iocb, loff_t offset, @@ -568,10 +567,8 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, /* this io's submitter should not have unlocked this before we could */ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb)); - if (ocfs2_iocb_is_sem_locked(iocb)) { - up_read(&inode->i_alloc_sem); + if (ocfs2_iocb_is_sem_locked(iocb)) ocfs2_iocb_clear_sem_locked(iocb); - } ocfs2_iocb_clear_rw_locked(iocb); @@ -580,6 +577,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, if (is_async) aio_complete(iocb, ret, 0); + inode_dio_done(inode); } /* diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b1e35a392ca5..de4ea1af041b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -171,7 +171,8 @@ static int ocfs2_dir_release(struct inode *inode, struct file *file) return 0; } -static int ocfs2_sync_file(struct file *file, int datasync) +static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end, + int datasync) { int err = 0; journal_t *journal; @@ -184,6 +185,16 @@ static int ocfs2_sync_file(struct file *file, int datasync) file->f_path.dentry->d_name.name, (unsigned long long)datasync); + err = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (err) + return err; + + /* + * Probably don't need the i_mutex at all in here, just putting it here + * to be consistent with how fsync used to be called, someone more + * familiar with the fs could possibly remove it. + */ + mutex_lock(&inode->i_mutex); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) { /* * We still have to flush drive's caches to get data to the @@ -200,6 +211,7 @@ static int ocfs2_sync_file(struct file *file, int datasync) bail: if (err) mlog_errno(err); + mutex_unlock(&inode->i_mutex); return (err < 0) ? -EIO : 0; } @@ -1142,6 +1154,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) if (status) goto bail_unlock; + inode_dio_wait(inode); + if (i_size_read(inode) > attr->ia_size) { if (ocfs2_should_order_data(inode)) { status = ocfs2_begin_ordered_truncate(inode, @@ -1279,11 +1293,11 @@ bail: return err; } -int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) +int ocfs2_permission(struct inode *inode, int mask) { int ret; - if (flags & IPERM_FLAG_RCU) + if (mask & MAY_NOT_BLOCK) return -ECHILD; ret = ocfs2_inode_lock(inode, NULL, 0); @@ -1293,7 +1307,7 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) goto out; } - ret = generic_permission(inode, mask, flags, ocfs2_check_acl); + ret = generic_permission(inode, mask); ocfs2_inode_unlock(inode, 0); out: @@ -2236,9 +2250,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ocfs2_iocb_clear_sem_locked(iocb); relock: - /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ + /* to match setattr's i_mutex -> rw_lock ordering */ if (direct_io) { - down_read(&inode->i_alloc_sem); have_alloc_sem = 1; /* communicate with ocfs2_dio_end_io */ ocfs2_iocb_set_sem_locked(iocb); @@ -2290,7 +2303,6 @@ relock: */ if (direct_io && !can_do_direct) { ocfs2_rw_unlock(inode, rw_level); - up_read(&inode->i_alloc_sem); have_alloc_sem = 0; rw_level = -1; @@ -2361,8 +2373,7 @@ out_dio: /* * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io * function pointer which is called when o_direct io completes so that - * it can unlock our rw lock. (it's the clustered equivalent of - * i_alloc_sem; protects truncate from racing with pending ios). + * it can unlock our rw lock. * Unfortunately there are error cases which call end_io and others * that don't. so we don't have to unlock the rw_lock if either an * async dio is going to do it in the future or an end_io after an @@ -2378,10 +2389,8 @@ out: ocfs2_rw_unlock(inode, rw_level); out_sems: - if (have_alloc_sem) { - up_read(&inode->i_alloc_sem); + if (have_alloc_sem) ocfs2_iocb_clear_sem_locked(iocb); - } mutex_unlock(&inode->i_mutex); @@ -2531,7 +2540,6 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, * need locks to protect pending reads from racing with truncate. */ if (filp->f_flags & O_DIRECT) { - down_read(&inode->i_alloc_sem); have_alloc_sem = 1; ocfs2_iocb_set_sem_locked(iocb); @@ -2574,10 +2582,9 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, } bail: - if (have_alloc_sem) { - up_read(&inode->i_alloc_sem); + if (have_alloc_sem) ocfs2_iocb_clear_sem_locked(iocb); - } + if (rw_level != -1) ocfs2_rw_unlock(inode, rw_level); @@ -2593,12 +2600,14 @@ const struct inode_operations ocfs2_file_iops = { .listxattr = ocfs2_listxattr, .removexattr = generic_removexattr, .fiemap = ocfs2_fiemap, + .get_acl = ocfs2_iop_get_acl, }; const struct inode_operations ocfs2_special_file_iops = { .setattr = ocfs2_setattr, .getattr = ocfs2_getattr, .permission = ocfs2_permission, + .get_acl = ocfs2_iop_get_acl, }; /* diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index f5afbbef6703..97bf761c9e7c 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -61,7 +61,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); -int ocfs2_permission(struct inode *inode, int mask, unsigned int flags); +int ocfs2_permission(struct inode *inode, int mask); int ocfs2_should_update_atime(struct inode *inode, struct vfsmount *vfsmnt); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index e5d738cd9cc0..53aa41ed7bf3 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2498,4 +2498,5 @@ const struct inode_operations ocfs2_dir_iops = { .listxattr = ocfs2_listxattr, .removexattr = generic_removexattr, .fiemap = ocfs2_fiemap, + .get_acl = ocfs2_iop_get_acl, }; diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index ebfd3825f12a..cf7823382664 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4368,25 +4368,6 @@ static inline int ocfs2_may_create(struct inode *dir, struct dentry *child) return inode_permission(dir, MAY_WRITE | MAY_EXEC); } -/* copied from user_path_parent. */ -static int ocfs2_user_path_parent(const char __user *path, - struct nameidata *nd, char **name) -{ - char *s = getname(path); - int error; - - if (IS_ERR(s)) - return PTR_ERR(s); - - error = kern_path_parent(s, nd); - if (error) - putname(s); - else - *name = s; - - return error; -} - /** * ocfs2_vfs_reflink - Create a reference-counted link * @@ -4460,10 +4441,8 @@ int ocfs2_reflink_ioctl(struct inode *inode, bool preserve) { struct dentry *new_dentry; - struct nameidata nd; - struct path old_path; + struct path old_path, new_path; int error; - char *to = NULL; if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) return -EOPNOTSUPP; @@ -4474,39 +4453,33 @@ int ocfs2_reflink_ioctl(struct inode *inode, return error; } - error = ocfs2_user_path_parent(newname, &nd, &to); - if (error) { + new_dentry = user_path_create(AT_FDCWD, newname, &new_path, 0); + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) { mlog_errno(error); goto out; } error = -EXDEV; - if (old_path.mnt != nd.path.mnt) - goto out_release; - new_dentry = lookup_create(&nd, 0); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) { + if (old_path.mnt != new_path.mnt) { mlog_errno(error); - goto out_unlock; + goto out_dput; } - error = mnt_want_write(nd.path.mnt); + error = mnt_want_write(new_path.mnt); if (error) { mlog_errno(error); goto out_dput; } error = ocfs2_vfs_reflink(old_path.dentry, - nd.path.dentry->d_inode, + new_path.dentry->d_inode, new_dentry, preserve); - mnt_drop_write(nd.path.mnt); + mnt_drop_write(new_path.mnt); out_dput: dput(new_dentry); -out_unlock: - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); -out_release: - path_put(&nd.path); - putname(to); + mutex_unlock(&new_path.dentry->d_inode->i_mutex); + path_put(&new_path); out: path_put(&old_path); |