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()) {
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();
#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)
#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_* */
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 */
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)
__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);
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) {
#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 {
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);
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);