]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: allow client to request caps when opening file
authorYan, Zheng <zyan@redhat.com>
Fri, 4 Mar 2016 13:13:39 +0000 (21:13 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 7 Mar 2016 01:06:41 +0000 (09:06 +0800)
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 <zyan@redhat.com>
src/include/ceph_fs.h
src/mds/Server.cc

index 744c3ce8a573068598031d53892146525c61a026..2daed592d36bbf34feb1cb1b623c549e29e35bfb 100644 (file)
@@ -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 {
index 2083c2c91a3da256b0d951aa492baa5ab1afb2e2..b1dcb12f08f44b7fff27c4d9833c355d280df1b1 100644 (file)
@@ -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<SimpleLock*> rdlocks;
   if (dn && (want_parent || want_dentry)) {
     mdr->pin(dn);
-    set<SimpleLock*> 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<SimpleLock*> 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))