OST_QUOTACHECK = 18,
OST_QUOTACTL = 19,
OST_QUOTA_ADJUST_QUNIT = 20,
+ OST_LADVISE = 21,
OST_LAST_OPC
} ost_cmd_t ;
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;
/* --------------------------------------------------------------------*/
{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"},
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)
{
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;
}
&ett_lustre_mdt_ioepoch,
&ett_lustre_capa,
&ett_lustre_acl,
+ &ett_lustre_ladvise,
};
proto_lustre = proto_register_protocol("Lustre", "lustre", "lustre");
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
--- /dev/null
+.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)
--- /dev/null
+.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)
* 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
};
int crw_nonblock;
};
-
/**
* State for 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;
__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);
};
/**
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)
{
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
#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 {
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 */
#include <stdint.h>
#include <lustre/lustre_user.h>
+#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+
extern bool liblustreapi_initialized;
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 */
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;
/* 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__ */
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
#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
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)
{
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;
},
[CIT_MISC] = {
.cio_fini = vvp_io_fini
- }
+ },
+ [CIT_LADVISE] = {
+ .cio_fini = vvp_io_fini
+ },
},
.cio_read_ahead = vvp_io_read_ahead
};
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,
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;
.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
}
[CIT_FSYNC] = {
.cio_fini = lov_empty_io_fini
},
+ [CIT_LADVISE] = {
+ .cio_fini = lov_empty_io_fini
+ },
[CIT_MISC] = {
.cio_fini = lov_empty_io_fini
}
result = 0;
break;
case CIT_FSYNC:
+ case CIT_LADVISE:
case CIT_SETATTR:
case CIT_DATA_VERSION:
result = +1;
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;
LASSERT(ergo(io->ci_ignore_layout || !io->ci_verify_layout,
!io->ci_need_restart));
break;
+ case CIT_LADVISE:
+ break;
default:
LBUG();
}
}
/**
+ * 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,
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[] = {
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 {
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 = {
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);
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)
{
.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
}
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;
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)
{
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
};
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,
};
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,
.dbo_read_prep = osd_read_prep,
.dbo_declare_punch = osd_declare_punch,
.dbo_punch = osd_punch,
+ .dbo_ladvise = osd_ladvise,
};
&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
&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,
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);
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 */
{ 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" },
__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);
(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);
(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));
}
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
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) \
"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"},
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;
--- /dev/null
+/*
+ * 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;
+}
+
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_ */
#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.
}
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();
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);
check_lu_dirent();
check_luda_type();
check_lu_dirpage();
+ check_lu_ladvise();
check_lustre_handle();
check_lustre_msg_v2();
check_ptlrpc_body();
(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);
(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));
}