summaryrefslogtreecommitdiff
path: root/fs/ceph/dir.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-09-16 20:35:17 +0800
committerSage Weil <sage@redhat.com>2014-10-14 12:56:49 -0700
commitb1ee94aa593abd03634bc3887b8e189840e42c12 (patch)
tree59f8d66fcc03a21a2f5364cd1b1d418705e45bdc /fs/ceph/dir.c
parent25e6bae356502cde283f1804111b44e6fad20fc2 (diff)
ceph: include the initial ACL in create/mkdir/mknod MDS requests
Current code set new file/directory's initial ACL in a non-atomic manner. Client first sends request to MDS to create new file/directory, then set the initial ACL after the new file/directory is successfully created. The fix is include the initial ACL in create/mkdir/mknod MDS requests. So MDS can handle creating file/directory and setting the initial ACL in one request. Signed-off-by: Yan, Zheng <zyan@redhat.com> Reviewed-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r--fs/ceph/dir.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index c29d6ae68874..26be84929439 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -682,17 +682,22 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
+ struct ceph_acls_info acls = {};
int err;
if (ceph_snap(dir) != CEPH_NOSNAP)
return -EROFS;
+ err = ceph_pre_init_acls(dir, &mode, &acls);
+ if (err < 0)
+ return err;
+
dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n",
dir, dentry, mode, rdev);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS);
if (IS_ERR(req)) {
- d_drop(dentry);
- return PTR_ERR(req);
+ err = PTR_ERR(req);
+ goto out;
}
req->r_dentry = dget(dentry);
req->r_num_caps = 2;
@@ -701,15 +706,20 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
req->r_args.mknod.rdev = cpu_to_le32(rdev);
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
+ if (acls.pagelist) {
+ req->r_pagelist = acls.pagelist;
+ acls.pagelist = NULL;
+ }
err = ceph_mdsc_do_request(mdsc, dir, req);
if (!err && !req->r_reply_info.head->is_dentry)
err = ceph_handle_notrace_create(dir, dentry);
ceph_mdsc_put_request(req);
-
+out:
if (!err)
- ceph_init_acl(dentry, dentry->d_inode, dir);
+ ceph_init_inode_acls(dentry->d_inode, &acls);
else
d_drop(dentry);
+ ceph_release_acls_info(&acls);
return err;
}
@@ -733,8 +743,8 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS);
if (IS_ERR(req)) {
- d_drop(dentry);
- return PTR_ERR(req);
+ err = PTR_ERR(req);
+ goto out;
}
req->r_dentry = dget(dentry);
req->r_num_caps = 2;
@@ -746,9 +756,8 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
if (!err && !req->r_reply_info.head->is_dentry)
err = ceph_handle_notrace_create(dir, dentry);
ceph_mdsc_put_request(req);
- if (!err)
- ceph_init_acl(dentry, dentry->d_inode, dir);
- else
+out:
+ if (err)
d_drop(dentry);
return err;
}
@@ -758,6 +767,7 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
+ struct ceph_acls_info acls = {};
int err = -EROFS;
int op;
@@ -772,6 +782,12 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
} else {
goto out;
}
+
+ mode |= S_IFDIR;
+ err = ceph_pre_init_acls(dir, &mode, &acls);
+ if (err < 0)
+ goto out;
+
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
if (IS_ERR(req)) {
err = PTR_ERR(req);
@@ -784,15 +800,20 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
req->r_args.mkdir.mode = cpu_to_le32(mode);
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
+ if (acls.pagelist) {
+ req->r_pagelist = acls.pagelist;
+ acls.pagelist = NULL;
+ }
err = ceph_mdsc_do_request(mdsc, dir, req);
if (!err && !req->r_reply_info.head->is_dentry)
err = ceph_handle_notrace_create(dir, dentry);
ceph_mdsc_put_request(req);
out:
if (!err)
- ceph_init_acl(dentry, dentry->d_inode, dir);
+ ceph_init_inode_acls(dentry->d_inode, &acls);
else
d_drop(dentry);
+ ceph_release_acls_info(&acls);
return err;
}