]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
MDS: allow the MDS to accept requests to set the btime
authorJeff Layton <jlayton@redhat.com>
Mon, 29 Aug 2016 11:16:41 +0000 (07:16 -0400)
committerJeff Layton <jlayton@redhat.com>
Mon, 29 Aug 2016 14:33:46 +0000 (10:33 -0400)
Unfortunately, the only option here is to rev the MClientRequest
version as the ceph_mds_request_head is not currently versioned. Add a
new ceph_mds_request_head, which contains a new ceph_mds_request_args
structure.

The new ceph_mds_request_head is now versioned via a __le16
at the beginning of it, and then the args structure is expanded to hold
the btime. When we get a legacy ceph_mds_request_head, we just set the
new fields to zero. When encoding a reply to a legacy client, we simply
don't encode the version in the head, or the btime in the setattr union
member.

Reluctantly-Signed-off-by: Jeff Layton <jlayton@redhat.com>
src/client/Client.cc
src/client/MetaRequest.h
src/include/ceph_fs.h
src/include/types.h
src/mds/Server.cc
src/messages/MClientRequest.h

index 433f1b0168a97f00e71f80e9858f388f1724a9b5..ddf38f9beff1a89cb8d690ed8c5005041d138b8c 100644 (file)
@@ -2146,7 +2146,7 @@ MClientRequest* Client::build_client_request(MetaRequest *request)
   MClientRequest *req = new MClientRequest(request->get_op());
   req->set_tid(request->tid);
   req->set_stamp(request->op_stamp);
-  memcpy(&req->head, &request->head, sizeof(ceph_mds_request_head_legacy));
+  memcpy(&req->head, &request->head, sizeof(ceph_mds_request_head));
 
   // if the filepath's haven't been set, set them!
   if (request->path.empty()) {
index 2640c5afc8c36a4bfaa462b82485e67095b63c82..8eb02048da0b2626d0b3a89d4548694568fb2d3e 100644 (file)
@@ -86,7 +86,7 @@ public:
     got_unsafe(false), item(this), unsafe_item(this),
     unsafe_dir_item(this), unsafe_target_item(this),
     caller_cond(0), dispatch_cond(0) {
-    memset(&head, 0, sizeof(ceph_mds_request_head_legacy));
+    memset(&head, 0, sizeof(head));
     head.op = op;
   }
   ~MetaRequest();
index b4f2ae6e4146ca023dd18e1c4a7bc3b1332efd34..73701a6ba6d9de610b937fa22ed2df4b71740055 100644 (file)
@@ -376,6 +376,7 @@ extern const char *ceph_mds_op_name(int op);
 #define CEPH_SETATTR_ATIME     (1 << 4)
 #define CEPH_SETATTR_SIZE      (1 << 5)
 #define CEPH_SETATTR_CTIME     (1 << 6)
+#define CEPH_SETATTR_BTIME     (1 << 9)
 #endif
 #define CEPH_SETATTR_MTIME_NOW (1 << 7)
 #define CEPH_SETATTR_ATIME_NOW (1 << 8)
@@ -399,6 +400,7 @@ extern const char *ceph_mds_op_name(int op);
 #define CEPH_READDIR_FRAG_COMPLETE     (1<<8)
 #define CEPH_READDIR_HASH_ORDER                (1<<9)
 
+/* Note that this is embedded wthin ceph_mds_request_head_legacy. */
 union ceph_mds_request_args_legacy {
        struct {
                __le32 mask;                 /* CEPH_CAP_* */
@@ -469,6 +471,85 @@ struct ceph_mds_request_head_legacy {
        union ceph_mds_request_args_legacy args;
 } __attribute__ ((packed));
 
+/*
+ * Note that this is embedded wthin ceph_mds_request_head. Also, compatability
+ * with the ceph_mds_request_args_legacy must be maintained!
+ */
+union ceph_mds_request_args {
+       struct {
+               __le32 mask;                 /* CEPH_CAP_* */
+       } __attribute__ ((packed)) getattr;
+       struct {
+               __le32 mode;
+               __le32 uid;
+               __le32 gid;
+               struct ceph_timespec mtime;
+               struct ceph_timespec atime;
+               __le64 size, old_size;       /* old_size needed by truncate */
+               __le32 mask;                 /* CEPH_SETATTR_* */
+               struct ceph_timespec btime;
+       } __attribute__ ((packed)) setattr;
+       struct {
+               __le32 frag;                 /* which dir fragment */
+               __le32 max_entries;          /* how many dentries to grab */
+               __le32 max_bytes;
+               __le16 flags;
+       } __attribute__ ((packed)) readdir;
+       struct {
+               __le32 mode;
+               __le32 rdev;
+       } __attribute__ ((packed)) mknod;
+       struct {
+               __le32 mode;
+       } __attribute__ ((packed)) mkdir;
+       struct {
+               __le32 flags;
+               __le32 mode;
+               __le32 stripe_unit;          /* layout for newly created file */
+               __le32 stripe_count;         /* ... */
+               __le32 object_size;
+               __le32 pool;                 /* if >= 0 and CREATEPOOLID feature */
+               __le32 mask;                 /* CEPH_CAP_* */
+               __le64 old_size;             /* if O_TRUNC */
+       } __attribute__ ((packed)) open;
+       struct {
+               __le32 flags;
+               __le32 osdmap_epoch;        /* use for set file/dir layout */
+       } __attribute__ ((packed)) setxattr;
+       struct {
+               struct ceph_file_layout layout;
+       } __attribute__ ((packed)) setlayout;
+       struct {
+               __u8 rule; /* currently fcntl or flock */
+               __u8 type; /* shared, exclusive, remove*/
+               __le64 owner; /* who requests/holds the lock */
+               __le64 pid; /* process id requesting the lock */
+               __le64 start; /* initial location to lock */
+               __le64 length; /* num bytes to lock from start */
+               __u8 wait; /* will caller wait for lock to become available? */
+       } __attribute__ ((packed)) filelock_change;
+} __attribute__ ((packed));
+
+#define CEPH_MDS_REQUEST_HEAD_VERSION  1
+
+/*
+ * Note that any change to this structure must ensure that it is compatible
+ * with ceph_mds_request_head_legacy.
+ */
+struct ceph_mds_request_head {
+       __le16 version;
+       __le64 oldest_client_tid;
+       __le32 mdsmap_epoch;           /* on client */
+       __le32 flags;                  /* CEPH_MDS_FLAG_* */
+       __u8 num_retry, num_fwd;       /* count retry, fwd attempts */
+       __le16 num_releases;           /* # include cap/lease release records */
+       __le32 op;                     /* mds op code */
+       __le32 caller_uid, caller_gid;
+       __le64 ino;                    /* use this ino for openc, mkdir, mknod,
+                                         etc. (if replaying) */
+       union ceph_mds_request_args args;
+} __attribute__ ((packed));
+
 /* cap/lease release record */
 struct ceph_mds_request_release {
        __le64 ino, cap_id;            /* ino and unique cap id */
index 545006c61aef560ec1618798efce4050e36c4ef0..3593f5af292b088a26d4ca2f0a3626d64300613e 100644 (file)
@@ -245,6 +245,7 @@ WRITE_RAW_ENCODER(ceph_file_layout)
 WRITE_RAW_ENCODER(ceph_dir_layout)
 WRITE_RAW_ENCODER(ceph_mds_session_head)
 WRITE_RAW_ENCODER(ceph_mds_request_head_legacy)
+WRITE_RAW_ENCODER(ceph_mds_request_head)
 WRITE_RAW_ENCODER(ceph_mds_request_release)
 WRITE_RAW_ENCODER(ceph_filelock)
 WRITE_RAW_ENCODER(ceph_mds_caps_head)
index 3ad1654b52493a9d58a5a6c6aa32e5228aae5a35..9a6bc92c05d63b41ab90351e5e294e8f7c8fb534 100644 (file)
@@ -3746,7 +3746,7 @@ void Server::handle_client_setattr(MDRequestRef& mdr)
   __u32 access_mask = MAY_WRITE;
 
   // xlock inode
-  if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID))
+  if (mask & (CEPH_SETATTR_MODE|CEPH_SETATTR_UID|CEPH_SETATTR_GID|CEPH_SETATTR_BTIME))
     xlocks.insert(&cur->authlock);
   if (mask & (CEPH_SETATTR_MTIME|CEPH_SETATTR_ATIME|CEPH_SETATTR_SIZE))
     xlocks.insert(&cur->filelock);
@@ -3811,7 +3811,9 @@ void Server::handle_client_setattr(MDRequestRef& mdr)
     pi->mtime = req->head.args.setattr.mtime;
   if (mask & CEPH_SETATTR_ATIME)
     pi->atime = req->head.args.setattr.atime;
-  if (mask & (CEPH_SETATTR_ATIME | CEPH_SETATTR_MTIME))
+  if (mask & CEPH_SETATTR_BTIME)
+    pi->btime = req->head.args.setattr.btime;
+  if (mask & (CEPH_SETATTR_ATIME | CEPH_SETATTR_MTIME | CEPH_SETATTR_BTIME))
     pi->time_warp_seq++;   // maybe not a timewarp, but still a serialization point.
   if (mask & CEPH_SETATTR_SIZE) {
     if (truncating_smaller) {
index 6d0c27ec6c1677ee18689e36c5f602293b838ace..26f69f7f3ec7246b70776485a96e2a125450f115 100644 (file)
@@ -36,6 +36,7 @@
 #include "msg/Message.h"
 #include "include/filepath.h"
 #include "mds/mdstypes.h"
+#include "include/ceph_features.h"
 
 #include <sys/types.h>
 #include <utime.h>
 // metadata ops.
 
 class MClientRequest : public Message {
-  static const int HEAD_VERSION = 3;
+  static const int HEAD_VERSION = 4;
   static const int COMPAT_VERSION = 1;
 
 public:
-  struct ceph_mds_request_head_legacy head;
+  struct ceph_mds_request_head head;
   utime_t stamp;
 
   struct Release {
@@ -160,7 +161,28 @@ public:
 
   void decode_payload() {
     bufferlist::iterator p = payload.begin();
-    ::decode(head, p);
+
+    if (header.version >= 4) {
+      ::decode(head, p);
+    } else {
+      struct ceph_mds_request_head_legacy *old_mds_head =
+       (struct ceph_mds_request_head_legacy *)&(head.oldest_client_tid);
+
+      ::decode(*old_mds_head, p);
+
+      head.version = 0;
+
+      /* Can't set the btime from legacy struct */
+      if (head.op == CEPH_MDS_OP_SETATTR) {
+       int localmask = head.args.setattr.mask;
+
+       localmask &= ~CEPH_SETATTR_BTIME;
+
+       head.args.setattr.btime = { 0 };
+       head.args.setattr.mask = localmask;
+      }
+    }
+
     ::decode(path, p);
     ::decode(path2, p);
     ::decode_nohead(head.num_releases, releases, p);
@@ -170,7 +192,17 @@ public:
 
   void encode_payload(uint64_t features) {
     head.num_releases = releases.size();
-    ::encode(head, payload);
+    head.version = CEPH_MDS_REQUEST_HEAD_VERSION;
+
+    if (features & CEPH_FEATURE_FS_BTIME) {
+      ::encode(head, payload);
+    } else {
+      struct ceph_mds_request_head_legacy *old_mds_head =
+       (struct ceph_mds_request_head_legacy *)&(head.oldest_client_tid);
+
+      ::encode(*old_mds_head, payload);
+    }
+
     ::encode(path, payload);
     ::encode(path2, payload);
     ::encode_nohead(releases, payload);