Whamcloud - gitweb
LU-5707 lfsck: store namespace LFSCK statistics info in new EA
[fs/lustre-release.git] / lustre / include / lustre / lustre_idl.h
index 6842e16..26da4c3 100644 (file)
 #ifndef _LUSTRE_IDL_H_
 #define _LUSTRE_IDL_H_
 
-#if !defined(LPU64)
 #include <libcfs/libcfs.h> /* for LPUX64, etc */
-#endif
-
-/* Defn's shared with user-space. */
-#include <lustre/lustre_user.h>
-
+#include <lnet/types.h>
+#include <lustre/lustre_user.h> /* Defn's shared with user-space. */
 #include <lustre/lustre_errno.h>
 #include <lustre_ver.h>
 
 #define LUSTRE_LOG_VERSION  0x00050000
 #define LUSTRE_MGS_VERSION  0x00060000
 
-typedef __u32 mdsno_t;
-typedef __u64 seqno_t;
 typedef __u64 obd_id;
 typedef __u64 obd_seq;
 typedef __s64 obd_time;
@@ -342,8 +336,9 @@ enum lma_incompat {
        LMAI_AGENT              = 0x00000002, /* agent inode */
        LMAI_REMOTE_PARENT      = 0x00000004, /* the parent of the object
                                                 is on the remote MDT */
+       LMAI_STRIPED            = 0x00000008, /* striped directory inode */
 };
-#define LMA_INCOMPAT_SUPP      (LMAI_AGENT | LMAI_REMOTE_PARENT)
+#define LMA_INCOMPAT_SUPP      (LMAI_AGENT | LMAI_REMOTE_PARENT | LMAI_STRIPED)
 
 extern void lustre_lma_swab(struct lustre_mdt_attrs *lma);
 extern void lustre_lma_init(struct lustre_mdt_attrs *lma,
@@ -784,9 +779,9 @@ static inline int ostid_to_fid(struct lu_fid *fid, const struct ost_id *ostid,
                 * been in production for years.  This can handle create rates
                 * of 1M objects/s/OST for 9 years, or combinations thereof. */
                if (oid >= IDIF_MAX_OID) {
-                        CERROR("bad MDT0 id, "DOSTID" ost_idx:%u\n",
-                               POSTID(ostid), ost_idx);
-                        return -EBADF;
+                       CERROR("bad MDT0 id(1), "DOSTID" ost_idx:%u\n",
+                              POSTID(ostid), ost_idx);
+                       return -EBADF;
                }
                fid->f_seq = fid_idif_seq(oid, ost_idx);
                /* truncate to 32 bits by assignment */
@@ -800,7 +795,7 @@ static inline int ostid_to_fid(struct lu_fid *fid, const struct ost_id *ostid,
                 * OST objects into the FID namespace.  In both cases, we just
                 * pass the FID through, no conversion needed. */
                if (ostid->oi_fid.f_ver != 0) {
-                       CERROR("bad MDT0 id, "DOSTID" ost_idx:%u\n",
+                       CERROR("bad MDT0 id(2), "DOSTID" ost_idx:%u\n",
                                POSTID(ostid), ost_idx);
                        return -EBADF;
                }
@@ -935,7 +930,7 @@ static inline int lu_fid_cmp(const struct lu_fid *f0,
 static inline void ostid_cpu_to_le(const struct ost_id *src_oi,
                                   struct ost_id *dst_oi)
 {
-       if (fid_seq_is_mdt0(ostid_seq(src_oi))) {
+       if (fid_seq_is_mdt0(src_oi->oi.oi_seq)) {
                dst_oi->oi.oi_id = cpu_to_le64(src_oi->oi.oi_id);
                dst_oi->oi.oi_seq = cpu_to_le64(src_oi->oi.oi_seq);
        } else {
@@ -946,7 +941,7 @@ static inline void ostid_cpu_to_le(const struct ost_id *src_oi,
 static inline void ostid_le_to_cpu(const struct ost_id *src_oi,
                                   struct ost_id *dst_oi)
 {
-       if (fid_seq_is_mdt0(ostid_seq(src_oi))) {
+       if (fid_seq_is_mdt0(src_oi->oi.oi_seq)) {
                dst_oi->oi.oi_id = le64_to_cpu(src_oi->oi.oi_id);
                dst_oi->oi.oi_seq = le64_to_cpu(src_oi->oi.oi_seq);
        } else {
@@ -1091,12 +1086,12 @@ static inline struct lu_dirent *lu_dirent_next(struct lu_dirent *ent)
         return next;
 }
 
-static inline int lu_dirent_calc_size(int namelen, __u16 attr)
+static inline size_t lu_dirent_calc_size(size_t namelen, __u16 attr)
 {
-        int size;
+       size_t size;
 
-        if (attr & LUDA_TYPE) {
-                const unsigned align = sizeof(struct luda_type) - 1;
+       if (attr & LUDA_TYPE) {
+               const size_t align = sizeof(struct luda_type) - 1;
                 size = (sizeof(struct lu_dirent) + namelen + align) & ~align;
                 size += sizeof(struct luda_type);
         } else
@@ -1105,15 +1100,6 @@ static inline int lu_dirent_calc_size(int namelen, __u16 attr)
         return (size + 7) & ~7;
 }
 
-static inline int lu_dirent_size(const struct lu_dirent *ent)
-{
-        if (le16_to_cpu(ent->lde_reclen) == 0) {
-                return lu_dirent_calc_size(le16_to_cpu(ent->lde_namelen),
-                                           le32_to_cpu(ent->lde_attrs));
-        }
-        return le16_to_cpu(ent->lde_reclen);
-}
-
 #define MDS_DIR_END_OFF 0xfffffffffffffffeULL
 
 /**
@@ -1176,7 +1162,6 @@ struct lustre_msg_v2 {
 
 /* without gss, ptlrpc_body is put at the first buffer. */
 #define PTLRPC_NUM_VERSIONS     4
-#define JOBSTATS_JOBID_SIZE     32  /* 32 bytes string */
 struct ptlrpc_body_v3 {
        struct lustre_handle pb_handle;
        __u32 pb_type;
@@ -1198,7 +1183,7 @@ struct ptlrpc_body_v3 {
        __u64 pb_pre_versions[PTLRPC_NUM_VERSIONS];
        /* padding for future needs */
        __u64 pb_padding[4];
-       char  pb_jobid[JOBSTATS_JOBID_SIZE];
+       char  pb_jobid[LUSTRE_JOBID_SIZE];
 };
 #define ptlrpc_body     ptlrpc_body_v3
 
@@ -1348,6 +1333,8 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 #define OBD_CONNECT_OPEN_BY_FID        0x20000000000000ULL /* open by fid won't pack
                                                       name in request */
 #define OBD_CONNECT_LFSCK      0x40000000000000ULL/* support online LFSCK */
+#define OBD_CONNECT_UNLINK_CLOSE 0x100000000000000ULL/* close file in unlink */
+#define OBD_CONNECT_DIR_STRIPE  0x400000000000000ULL /* striped DNE dir */
 
 /* XXX README XXX:
  * Please DO NOT add flag values here before first ensuring that this same
@@ -1392,7 +1379,9 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
                                OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
                                OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
                                OBD_CONNECT_FLOCK_DEAD | \
-                               OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK)
+                               OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | \
+                               OBD_CONNECT_OPEN_BY_FID | \
+                               OBD_CONNECT_DIR_STRIPE)
 
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
                                 OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
@@ -1581,6 +1570,8 @@ enum obdo_flags {
 #define LOV_MAGIC_JOIN_V1      (0x0BD20000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC_V3           (0x0BD30000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC_MIGRATE      (0x0BD40000 | LOV_MAGIC_MAGIC)
+/* reserved for specifying OSTs */
+#define LOV_MAGIC_SPECIFIC     (0x0BD50000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC              LOV_MAGIC_V1
 
 /*
@@ -1701,7 +1692,6 @@ static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi,
 #define XATTR_USER_PREFIX       "user."
 #define XATTR_TRUSTED_PREFIX    "trusted."
 #define XATTR_SECURITY_PREFIX   "security."
-#define XATTR_LUSTRE_PREFIX     "lustre."
 
 #define XATTR_NAME_LOV          "trusted.lov"
 #define XATTR_NAME_LMA          "trusted.lma"
@@ -1712,7 +1702,13 @@ static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi,
 #define XATTR_NAME_VERSION      "trusted.version"
 #define XATTR_NAME_SOM         "trusted.som"
 #define XATTR_NAME_HSM         "trusted.hsm"
-#define XATTR_NAME_LFSCK_NAMESPACE "trusted.lfsck_namespace"
+#define XATTR_NAME_LFSCK_BITMAP "trusted.lfsck_bitmap"
+
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 8, 53, 0)
+# define XATTR_NAME_LFSCK_NAMESPACE_OLD "trusted.lfsck_namespace"
+#endif
+
+#define XATTR_NAME_LFSCK_NAMESPACE "trusted.lfsck_ns"
 #define XATTR_NAME_MAX_LEN     32 /* increase this, if there is longer name. */
 
 struct lov_mds_md_v3 {            /* LOV EA mds/wire data (little-endian) */
@@ -1723,7 +1719,7 @@ struct lov_mds_md_v3 {            /* LOV EA mds/wire data (little-endian) */
        /* lmm_stripe_count used to be __u32 */
        __u16 lmm_stripe_count;   /* num stripes in use for this object */
        __u16 lmm_layout_gen;     /* layout generation number */
-       char  lmm_pool_name[LOV_MAXPOOLNAME]; /* must be 32bit aligned */
+       char  lmm_pool_name[LOV_MAXPOOLNAME + 1]; /* must be 32bit aligned */
        struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */
 };
 
@@ -1900,12 +1896,12 @@ extern void lustre_swab_obd_ioobj (struct obd_ioobj *ioo);
 
 /* multiple of 8 bytes => can array */
 struct niobuf_remote {
-        __u64 offset;
-        __u32 len;
-        __u32 flags;
+       __u64   rnb_offset;
+       __u32   rnb_len;
+       __u32   rnb_flags;
 };
 
-extern void lustre_swab_niobuf_remote (struct niobuf_remote *nbr);
+void lustre_swab_niobuf_remote(struct niobuf_remote *nbr);
 
 /* lock value block communicated between the filter and llite */
 
@@ -2131,8 +2127,8 @@ typedef enum {
        MDS_DISCONNECT          = 39,
        MDS_GETSTATUS           = 40,
        MDS_STATFS              = 41,
-       MDS_PIN                 = 42,
-       MDS_UNPIN               = 43,
+       MDS_PIN                 = 42, /* obsolete, never used in a release */
+       MDS_UNPIN               = 43, /* obsolete, never used in a release */
        MDS_SYNC                = 44,
        MDS_DONE_WRITING        = 45,
        MDS_SET_INFO            = 46,
@@ -2141,7 +2137,7 @@ typedef enum {
        MDS_GETXATTR            = 49,
        MDS_SETXATTR            = 50, /* obsolete, now it's MDS_REINT op */
        MDS_WRITEPAGE           = 51,
-       MDS_IS_SUBDIR           = 52,
+       MDS_IS_SUBDIR           = 52, /* obsolete, never used in a release */
        MDS_GET_INFO            = 53,
        MDS_HSM_STATE_GET       = 54,
        MDS_HSM_STATE_SET       = 55,
@@ -2305,42 +2301,42 @@ enum md_transient_state {
 };
 
 struct mdt_body {
-        struct lu_fid  fid1;
-        struct lu_fid  fid2;
-        struct lustre_handle handle;
-        __u64          valid;
-        __u64          size;   /* Offset, in the case of MDS_READPAGE */
-       obd_time        mtime;
-       obd_time        atime;
-       obd_time        ctime;
-        __u64          blocks; /* XID, in the case of MDS_READPAGE */
-        __u64          ioepoch;
-       __u64          t_state; /* transient file state defined in
-                                * enum md_transient_state
-                                * was "ino" until 2.4.0 */
-        __u32          fsuid;
-        __u32          fsgid;
-        __u32          capability;
-        __u32          mode;
-        __u32          uid;
-        __u32          gid;
-        __u32          flags; /* from vfs for pin/unpin, LUSTRE_BFLAG close */
-        __u32          rdev;
-        __u32          nlink; /* #bytes to read in the case of MDS_READPAGE */
-       __u32          unused2; /* was "generation" until 2.4.0 */
-        __u32          suppgid;
-        __u32          eadatasize;
-        __u32          aclsize;
-        __u32          max_mdsize;
-        __u32          max_cookiesize;
-        __u32          uid_h; /* high 32-bits of uid, for FUID */
-        __u32          gid_h; /* high 32-bits of gid, for FUID */
-        __u32          padding_5; /* also fix lustre_swab_mdt_body */
-        __u64          padding_6;
-        __u64          padding_7;
-        __u64          padding_8;
-        __u64          padding_9;
-        __u64          padding_10;
+       struct lu_fid mbo_fid1;
+       struct lu_fid mbo_fid2;
+       struct lustre_handle mbo_handle;
+       __u64   mbo_valid;
+       __u64   mbo_size; /* Offset, in the case of MDS_READPAGE */
+       obd_time mbo_mtime;
+       obd_time mbo_atime;
+       obd_time mbo_ctime;
+       __u64   mbo_blocks; /* XID, in the case of MDS_READPAGE */
+       __u64   mbo_ioepoch;
+       __u64   mbo_t_state; /* transient file state defined in
+                             * enum md_transient_state
+                             * was "ino" until 2.4.0 */
+       __u32   mbo_fsuid;
+       __u32   mbo_fsgid;
+       __u32   mbo_capability;
+       __u32   mbo_mode;
+       __u32   mbo_uid;
+       __u32   mbo_gid;
+       __u32   mbo_flags;
+       __u32   mbo_rdev;
+       __u32   mbo_nlink; /* #bytes to read in the case of MDS_READPAGE */
+       __u32   mbo_unused2; /* was "generation" until 2.4.0 */
+       __u32   mbo_suppgid;
+       __u32   mbo_eadatasize;
+       __u32   mbo_aclsize;
+       __u32   mbo_max_mdsize;
+       __u32   mbo_max_cookiesize;
+       __u32   mbo_uid_h; /* high 32-bits of uid, for FUID */
+       __u32   mbo_gid_h; /* high 32-bits of gid, for FUID */
+       __u32   mbo_padding_5; /* also fix lustre_swab_mdt_body */
+       __u64   mbo_padding_6;
+       __u64   mbo_padding_7;
+       __u64   mbo_padding_8;
+       __u64   mbo_padding_9;
+       __u64   mbo_padding_10;
 }; /* 216 */
 
 extern void lustre_swab_mdt_body (struct mdt_body *b);
@@ -2478,6 +2474,12 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
                                              */
 #define MDS_OPEN_RELEASE   02000000000000ULL /* Open the file for HSM release */
 
+/* lustre internal open flags, which should not be set from user space */
+#define MDS_OPEN_FL_INTERNAL (MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS |    \
+                             MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK |  \
+                             MDS_OPEN_BY_FID | MDS_OPEN_LEASE |        \
+                             MDS_OPEN_RELEASE)
+
 /* permission for create non-directory file */
 #define MAY_CREATE      (1 << 7)
 /* permission for create directory file */
@@ -2730,10 +2732,10 @@ struct lmv_mds_md_v1 {
                                         * be used to mark the object status,
                                         * for example migrating or dead. */
        __u32 lmv_layout_version;       /* Used for directory restriping */
-       __u32 lmv_padding;
-       struct lu_fid   lmv_master_fid; /* The FID of the master object, which
-                                        * is the namespace-visible dir FID */
-       char lmv_pool_name[LOV_MAXPOOLNAME];    /* pool name */
+       __u32 lmv_padding1;
+       __u64 lmv_padding2;
+       __u64 lmv_padding3;
+       char lmv_pool_name[LOV_MAXPOOLNAME + 1];        /* pool name */
        struct lu_fid lmv_stripe_fids[0];       /* FIDs for each stripe */
 };
 
@@ -2751,6 +2753,12 @@ struct lmv_mds_md_v1 {
 
 #define LMV_HASH_FLAG_MIGRATION        0x80000000
 #define LMV_HASH_FLAG_DEAD     0x40000000
+#define LMV_HASH_FLAG_BAD_TYPE 0x20000000
+
+/* The striped directory has ever lost its master LMV EA, then LFSCK
+ * re-generated it. This flag is used to indicate such case. It is an
+ * on-disk flag. */
+#define LMV_HASH_FLAG_LOST_LMV 0x10000000
 
 /**
  * The FNV-1a hash algorithm is as follows:
@@ -2959,6 +2967,8 @@ struct ldlm_extent {
         __u64 gid;
 };
 
+#define LDLM_GID_ANY  ((__u64) -1)
+
 static inline int ldlm_extent_overlap(const struct ldlm_extent *ex1,
                                      const struct ldlm_extent *ex2)
 {
@@ -3171,7 +3181,29 @@ typedef enum {
 } obd_cmd_t;
 #define OBD_FIRST_OPC OBD_PING
 
-/* catalog of log objects */
+/**
+ * llog contexts indices.
+ *
+ * There is compatibility problem with indexes below, they are not
+ * continuous and must keep their numbers for compatibility needs.
+ * See LU-5218 for details.
+ */
+enum llog_ctxt_id {
+       LLOG_CONFIG_ORIG_CTXT  =  0,
+       LLOG_CONFIG_REPL_CTXT = 1,
+       LLOG_MDS_OST_ORIG_CTXT = 2,
+       LLOG_MDS_OST_REPL_CTXT = 3, /* kept just to avoid re-assignment */
+       LLOG_SIZE_ORIG_CTXT = 4,
+       LLOG_SIZE_REPL_CTXT = 5,
+       LLOG_TEST_ORIG_CTXT = 8,
+       LLOG_TEST_REPL_CTXT = 9, /* kept just to avoid re-assignment */
+       LLOG_CHANGELOG_ORIG_CTXT = 12, /**< changelog generation on mdd */
+       LLOG_CHANGELOG_REPL_CTXT = 13, /**< changelog access on clients */
+       /* for multiple changelog consumers */
+       LLOG_CHANGELOG_USER_ORIG_CTXT = 14,
+       LLOG_AGENT_ORIG_CTXT = 15, /**< agent requests generation on cdt */
+       LLOG_MAX_CTXTS
+};
 
 /** Identifier for a single log object */
 struct llog_logid {
@@ -3283,7 +3315,7 @@ struct llog_setattr64_rec {
        __u32                   lsr_uid_h;
        __u32                   lsr_gid;
        __u32                   lsr_gid_h;
-       __u64                   lsr_padding;
+       __u64                   lsr_valid;
        struct llog_rec_tail    lsr_tail;
 } __attribute__((packed));
 
@@ -3316,15 +3348,9 @@ struct changelog_setinfo {
 
 /** changelog record */
 struct llog_changelog_rec {
-        struct llog_rec_hdr  cr_hdr;
-        struct changelog_rec cr;
-        struct llog_rec_tail cr_tail; /**< for_sizezof_only */
-} __attribute__((packed));
-
-struct llog_changelog_ext_rec {
-       struct llog_rec_hdr      cr_hdr;
-       struct changelog_ext_rec cr;
-       struct llog_rec_tail     cr_tail; /**< for_sizezof_only */
+       struct llog_rec_hdr  cr_hdr;
+       struct changelog_rec cr; /**< Variable length field */
+       struct llog_rec_tail cr_do_not_use; /**< for_sizeof_only */
 } __attribute__((packed));
 
 #define CHANGELOG_USER_PREFIX "cl"
@@ -3410,6 +3436,9 @@ enum llog_flag {
        LLOG_F_ZAP_WHEN_EMPTY   = 0x1,
        LLOG_F_IS_CAT           = 0x2,
        LLOG_F_IS_PLAIN         = 0x4,
+       LLOG_F_EXT_JOBID        = 0x8,
+
+       LLOG_F_EXT_MASK = LLOG_F_EXT_JOBID,
 };
 
 struct llog_log_hdr {
@@ -3525,16 +3554,24 @@ struct lfsck_request {
        union {
                __u32   lr_speed;
                __u32   lr_status;
+               __u32   lr_type;
        };
        __u16           lr_version;
        __u16           lr_active;
        __u16           lr_param;
        __u16           lr_async_windows;
-       __u32           lr_padding_1;
+       union {
+               __u32   lr_flags2;
+               __u32   lr_layout_version;
+       };
        struct lu_fid   lr_fid;
        struct lu_fid   lr_fid2;
-       struct lu_fid   lr_fid3;
-       __u64           lr_padding_2;
+       union {
+               struct lu_fid   lr_fid3;
+               char            lr_pool_name[LOV_MAXPOOLNAME + 1];
+       };
+       __u32           lr_stripe_count;
+       __u32           lr_hash_type;
        __u64           lr_padding_3;
 };
 
@@ -3560,11 +3597,19 @@ enum lfsck_events {
        LE_PEER_EXIT            = 9,
        LE_CONDITIONAL_DESTROY  = 10,
        LE_PAIRS_VERIFY         = 11,
+       LE_CREATE_ORPHAN        = 12,
+       LE_SKIP_NLINK_DECLARE   = 13,
+       LE_SKIP_NLINK           = 14,
+       LE_SET_LMV_MASTER       = 15,
+       LE_SET_LMV_SLAVE        = 16,
 };
 
 enum lfsck_event_flags {
        LEF_TO_OST              = 0x00000001,
        LEF_FROM_OST            = 0x00000002,
+       LEF_SET_LMV_HASH        = 0x00000004,
+       LEF_SET_LMV_ALL         = 0x00000008,
+       LEF_RECHECK_NAME_HASH   = 0x00000010,
 };
 
 static inline void lustre_set_wire_obdo(const struct obd_connect_data *ocd,
@@ -3635,6 +3680,8 @@ extern void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
 extern void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
                                             int stripe_count);
 extern void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
+void lustre_print_user_md(unsigned int level, struct lov_user_md *lum,
+                         const char *msg);
 
 /* llog_swab.c */
 extern void lustre_swab_llogd_body (struct llogd_body *d);
@@ -3871,6 +3918,14 @@ struct getinfo_fid2path {
 
 void lustre_swab_fid2path (struct getinfo_fid2path *gf);
 
+/** path2parent request/reply structures */
+struct getparent {
+       struct lu_fid   gp_fid;         /**< parent FID */
+       __u32           gp_linkno;      /**< hardlink number */
+       __u32           gp_name_size;   /**< size of the name field */
+       char            gp_name[0];     /**< zero-terminated link name */
+} __attribute__((packed));
+
 enum {
         LAYOUT_INTENT_ACCESS    = 0,
         LAYOUT_INTENT_READ      = 1,
@@ -3982,6 +4037,12 @@ struct object_update_param {
        char    oup_buf[0];
 };
 
+static inline size_t
+object_update_param_size(const struct object_update_param *param)
+{
+       return cfs_size_round(sizeof(*param) + param->oup_len);
+}
+
 /* object update */
 struct object_update {
        __u16           ou_type;                /* enum update_type */
@@ -4008,6 +4069,43 @@ struct object_update_request {
 void lustre_swab_object_update(struct object_update *ou);
 void lustre_swab_object_update_request(struct object_update_request *our);
 
+static inline size_t
+object_update_size(const struct object_update *update)
+{
+       const struct    object_update_param *param;
+       size_t          size;
+       unsigned int    i;
+
+       size = offsetof(struct object_update, ou_params[0]);
+       for (i = 0; i < update->ou_params_count; i++) {
+               param = (struct object_update_param *)((char *)update + size);
+               size += object_update_param_size(param);
+       }
+
+       return size;
+}
+
+static inline struct object_update *
+object_update_request_get(const struct object_update_request *our,
+                         unsigned int index, size_t *size)
+{
+       void    *ptr;
+       unsigned int i;
+
+       if (index >= our->ourq_count)
+               return NULL;
+
+       ptr = (void *)&our->ourq_updates[0];
+       for (i = 0; i < index; i++)
+               ptr += object_update_size(ptr);
+
+       if (size != NULL)
+               *size = object_update_size(ptr);
+
+       return ptr;
+}
+
+
 /* the result of object update */
 struct object_update_result {
        __u32   our_rc;
@@ -4030,6 +4128,33 @@ struct object_update_reply {
 void lustre_swab_object_update_result(struct object_update_result *our);
 void lustre_swab_object_update_reply(struct object_update_reply *our);
 
+static inline struct object_update_result *
+object_update_result_get(const struct object_update_reply *reply,
+                        unsigned int index, size_t *size)
+{
+       __u16 count = reply->ourp_count;
+       unsigned int i;
+       void *ptr;
+
+       if (index >= count)
+               return NULL;
+
+       ptr = (char *)reply +
+             cfs_size_round(offsetof(struct object_update_reply,
+                                     ourp_lens[count]));
+       for (i = 0; i < index; i++) {
+               if (reply->ourp_lens[i] == 0)
+                       return NULL;
+
+               ptr += cfs_size_round(reply->ourp_lens[i]);
+       }
+
+       if (size != NULL)
+               *size = reply->ourp_lens[index];
+
+       return ptr;
+}
+
 /** layout swap request structure
  * fid1 and fid2 are in mdt_body
  */