Whamcloud - gitweb
LU-14291 ptlrpc: format UPDATE messages in server-only code
[fs/lustre-release.git] / lustre / ptlrpc / layout.c
index 9780452..d7a9c28 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/module.h>
 
 #include <llog_swab.h>
-#include <lustre_debug.h>
 #include <lustre_swab.h>
 #include <obd.h>
 #include <obd_support.h>
@@ -71,10 +70,10 @@ static const struct req_msg_field *mgs_target_info_only[] = {
         &RMF_MGS_TARGET_INFO
 };
 
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 18, 53, 0)
 static const struct req_msg_field *mgs_set_info[] = {
-        &RMF_PTLRPC_BODY,
-        &RMF_MGS_SEND_PARAM
+       &RMF_PTLRPC_BODY,
+       &RMF_MGS_SEND_PARAM
 };
 #endif
 
@@ -100,8 +99,8 @@ static const struct req_msg_field *mdt_body_capa[] = {
 };
 
 static const struct req_msg_field *quotactl_only[] = {
-        &RMF_PTLRPC_BODY,
-        &RMF_OBD_QUOTACTL
+       &RMF_PTLRPC_BODY,
+       &RMF_OBD_QUOTACTL
 };
 
 static const struct req_msg_field *quota_body_only[] = {
@@ -213,7 +212,8 @@ static const struct req_msg_field *mds_reint_create_acl_client[] = {
        &RMF_DLM_REQ,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_create_sym_client[] = {
@@ -225,7 +225,8 @@ static const struct req_msg_field *mds_reint_create_sym_client[] = {
        &RMF_DLM_REQ,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_open_client[] = {
@@ -237,7 +238,8 @@ static const struct req_msg_field *mds_reint_open_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_open_server[] = {
@@ -372,6 +374,13 @@ static const struct req_msg_field *obd_set_info_client[] = {
         &RMF_SETINFO_VAL
 };
 
+static const struct req_msg_field *mdt_set_info_client[] = {
+       &RMF_PTLRPC_BODY,
+       &RMF_SETINFO_KEY,
+       &RMF_SETINFO_VAL,
+       &RMF_MDT_BODY
+};
+
 static const struct req_msg_field *ost_grant_shrink_client[] = {
         &RMF_PTLRPC_BODY,
         &RMF_SETINFO_KEY,
@@ -460,7 +469,8 @@ static const struct req_msg_field *ldlm_intent_open_server[] = {
        &RMF_CAPA1,
        &RMF_CAPA2,
        &RMF_NIOBUF_INLINE,
-       &RMF_FILE_SECCTX
+       &RMF_FILE_SECCTX,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_getattr_client[] = {
@@ -481,7 +491,8 @@ static const struct req_msg_field *ldlm_intent_getattr_server[] = {
        &RMF_ACL,
        &RMF_CAPA1,
        &RMF_FILE_SECCTX,
-       &RMF_DEFAULT_MDT_MD
+       &RMF_DEFAULT_MDT_MD,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_create_client[] = {
@@ -494,7 +505,8 @@ static const struct req_msg_field *ldlm_intent_create_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_open_client[] = {
@@ -508,7 +520,8 @@ static const struct req_msg_field *ldlm_intent_open_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_getxattr_client[] = {
@@ -570,21 +583,11 @@ static const struct req_msg_field *mds_setattr_server[] = {
         &RMF_CAPA2
 };
 
-static const struct req_msg_field *mds_update_client[] = {
-       &RMF_PTLRPC_BODY,
-       &RMF_OUT_UPDATE_HEADER,
-       &RMF_OUT_UPDATE_BUF,
-};
-
-static const struct req_msg_field *mds_update_server[] = {
-       &RMF_PTLRPC_BODY,
-       &RMF_OUT_UPDATE_REPLY,
-};
-
 static const struct req_msg_field *llog_origin_handle_create_client[] = {
-        &RMF_PTLRPC_BODY,
-        &RMF_LLOGD_BODY,
-        &RMF_NAME
+       &RMF_PTLRPC_BODY,
+       &RMF_LLOGD_BODY,
+       &RMF_NAME,
+       &RMF_MDT_BODY
 };
 
 static const struct req_msg_field *llogd_body_only[] = {
@@ -754,10 +757,11 @@ static const struct req_msg_field *obd_lfsck_reply[] = {
 static struct req_format *req_formats[] = {
        &RQF_OBD_PING,
        &RQF_OBD_SET_INFO,
+       &RQF_MDT_SET_INFO,
        &RQF_OBD_IDX_READ,
        &RQF_SEC_CTX,
        &RQF_MGS_TARGET_REG,
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 18, 53, 0)
        &RQF_MGS_SET_INFO,
 #endif
        &RQF_MGS_CONFIG_READ,
@@ -800,7 +804,9 @@ static struct req_format *req_formats[] = {
        &RQF_MDS_HSM_REQUEST,
        &RQF_MDS_SWAP_LAYOUTS,
        &RQF_MDS_RMFID,
+#ifdef HAVE_SERVER_SUPPORT
        &RQF_OUT_UPDATE,
+#endif
        &RQF_OST_CONNECT,
        &RQF_OST_DISCONNECT,
        &RQF_OST_QUOTACTL,
@@ -808,6 +814,7 @@ static struct req_format *req_formats[] = {
        &RQF_OST_SETATTR,
        &RQF_OST_CREATE,
        &RQF_OST_PUNCH,
+       &RQF_OST_FALLOCATE,
        &RQF_OST_SYNC,
        &RQF_OST_DESTROY,
        &RQF_OST_BRW_READ,
@@ -820,6 +827,7 @@ static struct req_format *req_formats[] = {
        &RQF_OST_SET_INFO_LAST_FID,
        &RQF_OST_GET_INFO_FIEMAP,
        &RQF_OST_LADVISE,
+       &RQF_OST_SEEK,
        &RQF_LDLM_ENQUEUE,
        &RQF_LDLM_ENQUEUE_LVB,
        &RQF_LDLM_CONVERT,
@@ -848,34 +856,40 @@ static struct req_format *req_formats[] = {
 };
 
 struct req_msg_field {
-        const __u32 rmf_flags;
-        const char  *rmf_name;
-        /**
-         * Field length. (-1) means "variable length".  If the
-         * \a RMF_F_STRUCT_ARRAY flag is set the field is also variable-length,
-         * but the actual size must be a whole multiple of \a rmf_size.
-         */
-        const int   rmf_size;
-        void        (*rmf_swabber)(void *);
-        void        (*rmf_dumper)(void *);
-        int         rmf_offset[ARRAY_SIZE(req_formats)][RCL_NR];
+       const __u32 rmf_flags;
+       const char  *rmf_name;
+       /**
+        * Field length. (-1) means "variable length".  If the
+        * \a RMF_F_STRUCT_ARRAY flag is set the field is also variable-length,
+        * but the actual size must be a whole multiple of \a rmf_size.
+        */
+       const int   rmf_size;
+       void        (*rmf_swabber)(void *);
+       /**
+        * Pass buffer size to swabbing function
+        * \retval      > 0             the number of bytes swabbed
+        *              -EOVERFLOW      on error
+        */
+       int         (*rmf_swab_len)(void *, __u32);
+       void        (*rmf_dumper)(void *);
+       int         rmf_offset[ARRAY_SIZE(req_formats)][RCL_NR];
 };
 
 enum rmf_flags {
-        /**
-         * The field is a string, must be NUL-terminated.
-         */
-        RMF_F_STRING = 1 << 0,
-        /**
-         * The field's buffer size need not match the declared \a rmf_size.
-         */
-        RMF_F_NO_SIZE_CHECK = 1 << 1,
-        /**
-         * The field's buffer size must be a whole multiple of the declared \a
-         * rmf_size and the \a rmf_swabber function must work on the declared \a
-         * rmf_size worth of bytes.
-         */
-        RMF_F_STRUCT_ARRAY = 1 << 2
+       /**
+        * The field is a string, must be NUL-terminated.
+        */
+       RMF_F_STRING            = BIT(0),
+       /**
+        * The field's buffer size need not match the declared \a rmf_size.
+        */
+       RMF_F_NO_SIZE_CHECK     = BIT(1),
+       /**
+        * The field's buffer size must be a whole multiple of the declared \a
+        * rmf_size and the \a rmf_swabber function must work on the declared \a
+        * rmf_size worth of bytes.
+        */
+       RMF_F_STRUCT_ARRAY      = BIT(2),
 };
 
 struct req_capsule;
@@ -891,6 +905,14 @@ struct req_capsule;
         .rmf_dumper  = (void (*)(void*))(dumper)                \
 }
 
+#define DEFINE_MSGFL(name, flags, size, swab_len, dumper) {    \
+       .rmf_name     = (name),                                 \
+       .rmf_flags    = (flags),                                \
+       .rmf_size     = (size),                                 \
+       .rmf_swab_len = (int (*)(void *, __u32))(swab_len),     \
+       .rmf_dumper   = (void (*)(void *))(dumper)              \
+}
+
 struct req_msg_field RMF_GENERIC_DATA =
         DEFINE_MSGF("generic_data", 0,
                     -1, NULL, NULL);
@@ -902,11 +924,11 @@ struct req_msg_field RMF_MGS_TARGET_INFO =
                     lustre_swab_mgs_target_info, NULL);
 EXPORT_SYMBOL(RMF_MGS_TARGET_INFO);
 
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 18, 53, 0)
 struct req_msg_field RMF_MGS_SEND_PARAM =
-        DEFINE_MSGF("mgs_send_param", 0,
-                    sizeof(struct mgs_send_param),
-                    NULL, NULL);
+       DEFINE_MSGF("mgs_send_param", 0,
+                   sizeof(struct mgs_send_param),
+                   NULL, NULL);
 EXPORT_SYMBOL(RMF_MGS_SEND_PARAM);
 #endif
 
@@ -972,9 +994,10 @@ struct req_msg_field RMF_MDT_BODY =
 EXPORT_SYMBOL(RMF_MDT_BODY);
 
 struct req_msg_field RMF_OBD_QUOTACTL =
-        DEFINE_MSGF("obd_quotactl", 0,
-                    sizeof(struct obd_quotactl),
-                    lustre_swab_obd_quotactl, NULL);
+       DEFINE_MSGFL("obd_quotactl",
+                    0,
+                    sizeof(struct obd_quotactl),
+                    lustre_swab_obd_quotactl, NULL);
 EXPORT_SYMBOL(RMF_OBD_QUOTACTL);
 
 struct req_msg_field RMF_QUOTA_BODY =
@@ -1040,6 +1063,10 @@ struct req_msg_field RMF_FILE_SECCTX =
        DEFINE_MSGF("file_secctx", RMF_F_NO_SIZE_CHECK, -1, NULL, NULL);
 EXPORT_SYMBOL(RMF_FILE_SECCTX);
 
+struct req_msg_field RMF_FILE_ENCCTX =
+       DEFINE_MSGF("file_encctx", RMF_F_NO_SIZE_CHECK, -1, NULL, NULL);
+EXPORT_SYMBOL(RMF_FILE_ENCCTX);
+
 struct req_msg_field RMF_LLOGD_BODY =
         DEFINE_MSGF("llogd_body", 0,
                     sizeof(struct llogd_body), lustre_swab_llogd_body, NULL);
@@ -1198,12 +1225,12 @@ struct req_msg_field RMF_OST_ID =
 EXPORT_SYMBOL(RMF_OST_ID);
 
 struct req_msg_field RMF_FIEMAP_KEY =
-        DEFINE_MSGF("fiemap", 0, sizeof(struct ll_fiemap_info_key),
-                    lustre_swab_fiemap, NULL);
+       DEFINE_MSGF("fiemap_key", 0, sizeof(struct ll_fiemap_info_key),
+                   lustre_swab_fiemap_info_key, NULL);
 EXPORT_SYMBOL(RMF_FIEMAP_KEY);
 
 struct req_msg_field RMF_FIEMAP_VAL =
-        DEFINE_MSGF("fiemap", 0, -1, lustre_swab_fiemap, NULL);
+       DEFINE_MSGFL("fiemap", 0, -1, lustre_swab_fiemap, NULL);
 EXPORT_SYMBOL(RMF_FIEMAP_VAL);
 
 struct req_msg_field RMF_IDX_INFO =
@@ -1249,15 +1276,6 @@ struct req_msg_field RMF_MDS_HSM_REQUEST =
                    lustre_swab_hsm_request, NULL);
 EXPORT_SYMBOL(RMF_MDS_HSM_REQUEST);
 
-struct req_msg_field RMF_OUT_UPDATE = DEFINE_MSGF("object_update", 0, -1,
-                               lustre_swab_object_update_request, NULL);
-EXPORT_SYMBOL(RMF_OUT_UPDATE);
-
-struct req_msg_field RMF_OUT_UPDATE_REPLY =
-                       DEFINE_MSGF("object_update_reply", 0, -1,
-                                   lustre_swab_object_update_reply, NULL);
-EXPORT_SYMBOL(RMF_OUT_UPDATE_REPLY);
-
 struct req_msg_field RMF_SWAP_LAYOUTS =
        DEFINE_MSGF("swap_layouts", 0, sizeof(struct  mdc_swap_layouts),
                    lustre_swab_swap_layouts, NULL);
@@ -1285,15 +1303,6 @@ struct req_msg_field RMF_OST_LADVISE =
                    lustre_swab_ladvise, NULL);
 EXPORT_SYMBOL(RMF_OST_LADVISE);
 
-struct req_msg_field RMF_OUT_UPDATE_HEADER = DEFINE_MSGF("out_update_header", 0,
-                               -1, lustre_swab_out_update_header, NULL);
-EXPORT_SYMBOL(RMF_OUT_UPDATE_HEADER);
-
-struct req_msg_field RMF_OUT_UPDATE_BUF = DEFINE_MSGF("update_buf",
-                       RMF_F_STRUCT_ARRAY, sizeof(struct out_update_buffer),
-                       lustre_swab_out_update_buffer, NULL);
-EXPORT_SYMBOL(RMF_OUT_UPDATE_BUF);
-
 /*
  * Request formats.
  */
@@ -1332,6 +1341,10 @@ struct req_format RQF_OBD_SET_INFO =
         DEFINE_REQ_FMT0("OBD_SET_INFO", obd_set_info_client, empty);
 EXPORT_SYMBOL(RQF_OBD_SET_INFO);
 
+struct req_format RQF_MDT_SET_INFO =
+       DEFINE_REQ_FMT0("MDT_SET_INFO", mdt_set_info_client, empty);
+EXPORT_SYMBOL(RQF_MDT_SET_INFO);
+
 /* Read index file through the network */
 struct req_format RQF_OBD_IDX_READ =
        DEFINE_REQ_FMT0("OBD_IDX_READ",
@@ -1347,10 +1360,10 @@ struct req_format RQF_MGS_TARGET_REG =
                          mgs_target_info_only);
 EXPORT_SYMBOL(RQF_MGS_TARGET_REG);
 
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 18, 53, 0)
 struct req_format RQF_MGS_SET_INFO =
-        DEFINE_REQ_FMT0("MGS_SET_INFO", mgs_set_info,
-                         mgs_set_info);
+       DEFINE_REQ_FMT0("MGS_SET_INFO", mgs_set_info,
+                       mgs_set_info);
 EXPORT_SYMBOL(RQF_MGS_SET_INFO);
 #endif
 
@@ -1511,11 +1524,6 @@ struct req_format RQF_MDS_GET_INFO =
                         mds_getinfo_server);
 EXPORT_SYMBOL(RQF_MDS_GET_INFO);
 
-struct req_format RQF_OUT_UPDATE =
-       DEFINE_REQ_FMT0("OUT_UPDATE", mds_update_client,
-                       mds_update_server);
-EXPORT_SYMBOL(RQF_OUT_UPDATE);
-
 struct req_format RQF_LDLM_ENQUEUE =
         DEFINE_REQ_FMT0("LDLM_ENQUEUE",
                         ldlm_enqueue_client, ldlm_enqueue_lvb_server);
@@ -1696,6 +1704,14 @@ struct req_format RQF_OST_PUNCH =
         DEFINE_REQ_FMT0("OST_PUNCH", ost_body_capa, ost_body_only);
 EXPORT_SYMBOL(RQF_OST_PUNCH);
 
+struct req_format RQF_OST_FALLOCATE =
+       DEFINE_REQ_FMT0("OST_FALLOCATE", ost_body_capa, ost_body_only);
+EXPORT_SYMBOL(RQF_OST_FALLOCATE);
+
+struct req_format RQF_OST_SEEK =
+       DEFINE_REQ_FMT0("OST_SEEK", ost_body_only, ost_body_only);
+EXPORT_SYMBOL(RQF_OST_SEEK);
+
 struct req_format RQF_OST_SYNC =
         DEFINE_REQ_FMT0("OST_SYNC", ost_body_capa, ost_body_only);
 EXPORT_SYMBOL(RQF_OST_SYNC);
@@ -1978,75 +1994,88 @@ __u32 __req_capsule_offset(const struct req_capsule *pill,
  * Helper for __req_capsule_get(); swabs value / array of values and/or dumps
  * them if desired.
  */
-static
-void
+static int
 swabber_dumper_helper(struct req_capsule *pill,
-                      const struct req_msg_field *field,
-                      enum req_location loc,
-                      int offset,
-                      void *value, int len, int dump, void (*swabber)( void *))
+                     const struct req_msg_field *field,
+                     enum req_location loc,
+                     int offset,
+                     void *value, int len, bool dump, void (*swabber)(void *))
 {
-        void    *p;
-        int     i;
-        int     n;
-        int     do_swab;
-        int     inout = loc == RCL_CLIENT;
+       void *p;
+       int i;
+       int n;
+       int size;
+       int rc = 0;
+       bool do_swab;
+       bool inout = loc == RCL_CLIENT;
+       bool array = field->rmf_flags & RMF_F_STRUCT_ARRAY;
 
-        swabber = swabber ?: field->rmf_swabber;
+       swabber = swabber ?: field->rmf_swabber;
 
-        if (ptlrpc_buf_need_swab(pill->rc_req, inout, offset) &&
-            swabber != NULL && value != NULL)
-                do_swab = 1;
-        else
-                do_swab = 0;
+       if (ptlrpc_buf_need_swab(pill->rc_req, inout, offset) &&
+           (swabber != NULL || field->rmf_swab_len != NULL) && value != NULL)
+               do_swab = true;
+       else
+               do_swab = false;
 
        if (!field->rmf_dumper)
-               dump = 0;
-
-        if (!(field->rmf_flags & RMF_F_STRUCT_ARRAY)) {
-                if (dump) {
-                        CDEBUG(D_RPCTRACE, "Dump of %sfield %s follows\n",
-                               do_swab ? "unswabbed " : "", field->rmf_name);
-                        field->rmf_dumper(value);
-                }
-                if (!do_swab)
-                        return;
-                swabber(value);
-                ptlrpc_buf_set_swabbed(pill->rc_req, inout, offset);
+               dump = false;
+
+       /*
+        * We're swabbing an array; swabber() swabs a single array element, so
+        * swab every element.
+        */
+       if (array && (len % field->rmf_size)) {
+               static const struct req_msg_field *last_field;
+
+               if (field != last_field) {
+                       CERROR("%s: array buffer size %u is not a multiple of element size %u\n",
+                              field->rmf_name, len, field->rmf_size);
+                       last_field = field;
+               }
+       }
+       /* For the non-array cases, the process of swab/dump/swab only
+        * needs to be done once. (n = 1)
+        */
+       if (!array)
+               len = field->rmf_size;
+       for (p = value, i = 0, n = len / field->rmf_size;
+            i < n;
+            i++, p += field->rmf_size) {
                if (dump) {
-                        CDEBUG(D_RPCTRACE, "Dump of swabbed field %s "
-                               "follows\n", field->rmf_name);
-                        field->rmf_dumper(value);
-                }
-
-                return;
-        }
-
-        /*
-         * We're swabbing an array; swabber() swabs a single array element, so
-         * swab every element.
-         */
-        LASSERT((len % field->rmf_size) == 0);
-        for (p = value, i = 0, n = len / field->rmf_size;
-             i < n;
-             i++, p += field->rmf_size) {
-                if (dump) {
-                        CDEBUG(D_RPCTRACE, "Dump of %sarray field %s, "
-                               "element %d follows\n",
-                               do_swab ? "unswabbed " : "", field->rmf_name, i);
-                        field->rmf_dumper(p);
-                }
-                if (!do_swab)
-                        continue;
-                swabber(p);
-                if (dump) {
-                        CDEBUG(D_RPCTRACE, "Dump of swabbed array field %s, "
-                               "element %d follows\n", field->rmf_name, i);
-                        field->rmf_dumper(value);
-                }
+                       CDEBUG(D_RPCTRACE, "Dump of %s%sfield %s element %d follows\n",
+                              do_swab ? "unswabbed " : "",
+                              array ? "array " : "",
+                              field->rmf_name, i);
+                       field->rmf_dumper(p);
+               }
+               if (!do_swab) {
+                       if (array)
+                               continue;
+                       else
+                               break;
+               }
+               if (!field->rmf_swab_len) {
+                       swabber(p);
+               } else {
+                       size = field->rmf_swab_len(p, len);
+                       if (size > 0) {
+                               len -= size;
+                       } else {
+                               rc = size;
+                               break;
+                       }
+               }
+               if (dump) {
+                       CDEBUG(D_RPCTRACE, "Dump of swabbed %sfield %s, element %d follows\n",
+                              array ? "array " : "", field->rmf_name, i);
+                       field->rmf_dumper(value);
+               }
         }
         if (do_swab)
                 ptlrpc_buf_set_swabbed(pill->rc_req, inout, offset);
+
+       return rc;
 }
 
 /**
@@ -2060,14 +2089,14 @@ swabber_dumper_helper(struct req_capsule *pill,
  * element of the array swabbed.
  */
 static void *__req_capsule_get(struct req_capsule *pill,
-                               const struct req_msg_field *field,
-                               enum req_location loc,
-                               void (*swabber)( void *),
-                               int dump)
+                              const struct req_msg_field *field,
+                              enum req_location loc,
+                              void (*swabber)(void *),
+                              bool dump)
 {
-        const struct req_format *fmt;
-        struct lustre_msg       *msg;
-        void                    *value;
+       const struct req_format *fmt;
+       struct lustre_msg       *msg;
+       void                    *value;
        __u32                    len;
        __u32                    offset;
 
@@ -2148,11 +2177,12 @@ void __req_capsule_dump(struct req_capsule *pill, enum req_location loc)
                         * have a specific dumper
                         */
                        len = req_capsule_get_size(pill, field, loc);
-                       CDEBUG(D_RPCTRACE, "Field %s has no dumper function;"
-                               "field size is %u\n", field->rmf_name, len);
+                       CDEBUG(D_RPCTRACE,
+                              "Field %s has no dumper function; field size is %u\n",
+                              field->rmf_name, len);
                } else {
                        /* It's dumping side-effect that we're interested in */
-                       (void) __req_capsule_get(pill, field, loc, NULL, 1);
+                       (void) __req_capsule_get(pill, field, loc, NULL, true);
                }
        }
        CDEBUG(D_RPCTRACE, "END REQ CAPSULE DUMP\n");
@@ -2181,9 +2211,9 @@ EXPORT_SYMBOL(req_capsule_server_dump);
  * buffer corresponding to the given RMF (\a field) of a \a pill.
  */
 void *req_capsule_client_get(struct req_capsule *pill,
-                             const struct req_msg_field *field)
+                            const struct req_msg_field *field)
 {
-        return __req_capsule_get(pill, field, RCL_CLIENT, NULL, 0);
+       return __req_capsule_get(pill, field, RCL_CLIENT, NULL, false);
 }
 EXPORT_SYMBOL(req_capsule_client_get);
 
@@ -2197,7 +2227,7 @@ void *req_capsule_client_swab_get(struct req_capsule *pill,
                                  const struct req_msg_field *field,
                                  void *swabber)
 {
-        return __req_capsule_get(pill, field, RCL_CLIENT, swabber, 0);
+       return __req_capsule_get(pill, field, RCL_CLIENT, swabber, false);
 }
 EXPORT_SYMBOL(req_capsule_client_swab_get);
 
@@ -2212,8 +2242,8 @@ void *req_capsule_client_sized_get(struct req_capsule *pill,
                                   const struct req_msg_field *field,
                                   __u32 len)
 {
-        req_capsule_set_size(pill, field, RCL_CLIENT, len);
-        return __req_capsule_get(pill, field, RCL_CLIENT, NULL, 0);
+       req_capsule_set_size(pill, field, RCL_CLIENT, len);
+       return __req_capsule_get(pill, field, RCL_CLIENT, NULL, false);
 }
 EXPORT_SYMBOL(req_capsule_client_sized_get);
 
@@ -2224,7 +2254,7 @@ EXPORT_SYMBOL(req_capsule_client_sized_get);
 void *req_capsule_server_get(struct req_capsule *pill,
                              const struct req_msg_field *field)
 {
-        return __req_capsule_get(pill, field, RCL_SERVER, NULL, 0);
+       return __req_capsule_get(pill, field, RCL_SERVER, NULL, false);
 }
 EXPORT_SYMBOL(req_capsule_server_get);
 
@@ -2235,10 +2265,10 @@ EXPORT_SYMBOL(req_capsule_server_get);
  * swabbing done outside this capsule abstraction.
  */
 void *req_capsule_server_swab_get(struct req_capsule *pill,
-                                  const struct req_msg_field *field,
-                                  void *swabber)
+                                 const struct req_msg_field *field,
+                                 void *swabber)
 {
-        return __req_capsule_get(pill, field, RCL_SERVER, swabber, 0);
+       return __req_capsule_get(pill, field, RCL_SERVER, swabber, false);
 }
 EXPORT_SYMBOL(req_capsule_server_swab_get);
 
@@ -2253,8 +2283,8 @@ void *req_capsule_server_sized_get(struct req_capsule *pill,
                                   const struct req_msg_field *field,
                                   __u32 len)
 {
-        req_capsule_set_size(pill, field, RCL_SERVER, len);
-        return __req_capsule_get(pill, field, RCL_SERVER, NULL, 0);
+       req_capsule_set_size(pill, field, RCL_SERVER, len);
+       return __req_capsule_get(pill, field, RCL_SERVER, NULL, false);
 }
 EXPORT_SYMBOL(req_capsule_server_sized_get);
 
@@ -2263,7 +2293,7 @@ void *req_capsule_server_sized_swab_get(struct req_capsule *pill,
                                        __u32 len, void *swabber)
 {
        req_capsule_set_size(pill, field, RCL_SERVER, len);
-       return __req_capsule_get(pill, field, RCL_SERVER, swabber, 0);
+       return __req_capsule_get(pill, field, RCL_SERVER, swabber, false);
 }
 EXPORT_SYMBOL(req_capsule_server_sized_swab_get);
 
@@ -2276,9 +2306,9 @@ EXPORT_SYMBOL(req_capsule_server_sized_swab_get);
  * client and server alike.
  */
 const void *req_capsule_other_get(struct req_capsule *pill,
-                                  const struct req_msg_field *field)
+                                 const struct req_msg_field *field)
 {
-        return __req_capsule_get(pill, field, pill->rc_loc ^ 1, NULL, 0);
+       return __req_capsule_get(pill, field, pill->rc_loc ^ 1, NULL, false);
 }
 EXPORT_SYMBOL(req_capsule_other_get);
 
@@ -2498,17 +2528,22 @@ void req_capsule_shrink(struct req_capsule *pill,
 
         offset = __req_capsule_offset(pill, field, loc);
 
-        msg = __req_msg(pill, loc);
-        len = lustre_msg_buflen(msg, offset);
+       msg = __req_msg(pill, loc);
+       len = lustre_msg_buflen(msg, offset);
        LASSERTF(newlen <= len, "%s:%s, oldlen=%u, newlen=%u\n",
-                                fmt->rf_name, field->rmf_name, len, newlen);
-
-        if (loc == RCL_CLIENT)
-                pill->rc_req->rq_reqlen = lustre_shrink_msg(msg, offset, newlen,
-                                                            1);
-        else
-                pill->rc_req->rq_replen = lustre_shrink_msg(msg, offset, newlen,
-                                                            1);
+                fmt->rf_name, field->rmf_name, len, newlen);
+
+       if (loc == RCL_CLIENT) {
+               pill->rc_req->rq_reqlen = lustre_shrink_msg(msg, offset, newlen,
+                                                           1);
+       } else {
+               pill->rc_req->rq_replen = lustre_shrink_msg(msg, offset, newlen,
+                                                           1);
+               /* update also field size in reply lenghts arrays for possible
+                * reply re-pack due to req_capsule_server_grow() call.
+                */
+               req_capsule_set_size(pill, field, loc, newlen);
+       }
 }
 EXPORT_SYMBOL(req_capsule_shrink);
 
@@ -2516,46 +2551,58 @@ int req_capsule_server_grow(struct req_capsule *pill,
                            const struct req_msg_field *field,
                            __u32 newlen)
 {
-        struct ptlrpc_reply_state *rs = pill->rc_req->rq_reply_state, *nrs;
-        char *from, *to;
+       struct ptlrpc_reply_state *rs = pill->rc_req->rq_reply_state, *nrs;
+       char *from, *to;
        int rc;
        __u32 offset, len;
 
-        LASSERT(pill->rc_fmt != NULL);
-        LASSERT(__req_format_is_sane(pill->rc_fmt));
-        LASSERT(req_capsule_has_field(pill, field, RCL_SERVER));
-        LASSERT(req_capsule_field_present(pill, field, RCL_SERVER));
-
-        len = req_capsule_get_size(pill, field, RCL_SERVER);
-        offset = __req_capsule_offset(pill, field, RCL_SERVER);
-       if ((__u32)pill->rc_req->rq_repbuf_len >=
-            lustre_packed_msg_size(pill->rc_req->rq_repmsg) - len + newlen)
-                CERROR("Inplace repack might be done\n");
-
-        pill->rc_req->rq_reply_state = NULL;
-        req_capsule_set_size(pill, field, RCL_SERVER, newlen);
-        rc = req_capsule_server_pack(pill);
-        if (rc) {
-                /* put old rs back, the caller will decide what to do */
-                pill->rc_req->rq_reply_state = rs;
-                return rc;
-        }
-        nrs = pill->rc_req->rq_reply_state;
-        /* Now we need only buffers, copy first chunk */
-        to = lustre_msg_buf(nrs->rs_msg, 0, 0);
-        from = lustre_msg_buf(rs->rs_msg, 0, 0);
-        len = (char *)lustre_msg_buf(rs->rs_msg, offset, 0) - from;
-        memcpy(to, from, len);
-        /* check if we have tail and copy it too */
-        if (rs->rs_msg->lm_bufcount > offset + 1) {
-                to = lustre_msg_buf(nrs->rs_msg, offset + 1, 0);
-                from = lustre_msg_buf(rs->rs_msg, offset + 1, 0);
-                offset = rs->rs_msg->lm_bufcount - 1;
-                len = (char *)lustre_msg_buf(rs->rs_msg, offset, 0) +
-                      cfs_size_round(rs->rs_msg->lm_buflens[offset]) - from;
-                memcpy(to, from, len);
-        }
-        /* drop old reply if everything is fine */
+       LASSERT(pill->rc_fmt != NULL);
+       LASSERT(__req_format_is_sane(pill->rc_fmt));
+       LASSERT(req_capsule_has_field(pill, field, RCL_SERVER));
+       LASSERT(req_capsule_field_present(pill, field, RCL_SERVER));
+
+       len = req_capsule_get_size(pill, field, RCL_SERVER);
+       offset = __req_capsule_offset(pill, field, RCL_SERVER);
+
+       CDEBUG(D_INFO, "Reply packed: %d, allocated: %d, field len %d -> %d\n",
+              lustre_packed_msg_size(rs->rs_msg), rs->rs_repbuf_len,
+                                     len, newlen);
+
+       req_capsule_set_size(pill, field, RCL_SERVER, newlen);
+       /**
+        * There can be enough space in current reply buffer, make sure
+        * that rs_repbuf is not a wrapper but real reply msg, otherwise
+        * re-packing is still needed.
+        */
+       if (rs->rs_msg == rs->rs_repbuf &&
+           rs->rs_repbuf_len >=
+           lustre_packed_msg_size(rs->rs_msg) - len + newlen) {
+               pill->rc_req->rq_replen = lustre_grow_msg(rs->rs_msg, offset,
+                                                         newlen);
+               return 0;
+       }
+
+       /* Re-allocate replay state */
+       pill->rc_req->rq_reply_state = NULL;
+       rc = req_capsule_server_pack(pill);
+       if (rc) {
+               /* put old values back, the caller should decide what to do */
+               req_capsule_set_size(pill, field, RCL_SERVER, len);
+               pill->rc_req->rq_reply_state = rs;
+               return rc;
+       }
+       nrs = pill->rc_req->rq_reply_state;
+       LASSERT(lustre_packed_msg_size(nrs->rs_msg) >
+               lustre_packed_msg_size(rs->rs_msg));
+
+       /* Now we need only buffers, copy them and grow the needed one */
+       to = lustre_msg_buf(nrs->rs_msg, 0, 0);
+       from = lustre_msg_buf(rs->rs_msg, 0, 0);
+       memcpy(to, from,
+              (char *)rs->rs_msg + lustre_packed_msg_size(rs->rs_msg) - from);
+       lustre_msg_set_buflen(nrs->rs_msg, offset, len);
+       pill->rc_req->rq_replen = lustre_grow_msg(nrs->rs_msg, offset, newlen);
+
         if (rs->rs_difficult) {
                 /* copy rs data */
                 int i;
@@ -2577,10 +2624,44 @@ int req_capsule_server_grow(struct req_capsule *pill,
 }
 EXPORT_SYMBOL(req_capsule_server_grow);
 
+#ifdef HAVE_SERVER_SUPPORT
+static const struct req_msg_field *mds_update_client[] = {
+       &RMF_PTLRPC_BODY,
+       &RMF_OUT_UPDATE_HEADER,
+       &RMF_OUT_UPDATE_BUF,
+};
+
+static const struct req_msg_field *mds_update_server[] = {
+       &RMF_PTLRPC_BODY,
+       &RMF_OUT_UPDATE_REPLY,
+};
+
+struct req_msg_field RMF_OUT_UPDATE = DEFINE_MSGFL("object_update", 0, -1,
+                               lustre_swab_object_update_request, NULL);
+EXPORT_SYMBOL(RMF_OUT_UPDATE);
+
+struct req_msg_field RMF_OUT_UPDATE_REPLY =
+                       DEFINE_MSGFL("object_update_reply", 0, -1,
+                                   lustre_swab_object_update_reply, NULL);
+EXPORT_SYMBOL(RMF_OUT_UPDATE_REPLY);
+
+struct req_msg_field RMF_OUT_UPDATE_HEADER = DEFINE_MSGF("out_update_header", 0,
+                               -1, lustre_swab_out_update_header, NULL);
+EXPORT_SYMBOL(RMF_OUT_UPDATE_HEADER);
+
+struct req_msg_field RMF_OUT_UPDATE_BUF = DEFINE_MSGF("update_buf",
+                       RMF_F_STRUCT_ARRAY, sizeof(struct out_update_buffer),
+                       lustre_swab_out_update_buffer, NULL);
+EXPORT_SYMBOL(RMF_OUT_UPDATE_BUF);
+
+struct req_format RQF_OUT_UPDATE =
+       DEFINE_REQ_FMT0("OUT_UPDATE", mds_update_client,
+                       mds_update_server);
+EXPORT_SYMBOL(RQF_OUT_UPDATE);
+
 int req_check_sepol(struct req_capsule *pill)
 {
        int rc = 0;
-#ifdef HAVE_SERVER_SUPPORT
        struct obd_export *export;
        struct lu_nodemap *nm = NULL;
        const char *sepol = NULL;
@@ -2614,8 +2695,8 @@ nm:
 
        if (!IS_ERR_OR_NULL(nm))
                nodemap_putref(nm);
-#endif
 
        return rc;
 }
 EXPORT_SYMBOL(req_check_sepol);
+#endif