X-Git-Url: https://git.proxmox.com/?p=ceph.git;a=blobdiff_plain;f=ceph%2Fsrc%2Finclude%2Fceph_fs.h;fp=ceph%2Fsrc%2Finclude%2Fceph_fs.h;h=28440c820dcfb8f17d0a04fcc301401025ec80fd;hp=1a75a519333600ea78218f85850e90252b690045;hb=aee94f6923ba628a85d855d0c5316d0da78bfa2a;hpb=27f45121cc74e31203777ad565f78d8aad9b92a2 diff --git a/ceph/src/include/ceph_fs.h b/ceph/src/include/ceph_fs.h index 1a75a5193..28440c820 100644 --- a/ceph/src/include/ceph_fs.h +++ b/ceph/src/include/ceph_fs.h @@ -418,6 +418,7 @@ enum { CEPH_MDS_OP_RMSNAP = 0x01401, CEPH_MDS_OP_LSSNAP = 0x00402, CEPH_MDS_OP_RENAMESNAP = 0x01403, + CEPH_MDS_OP_READDIR_SNAPDIFF = 0x01404, // internal op CEPH_MDS_OP_FRAGMENTDIR= 0x01500, @@ -429,6 +430,11 @@ enum { CEPH_MDS_OP_RDLOCK_FRAGSSTATS = 0x01507 }; +#define IS_CEPH_MDS_OP_NEWINODE(op) (op == CEPH_MDS_OP_CREATE || \ + op == CEPH_MDS_OP_MKNOD || \ + op == CEPH_MDS_OP_MKDIR || \ + op == CEPH_MDS_OP_SYMLINK) + extern const char *ceph_mds_op_name(int op); // setattr mask is an int @@ -473,12 +479,12 @@ int ceph_flags_sys2wire(int flags); #define CEPH_XATTR_REMOVE (1 << 31) /* - * readdir request flags; + * readdir/readdir_snapdiff request flags; */ #define CEPH_READDIR_REPLY_BITFLAGS (1<<0) /* - * readdir reply flags. + * readdir/readdir_snapdiff reply flags. */ #define CEPH_READDIR_FRAG_END (1<<0) #define CEPH_READDIR_FRAG_COMPLETE (1<<8) @@ -622,9 +628,17 @@ union ceph_mds_request_args { __le64 parent; __le32 hash; } __attribute__ ((packed)) lookupino; + struct { + __le32 frag; /* which dir fragment */ + __le32 max_entries; /* how many dentries to grab */ + __le32 max_bytes; + __le16 flags; + __le32 offset_hash; + __le64 snap_other; + } __attribute__ ((packed)) snapdiff; } __attribute__ ((packed)); -#define CEPH_MDS_REQUEST_HEAD_VERSION 2 +#define CEPH_MDS_REQUEST_HEAD_VERSION 3 /* * Note that any change to this structure must ensure that it is compatible @@ -645,9 +659,12 @@ struct ceph_mds_request_head { __le32 ext_num_retry; /* new count retry attempts */ __le32 ext_num_fwd; /* new count fwd attempts */ + + __le32 struct_len; /* to store size of struct ceph_mds_request_head */ + __le32 owner_uid, owner_gid; /* used for OPs which create inodes */ } __attribute__ ((packed)); -void inline encode(const struct ceph_mds_request_head& h, ceph::buffer::list& bl, bool old_version) { +void inline encode(const struct ceph_mds_request_head& h, ceph::buffer::list& bl) { using ceph::encode; encode(h.version, bl); encode(h.oldest_client_tid, bl); @@ -667,14 +684,30 @@ void inline encode(const struct ceph_mds_request_head& h, ceph::buffer::list& bl encode(h.ino, bl); bl.append((char*)&h.args, sizeof(h.args)); - if (!old_version) { + if (h.version >= 2) { encode(h.ext_num_retry, bl); encode(h.ext_num_fwd, bl); } + + if (h.version >= 3) { + __u32 struct_len = sizeof(struct ceph_mds_request_head); + encode(struct_len, bl); + encode(h.owner_uid, bl); + encode(h.owner_gid, bl); + + /* + * Please, add new fields handling here. + * You don't need to check h.version as we do it + * in decode(), because decode can properly skip + * all unsupported fields if h.version >= 3. + */ + } } void inline decode(struct ceph_mds_request_head& h, ceph::buffer::list::const_iterator& bl) { using ceph::decode; + unsigned struct_end = bl.get_off(); + decode(h.version, bl); decode(h.oldest_client_tid, bl); decode(h.mdsmap_epoch, bl); @@ -695,6 +728,42 @@ void inline decode(struct ceph_mds_request_head& h, ceph::buffer::list::const_it h.ext_num_retry = h.num_retry; h.ext_num_fwd = h.num_fwd; } + + if (h.version >= 3) { + decode(h.struct_len, bl); + struct_end += h.struct_len; + + decode(h.owner_uid, bl); + decode(h.owner_gid, bl); + } else { + /* + * client is old: let's take caller_{u,g}id as owner_{u,g}id + * this is how it worked before adding of owner_{u,g}id fields. + */ + h.owner_uid = h.caller_uid; + h.owner_gid = h.caller_gid; + } + + /* add new fields handling here */ + + /* + * From version 3 we have struct_len field. + * It allows us to properly handle a case + * when client send struct ceph_mds_request_head + * bigger in size than MDS supports. In this + * case we just want to skip all remaining bytes + * at the end. + * + * See also DECODE_FINISH macro. Unfortunately, + * we can't start using it right now as it will be + * an incompatible protocol change. + */ + if (h.version >= 3) { + if (bl.get_off() > struct_end) + throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); + if (bl.get_off() < struct_end) + bl += struct_end - bl.get_off(); + } } /* cap/lease release record */