Whamcloud - gitweb
LU-4931 ladvise: Add feature of giving file access advices 29/10029/52
authorLi Xi <lixi@ddn.com>
Tue, 22 Mar 2016 00:12:55 +0000 (08:12 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sun, 17 Apr 2016 20:51:32 +0000 (20:51 +0000)
The fadvise() system call provided by Linux kernel enables
applications to give advices or hints about how a file will be
accessed. However, It is only a client side mechanism which is
not enough for distributed file systems like Lustre, because in
order to tune system-wide cache or read-ahead policies, servers
need to understand the advices too.

This patch adds a new feature named ladvise which provides new
APIs and utils to give advices about the access pattern of Lustre
files with the purpose of performance improvement. It is similar
to Linux fadvise() system call, except it forwards the advices
directly from Lustre client to server. The server side codes will
apply appropriate read-ahead and caching techniques for the
corresponding files.

A typical workload for ladvise is e.g. a bunch of different
clients are doing small random reads of a file, so prefetching
pages into OSS cache with big linear reads before the random IO
is a net benefit. Fetching all that data into each client cache
with fadvise() may not be, due to much more data being sent to
the client.

Signed-off-by: Li Xi <lixi@ddn.com>
Change-Id: I6de14ed87199949963360d393897ff79826c9819
Reviewed-on: http://review.whamcloud.com/10029
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
35 files changed:
lustre/contrib/wireshark/packet-lustre.c
lustre/doc/Makefile.am
lustre/doc/lfs-ladvise.1 [new file with mode: 0644]
lustre/doc/llapi_ladvise.3 [new file with mode: 0644]
lustre/include/cl_object.h
lustre/include/dt_object.h
lustre/include/lustre/lustre_idl.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre/lustreapi.h
lustre/include/lustre_req_layout.h
lustre/include/lustre_swab.h
lustre/include/obd_support.h
lustre/llite/file.c
lustre/llite/vvp_io.c
lustre/lov/lov_io.c
lustre/obdclass/cl_io.c
lustre/ofd/ofd_dev.c
lustre/osc/osc_cl_internal.h
lustre/osc/osc_dev.c
lustre/osc/osc_internal.h
lustre/osc/osc_io.c
lustre/osc/osc_request.c
lustre/osd-ldiskfs/osd_io.c
lustre/osd-zfs/osd_io.c
lustre/ptlrpc/layout.c
lustre/ptlrpc/lproc_ptlrpc.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/wiretest.c
lustre/utils/Makefile.am
lustre/utils/lfs.c
lustre/utils/liblustreapi_ladvise.c [new file with mode: 0644]
lustre/utils/lustreapi_internal.h
lustre/utils/req-layout.c
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index cf41609..27640f6 100644 (file)
@@ -181,6 +181,7 @@ typedef enum {
   OST_QUOTACHECK = 18,
   OST_QUOTACTL   = 19,
   OST_QUOTA_ADJUST_QUNIT = 20,
+  OST_LADVISE = 21,
   OST_LAST_OPC
 } ost_cmd_t ;
 
@@ -1022,6 +1023,11 @@ static int hf_lustre_ldlm_intent_opc_pin      = -1;
 static int hf_lustre_llog_hdr_llh_flag_zap_when_empty = -1;
 static int hf_lustre_llog_hdr_llh_flag_is_cat = -1;
 static int hf_lustre_llog_hdr_llh_flag_is_play = -1;
+static int hf_lustre_lu_ladvise = -1;
+static int hf_lustre_lu_ladvise_lla_start = -1;
+static int hf_lustre_lu_ladvise_lla_end = -1;
+static int hf_lustre_lu_ladvise_lla_advice = -1;
+static int hf_lustre_lu_ladvise_lla_padding = -1;
 /* --------------------------------------------------------------------*/
 
 
@@ -1145,7 +1151,9 @@ const value_string lustre_op_codes[] = {
   {17 , "OST_SET_INFO"},
   {18 , "OST_QUOTACHECK"},
   {19 , "OST_QUOTACTL"},
-  {20 , "OST_LAST_OPC"},
+  {20 , "OST_QUOTA_ADJUST_QUNIT"},
+  {21 , "OST_LADVISE"},
+  {22 , "OST_LAST_OPC"},
   /*MDS Opcodes*/
   {33 , "MDS_GETATTR"},
   {34 , "MDS_GETATTR_NAME"},
@@ -8381,6 +8389,83 @@ lustre_dissect_generic_connect(tvbuff_t *tvb _U_, int offset _U_, packet_info *p
   return offset;
 }
 
+int
+lustre_dissect_struct_capa(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_,
+                          proto_tree *parent_tree _U_, int hf_index _U_, guint32 buf_num)
+{
+  proto_item *item = NULL;
+  proto_tree *tree = NULL;
+  int old_offset;
+  int data_len;
+
+  old_offset=offset;
+
+  data_len = LUSTRE_BUFFER_LEN(buf_num);
+  if (data_len == 0)
+    return offset;
+
+  if (parent_tree) {
+    item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);
+    tree = proto_item_add_subtree(item, ett_lustre_capa);
+  }
+
+  offset=lustre_dissect_struct_lu_fid(tvb,offset,pinfo,tree,hf_lustre_capa_fid);
+
+  offset=lustre_dissect_element_capa_opc(tvb,offset,pinfo,tree);
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_capa_uid);
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_capa_gid);
+
+  offset=lustre_dissect_element_capa_flags(tvb,offset,pinfo,tree);
+
+  offset=dissect_uint32(tvb,offset,pinfo,tree,hf_lustre_capa_keyid);
+
+  offset=dissect_uint32(tvb,offset,pinfo,tree,hf_lustre_capa_timeout);
+
+  offset=dissect_uint32(tvb,offset,pinfo,tree,hf_lustre_capa_expiry);
+
+  offset=lustre_dissect_struct_hmac(tvb,offset,pinfo,tree, hf_lustre_capa_hmac, 64);
+
+  if (item)
+    proto_item_set_len(item, offset-old_offset);
+  return offset;
+}
+
+
+int
+lustre_dissect_struct_lu_ladvise(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_,
+                                proto_tree *parent_tree _U_, int hf_index _U_, guint32 buf_num)
+{
+  proto_item *item = NULL;
+  proto_tree *tree = NULL;
+  int old_offset;
+  int data_len;
+
+  old_offset=offset;
+
+  data_len = LUSTRE_BUFFER_LEN(buf_num);
+  if (data_len == 0)
+    return offset;
+
+  if (parent_tree) {
+    item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE);
+    tree = proto_item_add_subtree(item, ett_lustre_ladvise);
+  }
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_lu_ladvise_lla_start);
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_lu_ladvise_lla_end);
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_lu_ladvise_lla_advice);
+
+  offset=dissect_uint64(tvb,offset,pinfo,tree,hf_lustre_lu_ladvise_lla_padding);
+
+  if (item)
+    proto_item_set_len(item, offset-old_offset);
+  return offset;
+}
+
 static int
 lustre_ost_opcode_process(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree * tree _U_, guint32 opc _U_, guint32 pb_type)
 {
@@ -8486,6 +8571,14 @@ lustre_ost_opcode_process(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo
     case OST_QUOTA_ADJUST_QUNIT:
       /* [quota_adjust_qunit] in both case ? */
       offset=lustre_dissect_struct_quota_adjust_qunit(tvb, offset, pinfo, tree, hf_lustre_quota_adjust_qunit) ;
+    case OST_LADVISE:
+      /*[ost_body] in both case */
+      offset=lustre_dissect_struct_ost_body(tvb, offset, pinfo, tree, hf_lustre_ost_body) ;
+      if (pb_type == PTL_RPC_MSG_REQUEST) {
+         offset=lustre_dissect_struct_capa(tvb, offset, pinfo, tree, hf_lustre_capa, LUSTRE_REQ_REC_OFF+1);
+         offset=lustre_dissect_struct_lu_ladvise(tvb, offset, pinfo, tree, hf_lustre_lu_ladvise, LUSTRE_REQ_REC_OFF+2);
+      }
+      break;
   };
   return offset;
 }
@@ -11034,6 +11127,7 @@ void proto_register_dcerpc_lustre(void)
     &ett_lustre_mdt_ioepoch,
     &ett_lustre_capa,
     &ett_lustre_acl,
+    &ett_lustre_ladvise,
        };
 
   proto_lustre = proto_register_protocol("Lustre", "lustre", "lustre");
index 7bf1423..bd5de6c 100644 (file)
@@ -58,7 +58,7 @@ MANFILES = lustre.7 lfs.1 mount.lustre.8 lctl.8 lnetctl.8 \
        llapi_hsm_copytool_recv.3 llapi_hsm_action_end.3 \
        llapi_hsm_action_progress.3 llapi_hsm_action_get_dfid.3 \
        llapi_hsm_action_get_fd.3 lustreapi.7 llapi_hsm_action_begin.3 \
-       llapi_hsm_copytool_register.3
+       llapi_hsm_copytool_register.3 lfs-ladvise.1 llapi_ladvise.3
 
 SERVER_MANFILES = mkfs.lustre.8 tunefs.lustre.8
 
diff --git a/lustre/doc/lfs-ladvise.1 b/lustre/doc/lfs-ladvise.1
new file mode 100644 (file)
index 0000000..e0d5927
--- /dev/null
@@ -0,0 +1,58 @@
+.TH LFS-LADVISE 1 2015-11-30 "Lustre" "Lustre Utilities"
+.SH NAME
+lfs ladvise \- give file access advices or hints to server.
+.SH SYNOPSIS
+.br
+.B lfs ladvise [--advice|-a ADVICE ] [--background|-b]
+        \fB[--start|-s START[kMGT]]
+        \fB{[--end|-e END[kMGT]] | [--length|-l LENGTH[kMGT]]}
+        \fB<FILE> ...\fR
+.br
+.SH DESCRIPTION
+Give file access advices or hints to Lustre server side, usually OSS. This lfs
+utility is simlar to Linux fadvise() system call, except it can forward the
+advices from Lustre clients to servers.
+.SH OPTIONS
+.TP
+\fB\-a\fR, \fB\-\-advice\fR=\fIADVICE\fR
+Give advice or hint of type \fIADVICE\fR.
+.TP
+\fB\-b\fR, \fB\-\-background
+Enable the advices to be sent and handled asynchronously.
+.TP
+\fB\-s\fR, \fB\-\-start\fR=\fISTART_OFFSET\fR
+File range starts from \fISTART_OFFSET\fR.
+.TP
+\fB\-e\fR, \fB\-\-end\fR=\fIEND_OFFSET\fR
+File range ends at (not including) \fIEND_OFFSET\fR.
+This option may not be specified at the same time as the -l option.
+.TP
+\fB\-l\fR, \fB\-\-length\fR=\fILENGTH\fR
+File range has length of \fILENGTH\fR. This option may not be specified at the
+same time as the -e option.
+.SH NOTE
+.PP
+Typically, the "lfs ladvise" forwards the advice to Lustre servers without
+guaranteeing what and when servers will react to the advice. Actions may or
+may not triggered when the advices are recieved, depending on the type of the
+advice as well as the real-time decision of the affected server-side
+components.
+
+A typical usage of ladvise is to enable applications and users with external
+knowledge to intervene in server-side cache management. For example, if a
+bunch of different clients are doing small random reads of a file, prefetching
+pages into OSS cache with big linear reads before the random IO is a net
+benefit. Fetching all that data into each client cache with fadvise() may not
+be, due to much more data being sent to the client.
+
+The main difference between Linux fadvise() system call and ladvise is that
+fadvise() is only a client side mechanism that does not pass the advice to the
+filesystem, while ladvise can send advices or hints to Lustre server sides.
+
+.SH AVAILABILITY
+The lfs ladvise command is part of the Lustre filesystem.
+.SH SEE ALSO
+.BR lfs (1),
+.BR fadvise (2),
+.BR llapi_ladvise (3),
+.BR lustre (7)
diff --git a/lustre/doc/llapi_ladvise.3 b/lustre/doc/llapi_ladvise.3
new file mode 100644 (file)
index 0000000..fc3f508
--- /dev/null
@@ -0,0 +1,69 @@
+.TH llapi_ladvise 3 "2015 Dec 15" "Lustre User API"
+.SH NAME
+llapi_ladvise \- give IO advices/hints on a Lustre file to the server
+.SH SYNOPSIS
+.nf
+.B #include <lustre/lustreapi.h>
+.sp
+.BI "int llapi_ladvise(int " fd ", unsigned long long " flags ", int " num_advise ", struct lu_ladvise *" ladvise ");"
+.sp
+.fi
+.SH DESCRIPTION
+.LP
+.B llapi_ladvise()
+gives advices to a file specified by the file descriptor
+.IR fd .
+.IR ladvise
+points to an array that contains the information of the advices. The number
+of advices is
+.IR num_advise ,
+which should be smaller than
+.B MAX_NUM_LADVISE.
+Each of these advises is given in
+.I lu_ladvise
+structure, which contains the following fields:
+.PP
+.in +4n
+.nf
+struct lu_ladvise {
+    __u64 lla_advice;  /* Advice type */
+    __u64 lla_start;   /* Start offset of file */
+    __u64 lla_end;     /* End offset of file(not included) */
+    __u64 lla_padding; /* Not used yet */
+};
+.fi
+.in
+.LP
+In addition, zero or more flags can be
+.RI bitwise-or 'd
+in
+.IR flags .
+The full list of file creation flags and file status flags is as follows:
+.TP
+.B LF_ASYNC
+Client return to userspace immediately after submitting ladvise RPCs, leaving
+server threads to handle the advices asynchronously.
+.PP
+.SH RETURN VALUES
+.PP
+.B llapi_ladvise()
+return 0 on success, or -1 if an error occurred (in which case, errno is set
+appropriately).
+.SH ERRORS
+.TP 15
+.SM ENOMEM
+Insufficient memory to complete operation.
+.TP
+.SM EINVAL
+One or more invalid arguments are given.
+.TP
+.SM EFAULT
+memory region pointed by
+.I ladvise
+is not properly mapped.
+.TP
+.SM ENOTSUPP
+Advice type is not supported.
+.SH "SEE ALSO"
+.BR lfs-ladvise (1),
+.BR liblustreapi (7)
index ba1d5f3..64bc6bf 100644 (file)
@@ -1395,6 +1395,11 @@ enum cl_io_type {
          * cl_io_loop() is never called for it.
          */
         CIT_MISC,
+       /**
+        * ladvise handling
+        * To give advice about access of a file
+        */
+       CIT_LADVISE,
         CIT_OP_NR
 };
 
@@ -1727,7 +1732,6 @@ struct cl_io_rw_common {
         int         crw_nonblock;
 };
 
-
 /**
  * State for io.
  *
@@ -1799,6 +1803,14 @@ struct cl_io {
                        /* how many pages were written/discarded */
                        unsigned int       fi_nr_written;
                } ci_fsync;
+               struct cl_ladvise_io {
+                       __u64                    li_start;
+                       __u64                    li_end;
+                       /** file system level fid */
+                       struct lu_fid           *li_fid;
+                       enum lu_ladvise_type     li_advice;
+                       __u64                    li_flags;
+               } ci_ladvise;
         } u;
         struct cl_2queue     ci_queue;
         size_t               ci_nob;
index a37e6c1..c69674f 100644 (file)
@@ -1318,6 +1318,27 @@ struct dt_body_operations {
                           __u64 start,
                           __u64 end,
                           struct thandle *th);
+       /**
+        * Give advices on specified region in an object.
+        *
+        * This method is used to give advices about access pattern on an
+        * given region of the object. The disk filesystem understands
+        * the advices and tunes cache/read-ahead policies.
+        *
+        * \param[in] env       execution environment for this thread
+        * \param[in] dt        object
+        * \param[in] start     the start of the region affected
+        * \param[in] end       the end of the region affected
+        * \param[in] advice    advice type
+        *
+        * \retval 0            on success
+        * \retval negative     negated errno on error
+        */
+       int   (*dbo_ladvise)(const struct lu_env *env,
+                            struct dt_object *dt,
+                            __u64 start,
+                            __u64 end,
+                            enum lu_ladvise_type advice);
 };
 
 /**
@@ -2393,6 +2414,15 @@ static inline int dt_punch(const struct lu_env *env, struct dt_object *dt,
        return dt->do_body_ops->dbo_punch(env, dt, start, end, th);
 }
 
+static inline int dt_ladvise(const struct lu_env *env, struct dt_object *dt,
+                            __u64 start, __u64 end, int advice)
+{
+       LASSERT(dt);
+       LASSERT(dt->do_body_ops);
+       LASSERT(dt->do_body_ops->dbo_ladvise);
+       return dt->do_body_ops->dbo_ladvise(env, dt, start, end, advice);
+}
+
 static inline int dt_fiemap_get(const struct lu_env *env, struct dt_object *d,
                                struct fiemap *fm)
 {
index e51aae3..9bff175 100644 (file)
@@ -1415,7 +1415,8 @@ typedef enum {
        OST_QUOTACHECK = 18, /* not used since 2.4 */
         OST_QUOTACTL   = 19,
        OST_QUOTA_ADJUST_QUNIT = 20, /* not used since 2.4 */
-        OST_LAST_OPC
+       OST_LADVISE    = 21,
+       OST_LAST_OPC /* must be < 33 to avoid MDS_GETATTR */
 } ost_cmd_t;
 #define OST_FIRST_OPC  OST_REPLY
 
index ad5c17e..b6605b2 100644 (file)
@@ -294,6 +294,7 @@ struct ll_futimes_3 {
 #define LL_IOC_MIGRATE                 _IOR('f', 247, int)
 #define LL_IOC_FID2MDTIDX              _IOWR('f', 248, struct lu_fid)
 #define LL_IOC_GETPARENT               _IOWR('f', 249, struct getparent)
+#define LL_IOC_LADVISE                 _IOR('f', 250, struct lu_ladvise)
 
 /* Lease types for use as arg and return of LL_IOC_{GET,SET}_LEASE ioctl. */
 enum ll_lease_type {
@@ -1389,6 +1390,38 @@ struct llapi_json_item_list {
        struct llapi_json_item  *ljil_items;
 };
 
+enum lu_ladvise_type {
+       LU_LADVISE_INVALID      = 0,
+};
+
+#define LU_LADVISE_NAMES {                                             \
+}
+
+struct lu_ladvise {
+       __u64 lla_advice;
+       __u64 lla_start;
+       __u64 lla_end;
+       __u64 lla_padding;
+};
+
+enum ladvise_flag {
+       LF_ASYNC        = 0x00000001,
+};
+
+#define LADVISE_MAGIC 0x1ADF1CE0
+#define LF_MASK LF_ASYNC
+
+struct ladvise_hdr {
+       __u32                   lah_magic;      /* LADVISE_MAGIC */
+       __u32                   lah_count;      /* number of advices */
+       __u64                   lah_flags;      /* from enum ladvise_flag */
+       __u64                   lah_padding1;   /* unused */
+       __u64                   lah_padding2;   /* unused */
+       struct lu_ladvise       lah_advise[0];
+};
+
+#define LAH_COUNT_MAX  (1024)
+
 /** @} lustreuser */
 
 #endif /* _LUSTRE_USER_H */
index 4164ce2..340bec5 100644 (file)
@@ -46,6 +46,8 @@
 #include <stdint.h>
 #include <lustre/lustre_user.h>
 
+#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+
 extern bool liblustreapi_initialized;
 
 
@@ -402,6 +404,9 @@ extern int llapi_lease_put(int fd);
 int llapi_group_lock(int fd, int gid);
 int llapi_group_unlock(int fd, int gid);
 
+/* Ladvise */
+int llapi_ladvise(int fd, unsigned long long flags, int num_advise,
+                 struct lu_ladvise *ladvise);
 /** @} llapi */
 
 /* llapi_layout user interface */
index 8130dc0..5a124b4 100644 (file)
@@ -213,6 +213,7 @@ extern struct req_format RQF_OST_GET_INFO_LAST_ID;
 extern struct req_format RQF_OST_GET_INFO_LAST_FID;
 extern struct req_format RQF_OST_SET_INFO_LAST_FID;
 extern struct req_format RQF_OST_GET_INFO_FIEMAP;
+extern struct req_format RQF_OST_LADVISE;
 
 /* LDLM req_format */
 extern struct req_format RQF_LDLM_ENQUEUE;
@@ -341,6 +342,9 @@ extern struct req_msg_field RMF_OUT_UPDATE_BUF;
 /* LFSCK format */
 extern struct req_msg_field RMF_LFSCK_REQUEST;
 extern struct req_msg_field RMF_LFSCK_REPLY;
+
+extern struct req_msg_field RMF_OST_LADVISE_HDR;
+extern struct req_msg_field RMF_OST_LADVISE;
 /** @} req_layout */
 
 #endif /* _LUSTRE_REQ_LAYOUT_H__ */
index 6de1241..c63d483 100644 (file)
@@ -116,5 +116,7 @@ void lustre_swab_object_update_reply(struct object_update_reply *our);
 void lustre_swab_swap_layouts(struct mdc_swap_layouts *msl);
 void lustre_swab_close_data(struct close_data *data);
 void lustre_swab_lmv_user_md(struct lmv_user_md *lum);
+void lustre_swab_ladvise(struct lu_ladvise *ladvise);
+void lustre_swab_ladvise_hdr(struct ladvise_hdr *ladvise_hdr);
 
 #endif
index 76bd434..ce28659 100644 (file)
@@ -323,6 +323,7 @@ extern char obd_jobid_var[];
 #define OBD_FAIL_OST_SET_INFO_NET        0x232
 #define OBD_FAIL_OST_NODESTROY          0x233
 #define OBD_FAIL_OST_READ_SIZE          0x234
+#define OBD_FAIL_OST_LADVISE_NET        0x235
 
 #define OBD_FAIL_LDLM                    0x300
 #define OBD_FAIL_LDLM_NAMESPACE_NEW      0x301
index d9aaebb..ff1dd64 100644 (file)
@@ -2204,6 +2204,55 @@ static int ll_file_futimes_3(struct file *file, const struct ll_futimes_3 *lfu)
        RETURN(rc);
 }
 
+/*
+ * Give file access advices
+ *
+ * The ladvise interface is similar to Linux fadvise() system call, except it
+ * forwards the advices directly from Lustre client to server. The server side
+ * codes will apply appropriate read-ahead and caching techniques for the
+ * corresponding files.
+ *
+ * A typical workload for ladvise is e.g. a bunch of different clients are
+ * doing small random reads of a file, so prefetching pages into OSS cache
+ * with big linear reads before the random IO is a net benefit. Fetching
+ * all that data into each client cache with fadvise() may not be, due to
+ * much more data being sent to the client.
+ */
+static int ll_ladvise(struct inode *inode, struct file *file, __u64 flags,
+                     struct lu_ladvise *ladvise)
+{
+       struct cl_env_nest nest;
+       struct lu_env *env;
+       struct cl_io *io;
+       struct cl_ladvise_io *lio;
+       int rc;
+       ENTRY;
+
+       env = cl_env_nested_get(&nest);
+       if (IS_ERR(env))
+               RETURN(PTR_ERR(env));
+
+       io = vvp_env_thread_io(env);
+       io->ci_obj = ll_i2info(inode)->lli_clob;
+
+       /* initialize parameters for ladvise */
+       lio = &io->u.ci_ladvise;
+       lio->li_start = ladvise->lla_start;
+       lio->li_end = ladvise->lla_end;
+       lio->li_fid = ll_inode2fid(inode);
+       lio->li_advice = ladvise->lla_advice;
+       lio->li_flags = flags;
+
+       if (cl_io_init(env, io, CIT_LADVISE, io->ci_obj) == 0)
+               rc = cl_io_loop(env, io);
+       else
+               rc = io->ci_result;
+
+       cl_io_fini(env, io);
+       cl_env_nested_put(&nest, env);
+       RETURN(rc);
+}
+
 static long
 ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -2545,6 +2594,56 @@ out:
 
                RETURN(ll_file_futimes_3(file, &lfu));
        }
+       case LL_IOC_LADVISE: {
+               struct ladvise_hdr *ladvise_hdr;
+               int i;
+               int num_advise;
+               int alloc_size = sizeof(*ladvise_hdr);
+
+               rc = 0;
+               OBD_ALLOC_PTR(ladvise_hdr);
+               if (ladvise_hdr == NULL)
+                       RETURN(-ENOMEM);
+
+               if (copy_from_user(ladvise_hdr,
+                                  (const struct ladvise_hdr __user *)arg,
+                                  alloc_size))
+                       GOTO(out_ladvise, rc = -EFAULT);
+
+               if (ladvise_hdr->lah_magic != LADVISE_MAGIC ||
+                   ladvise_hdr->lah_count < 1)
+                       GOTO(out_ladvise, rc = -EINVAL);
+
+               num_advise = ladvise_hdr->lah_count;
+               if (num_advise >= LAH_COUNT_MAX)
+                       GOTO(out_ladvise, rc = -EFBIG);
+
+               OBD_FREE_PTR(ladvise_hdr);
+               alloc_size = offsetof(typeof(*ladvise_hdr),
+                                     lah_advise[num_advise]);
+               OBD_ALLOC(ladvise_hdr, alloc_size);
+               if (ladvise_hdr == NULL)
+                       RETURN(-ENOMEM);
+
+               /*
+                * TODO: submit multiple advices to one server in a single RPC
+                */
+               if (copy_from_user(ladvise_hdr,
+                                  (const struct ladvise_hdr __user *)arg,
+                                  alloc_size))
+                       GOTO(out_ladvise, rc = -EFAULT);
+
+               for (i = 0; i < num_advise; i++) {
+                       rc = ll_ladvise(inode, file, ladvise_hdr->lah_flags,
+                                       &ladvise_hdr->lah_advise[i]);
+                       if (rc)
+                               break;
+               }
+
+out_ladvise:
+               OBD_FREE(ladvise_hdr, alloc_size);
+               RETURN(rc);
+       }
        default: {
                int err;
 
index cbc4997..daf75ac 100644 (file)
@@ -1443,7 +1443,10 @@ static const struct cl_io_operations vvp_io_ops = {
                },
                [CIT_MISC] = {
                        .cio_fini       = vvp_io_fini
-               }
+               },
+               [CIT_LADVISE] = {
+                       .cio_fini       = vvp_io_fini
+               },
        },
        .cio_read_ahead = vvp_io_read_ahead
 };
index 7626987..ebf45ba 100644 (file)
@@ -130,17 +130,25 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio,
        case CIT_READ:
        case CIT_WRITE: {
                io->u.ci_wr.wr_sync = cl_io_is_sync_write(parent);
-                if (cl_io_is_append(parent)) {
-                        io->u.ci_wr.wr_append = 1;
-                } else {
-                        io->u.ci_rw.crw_pos = start;
-                        io->u.ci_rw.crw_count = end - start;
-                }
-                break;
-        }
-        default:
-                break;
-        }
+               if (cl_io_is_append(parent)) {
+                       io->u.ci_wr.wr_append = 1;
+               } else {
+                       io->u.ci_rw.crw_pos = start;
+                       io->u.ci_rw.crw_count = end - start;
+               }
+               break;
+       }
+       case CIT_LADVISE: {
+               io->u.ci_ladvise.li_start = start;
+               io->u.ci_ladvise.li_end = end;
+               io->u.ci_ladvise.li_fid = parent->u.ci_ladvise.li_fid;
+               io->u.ci_ladvise.li_advice = parent->u.ci_ladvise.li_advice;
+               io->u.ci_ladvise.li_flags = parent->u.ci_ladvise.li_flags;
+               break;
+       }
+       default:
+               break;
+       }
 }
 
 static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
@@ -372,6 +380,12 @@ static int lov_io_slice_init(struct lov_io *lio,
                break;
        }
 
+       case CIT_LADVISE: {
+               lio->lis_pos = io->u.ci_ladvise.li_start;
+               lio->lis_endpos = io->u.ci_ladvise.li_end;
+               break;
+       }
+
         case CIT_MISC:
                 lio->lis_pos = 0;
                 lio->lis_endpos = OBD_OBJECT_EOF;
@@ -926,6 +940,15 @@ static const struct cl_io_operations lov_io_ops = {
                        .cio_start     = lov_io_start,
                        .cio_end       = lov_io_fsync_end
                },
+               [CIT_LADVISE] = {
+                       .cio_fini      = lov_io_fini,
+                       .cio_iter_init = lov_io_iter_init,
+                       .cio_iter_fini = lov_io_iter_fini,
+                       .cio_lock      = lov_io_lock,
+                       .cio_unlock    = lov_io_unlock,
+                       .cio_start     = lov_io_start,
+                       .cio_end       = lov_io_end
+               },
                [CIT_MISC] = {
                        .cio_fini      = lov_io_fini
                }
@@ -1005,6 +1028,9 @@ static const struct cl_io_operations lov_empty_io_ops = {
                [CIT_FSYNC] = {
                        .cio_fini      = lov_empty_io_fini
                },
+               [CIT_LADVISE] = {
+                       .cio_fini   = lov_empty_io_fini
+               },
                [CIT_MISC] = {
                        .cio_fini      = lov_empty_io_fini
                }
@@ -1052,6 +1078,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
                result = 0;
                break;
        case CIT_FSYNC:
+       case CIT_LADVISE:
        case CIT_SETATTR:
        case CIT_DATA_VERSION:
                result = +1;
@@ -1090,6 +1117,7 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
                LASSERTF(0, "invalid type %d\n", io->ci_type);
        case CIT_MISC:
        case CIT_FSYNC:
+       case CIT_LADVISE:
        case CIT_DATA_VERSION:
                result = 1;
                break;
index e2c1a4e..2da5856 100644 (file)
@@ -143,6 +143,8 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io)
                LASSERT(ergo(io->ci_ignore_layout || !io->ci_verify_layout,
                                !io->ci_need_restart));
                break;
+       case CIT_LADVISE:
+               break;
        default:
                LBUG();
        }
index d48472b..e95052b 100644 (file)
@@ -2106,6 +2106,97 @@ out:
 }
 
 /**
+ * OFD request handler for OST_LADVISE RPC.
+ *
+ * Tune cache or perfetch policies according to advices.
+ *
+ * \param[in] tsi      target session environment for this request
+ *
+ * \retval             0 if successful
+ * \retval             negative errno on error
+ */
+static int ofd_ladvise_hdl(struct tgt_session_info *tsi)
+{
+       struct ptlrpc_request   *req = tgt_ses_req(tsi);
+       struct obd_export       *exp = tsi->tsi_exp;
+       struct ofd_device       *ofd = ofd_exp(exp);
+       struct ost_body         *body, *repbody;
+       struct ofd_thread_info  *info;
+       struct ofd_object       *fo;
+       const struct lu_env     *env = req->rq_svc_thread->t_env;
+       int                      rc = 0;
+       struct lu_ladvise       *ladvise;
+       int                      num_advise;
+       struct ladvise_hdr      *ladvise_hdr;
+       int                      i;
+       ENTRY;
+
+       body = tsi->tsi_ost_body;
+
+       if ((body->oa.o_valid & OBD_MD_FLID) != OBD_MD_FLID)
+               RETURN(err_serious(-EPROTO));
+
+       ladvise_hdr = req_capsule_client_get(tsi->tsi_pill,
+                                            &RMF_OST_LADVISE_HDR);
+       if (ladvise_hdr == NULL)
+               RETURN(err_serious(-EPROTO));
+
+       if (ladvise_hdr->lah_magic != LADVISE_MAGIC ||
+           ladvise_hdr->lah_count < 1)
+               RETURN(err_serious(-EPROTO));
+
+       if ((ladvise_hdr->lah_flags & (~LF_MASK)) != 0)
+               RETURN(err_serious(-EPROTO));
+
+       ladvise = req_capsule_client_get(tsi->tsi_pill, &RMF_OST_LADVISE);
+       if (ladvise == NULL)
+               RETURN(err_serious(-EPROTO));
+
+       num_advise = req_capsule_get_size(&req->rq_pill,
+                                         &RMF_OST_LADVISE, RCL_CLIENT) /
+                    sizeof(*ladvise);
+       if (num_advise < ladvise_hdr->lah_count)
+               RETURN(err_serious(-EPROTO));
+
+       repbody = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY);
+       repbody->oa = body->oa;
+
+       info = ofd_info_init(env, exp);
+
+       rc = ostid_to_fid(&info->fti_fid, &body->oa.o_oi,
+                         ofd->ofd_lut.lut_lsd.lsd_osd_index);
+       if (rc != 0)
+               RETURN(rc);
+
+       fo = ofd_object_find(env, ofd, &info->fti_fid);
+       if (IS_ERR(fo)) {
+               rc = PTR_ERR(fo);
+               RETURN(rc);
+       }
+       LASSERT(fo != NULL);
+
+       for (i = 0; i < num_advise; i++, ladvise++) {
+               if (ladvise->lla_end <= ladvise->lla_start) {
+                       rc = err_serious(-EPROTO);
+                       break;
+               }
+
+               /* Handle different advice types */
+               switch (ladvise->lla_advice) {
+               default:
+                       rc = -ENOTSUPP;
+                       break;
+               }
+               if (rc != 0)
+                       break;
+       }
+
+       ofd_object_put(env, fo);
+       req->rq_status = rc;
+       RETURN(rc);
+}
+
+/**
  * OFD request handler for OST_QUOTACTL RPC.
  *
  * This is part of request processing to validate incoming request fields,
@@ -2624,6 +2715,7 @@ TGT_OST_HDL_HP(HABEO_CORPUS| HABEO_REFERO | MUTABOR,
                                                        ofd_hp_punch),
 TGT_OST_HDL(HABEO_CORPUS| HABEO_REFERO,        OST_SYNC,       ofd_sync_hdl),
 TGT_OST_HDL(0          | HABEO_REFERO, OST_QUOTACTL,   ofd_quotactl),
+TGT_OST_HDL(HABEO_CORPUS | HABEO_REFERO, OST_LADVISE,  ofd_ladvise_hdl),
 };
 
 static struct tgt_opc_slice ofd_common_slice[] = {
index e3ef013..dbfad66 100644 (file)
@@ -111,6 +111,7 @@ struct osc_thread_info {
        pgoff_t                 oti_fn_index; /* first non-overlapped index */
        struct cl_sync_io       oti_anchor;
        struct cl_req_attr      oti_req_attr;
+       struct lu_buf           oti_ladvise_buf;
 };
 
 struct osc_object {
index b511a22..1dd13de 100644 (file)
@@ -123,8 +123,10 @@ static void *osc_key_init(const struct lu_context *ctx,
 static void osc_key_fini(const struct lu_context *ctx,
                          struct lu_context_key *key, void *data)
 {
-        struct osc_thread_info *info = data;
-        OBD_SLAB_FREE_PTR(info, osc_thread_kmem);
+       struct osc_thread_info *info = data;
+
+       lu_buf_free(&info->oti_ladvise_buf);
+       OBD_SLAB_FREE_PTR(info, osc_thread_kmem);
 }
 
 struct lu_context_key osc_key = {
index cef083f..c5f2a61 100644 (file)
@@ -129,7 +129,10 @@ int osc_punch_base(struct obd_export *exp, struct obdo *oa,
 int osc_sync_base(struct osc_object *obj, struct obdo *oa,
                  obd_enqueue_update_f upcall, void *cookie,
                  struct ptlrpc_request_set *rqset);
-
+int osc_ladvise_base(struct obd_export *exp, struct obdo *oa,
+                    struct ladvise_hdr *ladvise_hdr,
+                    obd_enqueue_update_f upcall, void *cookie,
+                    struct ptlrpc_request_set *rqset);
 int osc_process_config_base(struct obd_device *obd, struct lustre_cfg *cfg);
 int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
                  struct list_head *ext_list, int cmd);
index 69d4e06..b99db70 100644 (file)
@@ -838,6 +838,76 @@ static void osc_io_fsync_end(const struct lu_env *env,
        slice->cis_io->ci_result = result;
 }
 
+static int osc_io_ladvise_start(const struct lu_env *env,
+                               const struct cl_io_slice *slice)
+{
+       int                      result = 0;
+       struct cl_io            *io = slice->cis_io;
+       struct osc_io           *oio = cl2osc_io(env, slice);
+       struct cl_object        *obj = slice->cis_obj;
+       struct lov_oinfo        *loi = cl2osc(obj)->oo_oinfo;
+       struct cl_ladvise_io    *lio = &io->u.ci_ladvise;
+       struct obdo             *oa = &oio->oi_oa;
+       struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+       struct lu_ladvise       *ladvise;
+       struct ladvise_hdr      *ladvise_hdr;
+       int                      buf_size;
+       int                      num_advise = 1;
+       ENTRY;
+
+       /* TODO: add multiple ladvise support in CLIO */
+       buf_size = offsetof(typeof(*ladvise_hdr), lah_advise[num_advise]);
+       if (osc_env_info(env)->oti_ladvise_buf.lb_len < buf_size)
+               lu_buf_realloc(&osc_env_info(env)->oti_ladvise_buf, buf_size);
+
+       ladvise_hdr = osc_env_info(env)->oti_ladvise_buf.lb_buf;
+       if (ladvise_hdr == NULL)
+               RETURN(-ENOMEM);
+
+       memset(ladvise_hdr, 0, buf_size);
+       ladvise_hdr->lah_magic = LADVISE_MAGIC;
+       ladvise_hdr->lah_count = num_advise;
+       ladvise_hdr->lah_flags = lio->li_flags;
+
+       memset(oa, 0, sizeof(*oa));
+       oa->o_oi = loi->loi_oi;
+       oa->o_valid = OBD_MD_FLID;
+       obdo_set_parent_fid(oa, lio->li_fid);
+
+       ladvise = ladvise_hdr->lah_advise;
+       ladvise->lla_start = lio->li_start;
+       ladvise->lla_end = lio->li_end;
+       ladvise->lla_advice = lio->li_advice;
+
+       if (lio->li_flags & LF_ASYNC) {
+               result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
+                                         ladvise_hdr, NULL, NULL, NULL);
+       } else {
+               init_completion(&cbargs->opc_sync);
+               result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
+                                         ladvise_hdr, osc_async_upcall,
+                                         cbargs, PTLRPCD_SET);
+               cbargs->opc_rpc_sent = result == 0;
+       }
+       RETURN(result);
+}
+
+static void osc_io_ladvise_end(const struct lu_env *env,
+                              const struct cl_io_slice *slice)
+{
+       struct cl_io            *io = slice->cis_io;
+       struct osc_io           *oio = cl2osc_io(env, slice);
+       struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+       int                      result = 0;
+       struct cl_ladvise_io    *lio = &io->u.ci_ladvise;
+
+       if ((!(lio->li_flags & LF_ASYNC)) && cbargs->opc_rpc_sent) {
+               wait_for_completion(&cbargs->opc_sync);
+               result = cbargs->opc_rc;
+       }
+       slice->cis_io->ci_result = result;
+}
+
 static void osc_io_end(const struct lu_env *env,
                       const struct cl_io_slice *slice)
 {
@@ -886,6 +956,11 @@ static const struct cl_io_operations osc_io_ops = {
                        .cio_end    = osc_io_fsync_end,
                        .cio_fini   = osc_io_fini
                },
+               [CIT_LADVISE] = {
+                       .cio_start  = osc_io_ladvise_start,
+                       .cio_end    = osc_io_ladvise_end,
+                       .cio_fini   = osc_io_fini
+               },
                [CIT_MISC] = {
                        .cio_fini   = osc_io_fini
                }
index 3655730..9b2a805 100644 (file)
@@ -91,6 +91,12 @@ struct osc_fsync_args {
        void                    *fa_cookie;
 };
 
+struct osc_ladvise_args {
+       struct obdo             *la_oa;
+       obd_enqueue_update_f     la_upcall;
+       void                    *la_cookie;
+};
+
 struct osc_enqueue_args {
        struct obd_export       *oa_exp;
        enum ldlm_type          oa_type;
@@ -269,6 +275,94 @@ int osc_setattr_async(struct obd_export *exp, struct obdo *oa,
        RETURN(0);
 }
 
+static int osc_ladvise_interpret(const struct lu_env *env,
+                                struct ptlrpc_request *req,
+                                void *arg, int rc)
+{
+       struct osc_ladvise_args *la = arg;
+       struct ost_body *body;
+       ENTRY;
+
+       if (rc != 0)
+               GOTO(out, rc);
+
+       body = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY);
+       if (body == NULL)
+               GOTO(out, rc = -EPROTO);
+
+       *la->la_oa = body->oa;
+out:
+       rc = la->la_upcall(la->la_cookie, rc);
+       RETURN(rc);
+}
+
+/**
+ * If rqset is NULL, do not wait for response. Upcall and cookie could also
+ * be NULL in this case
+ */
+int osc_ladvise_base(struct obd_export *exp, struct obdo *oa,
+                    struct ladvise_hdr *ladvise_hdr,
+                    obd_enqueue_update_f upcall, void *cookie,
+                    struct ptlrpc_request_set *rqset)
+{
+       struct ptlrpc_request   *req;
+       struct ost_body         *body;
+       struct osc_ladvise_args *la;
+       int                      rc;
+       struct lu_ladvise       *req_ladvise;
+       struct lu_ladvise       *ladvise = ladvise_hdr->lah_advise;
+       int                      num_advise = ladvise_hdr->lah_count;
+       struct ladvise_hdr      *req_ladvise_hdr;
+       ENTRY;
+
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_LADVISE);
+       if (req == NULL)
+               RETURN(-ENOMEM);
+
+       req_capsule_set_size(&req->rq_pill, &RMF_OST_LADVISE, RCL_CLIENT,
+                            num_advise * sizeof(*ladvise));
+       rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_LADVISE);
+       if (rc != 0) {
+               ptlrpc_request_free(req);
+               RETURN(rc);
+       }
+       req->rq_request_portal = OST_IO_PORTAL;
+       ptlrpc_at_set_req_timeout(req);
+
+       body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY);
+       LASSERT(body);
+       lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa,
+                            oa);
+
+       req_ladvise_hdr = req_capsule_client_get(&req->rq_pill,
+                                                &RMF_OST_LADVISE_HDR);
+       memcpy(req_ladvise_hdr, ladvise_hdr, sizeof(*ladvise_hdr));
+
+       req_ladvise = req_capsule_client_get(&req->rq_pill, &RMF_OST_LADVISE);
+       memcpy(req_ladvise, ladvise, sizeof(*ladvise) * num_advise);
+       ptlrpc_request_set_replen(req);
+
+       if (rqset == NULL) {
+               /* Do not wait for response. */
+               ptlrpcd_add_req(req);
+               RETURN(0);
+       }
+
+       req->rq_interpret_reply = osc_ladvise_interpret;
+       CLASSERT(sizeof(*la) <= sizeof(req->rq_async_args));
+       la = ptlrpc_req_async_args(req);
+       la->la_oa = oa;
+       la->la_upcall = upcall;
+       la->la_cookie = cookie;
+
+       if (rqset == PTLRPCD_SET)
+               ptlrpcd_add_req(req);
+       else
+               ptlrpc_set_add_req(rqset, req);
+
+       RETURN(0);
+}
+
 static int osc_create(const struct lu_env *env, struct obd_export *exp,
                      struct obdo *oa)
 {
index fb6316a..5ef77b2 100644 (file)
@@ -1919,6 +1919,21 @@ static int osd_fiemap_get(const struct lu_env *env, struct dt_object *dt,
        return rc;
 }
 
+static int osd_ladvise(const struct lu_env *env, struct dt_object *dt,
+                      __u64 start, __u64 end, enum lu_ladvise_type advice)
+{
+       int     rc;
+       ENTRY;
+
+       switch (advice) {
+       default:
+               rc = -ENOTSUPP;
+               break;
+       }
+
+       RETURN(rc);
+}
+
 /*
  * in some cases we may need declare methods for objects being created
  * e.g., when we create symlink
@@ -1928,17 +1943,18 @@ const struct dt_body_operations osd_body_ops_new = {
 };
 
 const struct dt_body_operations osd_body_ops = {
-        .dbo_read                 = osd_read,
-        .dbo_declare_write        = osd_declare_write,
-        .dbo_write                = osd_write,
-        .dbo_bufs_get             = osd_bufs_get,
-        .dbo_bufs_put             = osd_bufs_put,
-        .dbo_write_prep           = osd_write_prep,
-        .dbo_declare_write_commit = osd_declare_write_commit,
-        .dbo_write_commit         = osd_write_commit,
-        .dbo_read_prep            = osd_read_prep,
-        .dbo_declare_punch         = osd_declare_punch,
-        .dbo_punch                 = osd_punch,
-        .dbo_fiemap_get           = osd_fiemap_get,
+       .dbo_read                       = osd_read,
+       .dbo_declare_write              = osd_declare_write,
+       .dbo_write                      = osd_write,
+       .dbo_bufs_get                   = osd_bufs_get,
+       .dbo_bufs_put                   = osd_bufs_put,
+       .dbo_write_prep                 = osd_write_prep,
+       .dbo_declare_write_commit       = osd_declare_write_commit,
+       .dbo_write_commit               = osd_write_commit,
+       .dbo_read_prep                  = osd_read_prep,
+       .dbo_declare_punch              = osd_declare_punch,
+       .dbo_punch                      = osd_punch,
+       .dbo_fiemap_get                 = osd_fiemap_get,
+       .dbo_ladvise                    = osd_ladvise,
 };
 
index 8299128..a6b6cea 100644 (file)
@@ -906,6 +906,20 @@ static int osd_declare_punch(const struct lu_env *env, struct dt_object *dt,
                                 false));
 }
 
+static int osd_ladvise(const struct lu_env *env, struct dt_object *dt,
+                      __u64 start, __u64 end, enum lu_ladvise_type advice)
+{
+       int     rc;
+       ENTRY;
+
+       switch (advice) {
+       default:
+               rc = -ENOTSUPP;
+               break;
+       }
+
+       RETURN(rc);
+}
 
 struct dt_body_operations osd_body_ops = {
        .dbo_read                       = osd_read,
@@ -919,4 +933,5 @@ struct dt_body_operations osd_body_ops = {
        .dbo_read_prep                  = osd_read_prep,
        .dbo_declare_punch              = osd_declare_punch,
        .dbo_punch                      = osd_punch,
+       .dbo_ladvise                    = osd_ladvise,
 };
index 20cbf1e..8a4933d 100644 (file)
@@ -651,6 +651,13 @@ static const struct req_msg_field *ost_get_fiemap_client[] = {
         &RMF_FIEMAP_VAL
 };
 
+static const struct req_msg_field *ost_ladvise[] = {
+       &RMF_PTLRPC_BODY,
+       &RMF_OST_BODY,
+       &RMF_OST_LADVISE_HDR,
+       &RMF_OST_LADVISE,
+};
+
 static const struct req_msg_field *ost_get_fiemap_server[] = {
         &RMF_PTLRPC_BODY,
         &RMF_FIEMAP_VAL
@@ -772,12 +779,13 @@ static struct req_format *req_formats[] = {
         &RQF_OST_GET_INFO_LAST_ID,
        &RQF_OST_GET_INFO_LAST_FID,
        &RQF_OST_SET_INFO_LAST_FID,
-        &RQF_OST_GET_INFO_FIEMAP,
-        &RQF_LDLM_ENQUEUE,
-        &RQF_LDLM_ENQUEUE_LVB,
-        &RQF_LDLM_CONVERT,
-        &RQF_LDLM_CANCEL,
-        &RQF_LDLM_CALLBACK,
+       &RQF_OST_GET_INFO_FIEMAP,
+       &RQF_OST_LADVISE,
+       &RQF_LDLM_ENQUEUE,
+       &RQF_LDLM_ENQUEUE_LVB,
+       &RQF_LDLM_CONVERT,
+       &RQF_LDLM_CANCEL,
+       &RQF_LDLM_CALLBACK,
         &RQF_LDLM_CP_CALLBACK,
         &RQF_LDLM_BL_CALLBACK,
         &RQF_LDLM_GL_CALLBACK,
@@ -1202,6 +1210,18 @@ struct req_msg_field RMF_LFSCK_REPLY =
                    lustre_swab_lfsck_reply, NULL);
 EXPORT_SYMBOL(RMF_LFSCK_REPLY);
 
+struct req_msg_field RMF_OST_LADVISE_HDR =
+       DEFINE_MSGF("ladvise_request", 0,
+                   sizeof(struct ladvise_hdr),
+                   lustre_swab_ladvise_hdr, NULL);
+EXPORT_SYMBOL(RMF_OST_LADVISE_HDR);
+
+struct req_msg_field RMF_OST_LADVISE =
+       DEFINE_MSGF("ladvise_request", RMF_F_STRUCT_ARRAY,
+                   sizeof(struct lu_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);
@@ -1659,6 +1679,10 @@ struct req_format RQF_LFSCK_QUERY =
        DEFINE_REQ_FMT0("LFSCK_QUERY", obd_lfsck_request, obd_lfsck_reply);
 EXPORT_SYMBOL(RQF_LFSCK_QUERY);
 
+struct req_format RQF_OST_LADVISE =
+       DEFINE_REQ_FMT0("OST_LADVISE", ost_ladvise, ost_body_only);
+EXPORT_SYMBOL(RQF_OST_LADVISE);
+
 #if !defined(__REQ_LAYOUT_USER__)
 
 /* Convenience macro */
index 3cb05f5..255c9f5 100644 (file)
@@ -70,6 +70,7 @@ static struct ll_rpc_opcode {
         { OST_QUOTACHECK,   "ost_quotacheck" },
         { OST_QUOTACTL,     "ost_quotactl" },
         { OST_QUOTA_ADJUST_QUNIT, "ost_quota_adjust_qunit" },
+       { OST_LADVISE,      "ost_ladvise" },
         { MDS_GETATTR,      "mds_getattr" },
         { MDS_GETATTR_NAME, "mds_getattr_lock" },
         { MDS_CLOSE,        "mds_close" },
index 91c0e7e..dc7f535 100644 (file)
@@ -2639,3 +2639,22 @@ void lustre_swab_orphan_ent(struct lu_orphan_ent *ent)
        __swab32s(&ent->loe_rec.lor_gid);
 }
 EXPORT_SYMBOL(lustre_swab_orphan_ent);
+
+void lustre_swab_ladvise(struct lu_ladvise *ladvise)
+{
+       __swab64s(&ladvise->lla_start);
+       __swab64s(&ladvise->lla_end);
+       __swab64s(&ladvise->lla_advice);
+       CLASSERT(offsetof(typeof(*ladvise), lla_padding) != 0);
+}
+EXPORT_SYMBOL(lustre_swab_ladvise);
+
+void lustre_swab_ladvise_hdr(struct ladvise_hdr *ladvise_hdr)
+{
+       __swab32s(&ladvise_hdr->lah_magic);
+       __swab32s(&ladvise_hdr->lah_count);
+       __swab64s(&ladvise_hdr->lah_flags);
+       CLASSERT(offsetof(typeof(*ladvise_hdr), lah_padding1) != 0);
+       CLASSERT(offsetof(typeof(*ladvise_hdr), lah_padding2) != 0);
+}
+EXPORT_SYMBOL(lustre_swab_ladvise_hdr);
index e302e39..a8f52f8 100644 (file)
@@ -104,7 +104,9 @@ void lustre_assert_wire_constants(void)
                 (long long)OST_QUOTACTL);
        LASSERTF(OST_QUOTA_ADJUST_QUNIT == 20, "found %lld\n",
                 (long long)OST_QUOTA_ADJUST_QUNIT);
-       LASSERTF(OST_LAST_OPC == 21, "found %lld\n",
+       LASSERTF(OST_LADVISE == 21, "found %lld\n",
+                (long long)OST_LADVISE);
+       LASSERTF(OST_LAST_OPC == 22, "found %lld\n",
                 (long long)OST_LAST_OPC);
        LASSERTF(OBD_OBJECT_EOF == 0xffffffffffffffffULL, "found 0x%.16llxULL\n",
                 OBD_OBJECT_EOF);
@@ -5023,4 +5025,54 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct llog_update_record, lur_update_rec));
        LASSERTF((int)sizeof(((struct llog_update_record *)0)->lur_update_rec) == 32, "found %lld\n",
                 (long long)(int)sizeof(((struct llog_update_record *)0)->lur_update_rec));
+
+       /* Checks for struct lu_ladvise */
+       LASSERTF((int)sizeof(struct lu_ladvise) == 32, "found %lld\n",
+                (long long)(int)sizeof(struct lu_ladvise));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_advice) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_advice));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_advice) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_advice));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_start) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_start));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_start) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_start));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_end) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_end));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_end) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_end));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_padding) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_padding));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_padding) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_padding));
+
+       /* Checks for struct ladvise_hdr */
+       LASSERTF(LADVISE_MAGIC == 0x1ADF1CE0, "found 0x%.8x\n",
+                LADVISE_MAGIC);
+       LASSERTF((int)sizeof(struct ladvise_hdr) == 32, "found %lld\n",
+                (long long)(int)sizeof(struct ladvise_hdr));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_magic) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_magic));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_magic) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_magic));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_count) == 4, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_count));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_count) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_count));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_flags) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_flags));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_flags) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_flags));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_padding1) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_padding1));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_padding1) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_padding1));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_padding2) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_padding2));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_padding2) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_padding2));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_advise) == 32, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_advise));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_advise) == 0, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_advise));
 }
index f2523be..9fea34e 100644 (file)
@@ -85,7 +85,8 @@ liblustreapitmp_a_SOURCES = liblustreapi.c liblustreapi_hsm.c \
                            liblustreapi_lease.c liblustreapi_util.c \
                            liblustreapi_kernelconn.c liblustreapi_param.c \
                            $(top_builddir)/libcfs/libcfs/util/string.c \
-                           $(top_builddir)/libcfs/libcfs/util/param.c
+                           $(top_builddir)/libcfs/libcfs/util/param.c \
+                           liblustreapi_ladvise.c
 if UTILS
 # build static and shared lib lustreapi
 liblustreapi.a : liblustreapitmp.a
index 1dcfc44..bcc1963 100644 (file)
@@ -116,6 +116,7 @@ static int lfs_hsm_remove(int argc, char **argv);
 static int lfs_hsm_cancel(int argc, char **argv);
 static int lfs_swap_layouts(int argc, char **argv);
 static int lfs_mv(int argc, char **argv);
+static int lfs_ladvise(int argc, char **argv);
 
 /* Setstripe and migrate share mostly the same parameters */
 #define SSM_CMD_COMMON(cmd) \
@@ -384,6 +385,12 @@ command_t cmdlist[] = {
         "use \"migrate\" instead.\n"
         "usage: mv <directory|filename> [--mdt-index|-M] <mdt_index> "
         "[--verbose|-v]\n"},
+       {"ladvise", lfs_ladvise, 0,
+        "Provide servers with advice about access patterns for a file.\n"
+        "usage: ladvise [--advice|-a ADVICE] [--start|-s START[kMGT]]\n"
+        "               [--background|-b]\n"
+        "               {[--end|-e END[kMGT]] | [--length|-l LENGTH[kMGT]]}\n"
+        "               <file> ..."},
        {"help", Parser_help, 0, "help"},
        {"exit", Parser_quit, 0, "quit"},
        {"quit", Parser_quit, 0, "quit"},
@@ -4221,6 +4228,178 @@ static int lfs_swap_layouts(int argc, char **argv)
                                  SWAP_LAYOUTS_KEEP_ATIME);
 }
 
+static const char *const ladvise_names[] = LU_LADVISE_NAMES;
+
+static enum lu_ladvise_type lfs_get_ladvice(const char *string)
+{
+       enum lu_ladvise_type advice;
+
+       for (advice = 0;
+            advice < ARRAY_SIZE(ladvise_names); advice++) {
+               if (ladvise_names[advice] == NULL)
+                       continue;
+               if (strcmp(string, ladvise_names[advice]) == 0)
+                       return advice;
+       }
+
+       return LU_LADVISE_INVALID;
+}
+
+static int lfs_ladvise(int argc, char **argv)
+{
+       struct option            long_opts[] = {
+               {"advice",      required_argument,      0, 'a'},
+               {"background",  no_argument,            0, 'b'},
+               {"end",         required_argument,      0, 'e'},
+               {"start",       required_argument,      0, 's'},
+               {"length",      required_argument,      0, 'l'},
+               {0, 0, 0, 0}
+       };
+       char                     short_opts[] = "a:be:l:s:";
+       int                      c;
+       int                      rc = 0;
+       const char              *path;
+       int                      fd;
+       struct lu_ladvise        advice;
+       enum lu_ladvise_type     advice_type = LU_LADVISE_INVALID;
+       unsigned long long       start = 0;
+       unsigned long long       end = LUSTRE_EOF;
+       unsigned long long       length = 0;
+       unsigned long long       size_units;
+       unsigned long long       flags = 0;
+
+       optind = 0;
+       while ((c = getopt_long(argc, argv, short_opts,
+                               long_opts, NULL)) != -1) {
+               switch (c) {
+               case 'a':
+                       advice_type = lfs_get_ladvice(optarg);
+                       if (advice_type == LU_LADVISE_INVALID) {
+                               fprintf(stderr, "%s: invalid advice type "
+                                       "'%s'\n", argv[0], optarg);
+                               fprintf(stderr, "Valid types:");
+
+                               for (advice_type = 0;
+                                    advice_type < ARRAY_SIZE(ladvise_names);
+                                    advice_type++) {
+                                       if (ladvise_names[advice_type] == NULL)
+                                               continue;
+                                       fprintf(stderr, " %s",
+                                               ladvise_names[advice_type]);
+                               }
+                               fprintf(stderr, "\n");
+
+                               return CMD_HELP;
+                       }
+                       break;
+               case 'b':
+                       flags |= LF_ASYNC;
+                       break;
+               case 'e':
+                       size_units = 1;
+                       rc = llapi_parse_size(optarg, &end,
+                                             &size_units, 0);
+                       if (rc) {
+                               fprintf(stderr, "%s: bad end offset '%s'\n",
+                                       argv[0], optarg);
+                               return CMD_HELP;
+                       }
+                       break;
+               case 's':
+                       size_units = 1;
+                       rc = llapi_parse_size(optarg, &start,
+                                             &size_units, 0);
+                       if (rc) {
+                               fprintf(stderr, "%s: bad start offset "
+                                       "'%s'\n", argv[0], optarg);
+                               return CMD_HELP;
+                       }
+                       break;
+               case 'l':
+                       size_units = 1;
+                       rc = llapi_parse_size(optarg, &length,
+                                             &size_units, 0);
+                       if (rc) {
+                               fprintf(stderr, "%s: bad length '%s'\n",
+                                       argv[0], optarg);
+                               return CMD_HELP;
+                       }
+                       break;
+               case '?':
+                       return CMD_HELP;
+               default:
+                       fprintf(stderr, "%s: option '%s' unrecognized\n",
+                               argv[0], argv[optind - 1]);
+                       return CMD_HELP;
+               }
+       }
+
+       if (advice_type == LU_LADVISE_INVALID) {
+               fprintf(stderr, "%s: please give an advice type\n", argv[0]);
+               fprintf(stderr, "Valid types:");
+               for (advice_type = 0; advice_type < ARRAY_SIZE(ladvise_names);
+                    advice_type++) {
+                       if (ladvise_names[advice_type] == NULL)
+                               continue;
+                       fprintf(stderr, " %s", ladvise_names[advice_type]);
+               }
+               fprintf(stderr, "\n");
+               return CMD_HELP;
+       }
+
+       if (argc <= optind) {
+               fprintf(stderr, "%s: please give one or more file names\n",
+                       argv[0]);
+               return CMD_HELP;
+       }
+
+       if (end != LUSTRE_EOF && length != 0 && end != start + length) {
+               fprintf(stderr, "%s: conflicting arguments of -l and -e\n",
+                       argv[0]);
+               return CMD_HELP;
+       }
+
+       if (end == LUSTRE_EOF && length != 0)
+               end = start + length;
+
+       if (end <= start) {
+               fprintf(stderr, "%s: range [%llu, %llu] is invalid\n",
+                       argv[0], start, end);
+               return CMD_HELP;
+       }
+
+       while (optind < argc) {
+               int rc2;
+
+               path = argv[optind++];
+
+               fd = open(path, O_RDONLY);
+               if (fd < 0) {
+                       fprintf(stderr, "%s: cannot open file '%s': %s\n",
+                               argv[0], path, strerror(errno));
+                       rc2 = -errno;
+                       goto next;
+               }
+
+               advice.lla_start = start;
+               advice.lla_end = end;
+               advice.lla_advice = advice_type;
+               advice.lla_padding = 0;
+               rc2 = llapi_ladvise(fd, flags, 1, &advice);
+               close(fd);
+               if (rc2 < 0) {
+                       fprintf(stderr, "%s: cannot give advice '%s' to file "
+                               "'%s': %s\n", argv[0],
+                               ladvise_names[advice_type],
+                               path, strerror(errno));
+               }
+next:
+               if (rc == 0 && rc2 < 0)
+                       rc = rc2;
+       }
+       return rc;
+}
+
 int main(int argc, char **argv)
 {
         int rc;
diff --git a/lustre/utils/liblustreapi_ladvise.c b/lustre/utils/liblustreapi_ladvise.c
new file mode 100644 (file)
index 0000000..85083f1
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * LGPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * (C) Copyright (c) 2015, DataDirect Networks Inc, all rights reserved.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * LGPL version 2.1 or (at your discretion) any later version.
+ * LGPL version 2.1 accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl-2.1.html
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * LGPL HEADER END
+ */
+/*
+ * lustre/utils/liblustreapi_ladvise.c
+ *
+ * lustreapi library for ladvise
+ *
+ * Author: Li Xi <lixi@ddn.com>
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <lustre/lustreapi.h>
+#include <lustre/lustre_idl.h>
+#include "lustreapi_internal.h"
+
+/*
+ * Give file access advices
+ *
+ * \param fd       File to give advice on.
+ * \param ladvise  Advice to give.
+ *
+ * \retval 0 on success.
+ * \retval -errno on failure.
+ */
+int llapi_ladvise(int fd, unsigned long long flags, int num_advise,
+                 struct lu_ladvise *ladvise)
+{
+       int rc;
+       struct ladvise_hdr *ladvise_hdr;
+
+       if (num_advise < 1 || num_advise >= LAH_COUNT_MAX) {
+               errno = EINVAL;
+               llapi_error(LLAPI_MSG_ERROR, -EINVAL,
+                           "bad advice number %d", num_advise);
+               return -1;
+       }
+
+       ladvise_hdr = calloc(1, offsetof(typeof(*ladvise_hdr),
+                            lah_advise[num_advise]));
+       if (ladvise_hdr == NULL) {
+               errno = ENOMEM;
+               llapi_error(LLAPI_MSG_ERROR, -ENOMEM, "not enough memory");
+               return -1;
+       }
+       ladvise_hdr->lah_magic = LADVISE_MAGIC;
+       ladvise_hdr->lah_count = num_advise;
+       ladvise_hdr->lah_flags = flags & LF_MASK;
+       memcpy(ladvise_hdr->lah_advise, ladvise, sizeof(*ladvise) * num_advise);
+
+       rc = ioctl(fd, LL_IOC_LADVISE, ladvise_hdr);
+       if (rc < 0) {
+               llapi_error(LLAPI_MSG_ERROR, -errno, "cannot give advice");
+               return -1;
+       }
+       return 0;
+}
+
index deb77fc..6730a9d 100644 (file)
@@ -127,5 +127,4 @@ int libcfs_ukuc_stop(struct lustre_kernelcomm *l);
 int libcfs_ukuc_get_rfd(struct lustre_kernelcomm *link);
 int libcfs_ukuc_msg_get(struct lustre_kernelcomm *l, char *buf, int maxsize,
                        int transport);
-
 #endif /* _LUSTREAPI_INTERNAL_H_ */
index 6668fd4..3a975e7 100644 (file)
 
 #include <linux/types.h>
 
-#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
 #define __REQ_LAYOUT_USER__ (1)
 #define EXPORT_SYMBOL(s)
 
 #include <lustre/lustre_idl.h>
 #include <lustre_req_layout.h>
+#include <lustre/lustreapi.h>
 
 #define lustre_swab_generic_32s NULL
 #define lustre_swab_lu_seq_range NULL
 #define lustre_swab_lmv_user_md NULL
 #define lustre_swab_lfsck_request NULL
 #define lustre_swab_lfsck_reply NULL
+#define lustre_swab_ladvise_hdr NULL
+#define lustre_swab_ladvise NULL
 
 /*
  * Yes, include .c file.
index 2415c43..eabca64 100644 (file)
@@ -308,6 +308,17 @@ check_lu_dirpage(void)
 }
 
 static void
+check_lu_ladvise(void)
+{
+       BLANK_LINE();
+       CHECK_STRUCT(lu_ladvise);
+       CHECK_MEMBER(lu_ladvise, lla_start);
+       CHECK_MEMBER(lu_ladvise, lla_end);
+       CHECK_MEMBER(lu_ladvise, lla_advice);
+       CHECK_MEMBER(lu_ladvise, lla_padding);
+}
+
+static void
 check_lustre_handle(void)
 {
        BLANK_LINE();
@@ -2412,6 +2423,7 @@ main(int argc, char **argv)
        CHECK_VALUE(OST_QUOTACHECK);
        CHECK_VALUE(OST_QUOTACTL);
        CHECK_VALUE(OST_QUOTA_ADJUST_QUNIT);
+       CHECK_VALUE(OST_LADVISE);
        CHECK_VALUE(OST_LAST_OPC);
 
        CHECK_DEFINE_64X(OBD_OBJECT_EOF);
@@ -2607,6 +2619,7 @@ main(int argc, char **argv)
        check_lu_dirent();
        check_luda_type();
        check_lu_dirpage();
+       check_lu_ladvise();
        check_lustre_handle();
        check_lustre_msg_v2();
        check_ptlrpc_body();
index 040c14b..fc031e4 100644 (file)
@@ -119,7 +119,9 @@ void lustre_assert_wire_constants(void)
                 (long long)OST_QUOTACTL);
        LASSERTF(OST_QUOTA_ADJUST_QUNIT == 20, "found %lld\n",
                 (long long)OST_QUOTA_ADJUST_QUNIT);
-       LASSERTF(OST_LAST_OPC == 21, "found %lld\n",
+       LASSERTF(OST_LADVISE == 21, "found %lld\n",
+                (long long)OST_LADVISE);
+       LASSERTF(OST_LAST_OPC == 22, "found %lld\n",
                 (long long)OST_LAST_OPC);
        LASSERTF(OBD_OBJECT_EOF == 0xffffffffffffffffULL, "found 0x%.16llxULL\n",
                 OBD_OBJECT_EOF);
@@ -5038,4 +5040,54 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct llog_update_record, lur_update_rec));
        LASSERTF((int)sizeof(((struct llog_update_record *)0)->lur_update_rec) == 32, "found %lld\n",
                 (long long)(int)sizeof(((struct llog_update_record *)0)->lur_update_rec));
+
+       /* Checks for struct lu_ladvise */
+       LASSERTF((int)sizeof(struct lu_ladvise) == 32, "found %lld\n",
+                (long long)(int)sizeof(struct lu_ladvise));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_advice) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_advice));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_advice) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_advice));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_start) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_start));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_start) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_start));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_end) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_end));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_end) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_end));
+       LASSERTF((int)offsetof(struct lu_ladvise, lla_padding) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct lu_ladvise, lla_padding));
+       LASSERTF((int)sizeof(((struct lu_ladvise *)0)->lla_padding) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct lu_ladvise *)0)->lla_padding));
+
+       /* Checks for struct ladvise_hdr */
+       LASSERTF(LADVISE_MAGIC == 0x1ADF1CE0, "found 0x%.8x\n",
+                LADVISE_MAGIC);
+       LASSERTF((int)sizeof(struct ladvise_hdr) == 32, "found %lld\n",
+                (long long)(int)sizeof(struct ladvise_hdr));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_magic) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_magic));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_magic) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_magic));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_count) == 4, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_count));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_count) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_count));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_flags) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_flags));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_flags) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_flags));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_padding1) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_padding1));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_padding1) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_padding1));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_padding2) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_padding2));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_padding2) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_padding2));
+       LASSERTF((int)offsetof(struct ladvise_hdr, lah_advise) == 32, "found %lld\n",
+                (long long)(int)offsetof(struct ladvise_hdr, lah_advise));
+       LASSERTF((int)sizeof(((struct ladvise_hdr *)0)->lah_advise) == 0, "found %lld\n",
+                (long long)(int)sizeof(((struct ladvise_hdr *)0)->lah_advise));
 }