From: Yan, Zheng Date: Fri, 4 Mar 2016 13:13:39 +0000 (+0800) Subject: mds: allow client to request caps when opening file X-Git-Tag: v10.1.1~116^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f4bd1fc9cbfddee3f0d2e6fce4a515999d14129d;p=ceph.git mds: allow client to request caps when opening file Allow client to request xattrs while opening file. MDS adds xattrs and corresponding caps to the reply. This is important for selinux on kcephfs. Fixes: #14360 Signed-off-by: Yan, Zheng --- diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index 744c3ce8a57..2daed592d36 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -410,7 +410,7 @@ union ceph_mds_request_args { __le32 stripe_count; /* ... */ __le32 object_size; __le32 pool; /* if >= 0 and CREATEPOOLID feature */ - __le32 unused; /* used to be preferred */ + __le32 mask; /* CEPH_CAP_* */ __le64 old_size; /* if O_TRUNC */ } __attribute__ ((packed)) open; struct { diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 2083c2c91a3..b1dcb12f08f 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -2769,10 +2769,30 @@ void Server::handle_client_lookup_ino(MDRequestRef& mdr, CDentry *dn = in->get_projected_parent_dn(); CInode *diri = dn ? dn->get_dir()->inode : NULL; + + set rdlocks; if (dn && (want_parent || want_dentry)) { mdr->pin(dn); - set rdlocks, wrlocks, xlocks; rdlocks.insert(&dn->lock); + } + + unsigned mask = req->head.args.getattr.mask; + if (mask) { + Capability *cap = in->get_client_cap(mdr->get_client()); + int issued = 0; + if (cap && (mdr->snapid == CEPH_NOSNAP || mdr->snapid <= cap->client_follows)) + issued = cap->issued(); + // permission bits, ACL/security xattrs + if ((mask & CEPH_CAP_AUTH_SHARED) && (issued & CEPH_CAP_AUTH_EXCL) == 0) + rdlocks.insert(&in->authlock); + if ((mask & CEPH_CAP_XATTR_SHARED) && (issued & CEPH_CAP_XATTR_EXCL) == 0) + rdlocks.insert(&in->xattrlock); + + mdr->getattr_caps = mask; + } + + if (!rdlocks.empty()) { + set wrlocks, xlocks; if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; @@ -2909,6 +2929,21 @@ void Server::handle_client_open(MDRequestRef& mdr) return; } + unsigned mask = req->head.args.open.mask; + if (mask) { + Capability *cap = cur->get_client_cap(mdr->get_client()); + int issued = 0; + if (cap && (mdr->snapid == CEPH_NOSNAP || mdr->snapid <= cap->client_follows)) + issued = cap->issued(); + // permission bits, ACL/security xattrs + if ((mask & CEPH_CAP_AUTH_SHARED) && (issued & CEPH_CAP_AUTH_EXCL) == 0) + rdlocks.insert(&cur->authlock); + if ((mask & CEPH_CAP_XATTR_SHARED) && (issued & CEPH_CAP_XATTR_EXCL) == 0) + rdlocks.insert(&cur->xattrlock); + + mdr->getattr_caps = mask; + } + // O_TRUNC if ((flags & O_TRUNC) && !mdr->has_completed) { assert(cur->is_auth()); @@ -2945,7 +2980,7 @@ void Server::handle_client_open(MDRequestRef& mdr) if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; - int mask = MAY_READ; + mask = MAY_READ; if (cmode & CEPH_FILE_MODE_WR) mask |= MAY_WRITE; if (!check_access(mdr, cur, mask))