ceph: Check for created flag in response from mds
authorSam Lang <sam.lang@inktank.com>
Fri, 28 Dec 2012 17:56:46 +0000 (09:56 -0800)
committerAlex Elder <elder@inktank.com>
Thu, 17 Jan 2013 18:42:36 +0000 (12:42 -0600)
The mds now sends back a created inode if the create request
performed the create.  If the file already existed, no inode is
returned in the reply.  This allows ceph to set the created flag
in atomic_open so that permissions are properly checked in the case
that the file wasn't created by the create call to the mds.

To ensure compability with previous kernels, a feature for sending
back the inode in the create reply was added, so that the mds will
only send back the inode if the client indicates it supports the
feature.

Signed-off-by: Sam Lang <sam.lang@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
fs/ceph/file.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
include/linux/ceph/ceph_features.h

index 2c71cbd78332880e866b72dfd1bc9ff6f40e161a..22b5b71b54018267c1c5b4ea6c30e42092d301fa 100644 (file)
@@ -266,6 +266,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
                err = finish_no_open(file, dn);
        } else {
                dout("atomic_open finish_open on dn %p\n", dn);
+               if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
+                       *opened |= FILE_CREATED;
+               }
                err = finish_open(file, dentry, ceph_open, opened);
        }
 
index 9165eb8309eba442efa237aaa313a43c92641607..d95842036c8b11b570f0c5a998087527d3b351e3 100644 (file)
@@ -232,6 +232,30 @@ bad:
        return -EIO;
 }
 
+/*
+ * parse create results
+ */
+static int parse_reply_info_create(void **p, void *end,
+                                 struct ceph_mds_reply_info_parsed *info,
+                                 int features)
+{
+       if (features & CEPH_FEATURE_REPLY_CREATE_INODE) {
+               if (*p == end) {
+                       info->has_create_ino = false;
+               } else {
+                       info->has_create_ino = true;
+                       info->ino = ceph_decode_64(p);
+               }
+       }
+
+       if (unlikely(*p != end))
+               goto bad;
+       return 0;
+
+bad:
+       return -EIO;
+}
+
 /*
  * parse extra results
  */
@@ -241,8 +265,12 @@ static int parse_reply_info_extra(void **p, void *end,
 {
        if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
                return parse_reply_info_filelock(p, end, info, features);
-       else
+       else if (info->head->op == CEPH_MDS_OP_READDIR)
                return parse_reply_info_dir(p, end, info, features);
+       else if (info->head->op == CEPH_MDS_OP_CREATE)
+               return parse_reply_info_create(p, end, info, features);
+       else
+               return -EIO;
 }
 
 /*
@@ -2170,7 +2198,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        mutex_lock(&req->r_fill_mutex);
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
-               if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
+               if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR ||
+                                   req->r_op == CEPH_MDS_OP_LSSNAP) &&
                    rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
index dd26846dd71de4267146b7deb43c7a5d7b9b976f..567f7c60354e916fe5b34679d53313a361c2b08d 100644 (file)
@@ -74,6 +74,12 @@ struct ceph_mds_reply_info_parsed {
                        struct ceph_mds_reply_info_in *dir_in;
                        u8                            dir_complete, dir_end;
                };
+
+               /* for create results */
+               struct {
+                       bool has_create_ino;
+                       u64 ino;
+               };
        };
 
        /* encoded blob describing snapshot contexts for certain
index dad579b0c0e65981ea42c7a820f71e0480154b17..6b7c6acbb3bf46119076bd95356c3621c26adb70 100644 (file)
 #define CEPH_FEATURE_DIRLAYOUTHASH  (1<<7)
 /* bits 8-17 defined by user-space; not supported yet here */
 #define CEPH_FEATURE_CRUSH_TUNABLES (1<<18)
+/* bits 19-25 defined by user-space; not supported yet here */
+#define CEPH_FEATURE_REPLY_CREATE_INODE (1<<27)
 
 /*
  * Features supported.
  */
 #define CEPH_FEATURES_SUPPORTED_DEFAULT  \
        (CEPH_FEATURE_NOSRCADDR |        \
-        CEPH_FEATURE_CRUSH_TUNABLES)
+        CEPH_FEATURE_CRUSH_TUNABLES |   \
+        CEPH_FEATURE_REPLY_CREATE_INODE)
 
 #define CEPH_FEATURES_REQUIRED_DEFAULT   \
        (CEPH_FEATURE_NOSRCADDR)