From 40137f1d07295ee4a0bb75d2ae553c42e66295f4 Mon Sep 17 00:00:00 2001 From: jcl Date: Thu, 10 Jan 2013 18:42:12 +0100 Subject: [PATCH] LU-2061 hsm: send HSM resquest to CDT This patch implements the user interface to ask for hsm requests It implements: - lfs hsm_archive - lfs hsm_restore - lfs hsm_cancel - lfs hsm_remove - lfs hsm_release The matching llapi call: - llapi_hsm_user_request_alloc() - llapi_hsm_request() related MDS functions: - mdt_hsm_request() and the MDS RPC: - MDS_HSM_REQUEST Signed-off-by: JC Lafoucriere Change-Id: I635f6e0518ec12c359dbb528c3a61216650d952d Reviewed-on: http://review.whamcloud.com/5030 Reviewed-by: Johann Lombardi Tested-by: Hudson Tested-by: Maloo Reviewed-by: Andreas Dilger --- lustre/include/lustre/lustre_idl.h | 2 +- lustre/include/lustre/lustre_user.h | 43 ++++-- lustre/include/lustre/lustreapi.h | 7 +- lustre/include/lustre_req_layout.h | 2 + lustre/llite/dir.c | 34 +++++ lustre/mdc/lproc_mdc.c | 2 +- lustre/mdc/mdc_request.c | 74 +++++++++-- lustre/mdt/mdt_hsm.c | 117 +++++++++++++++- lustre/mdt/mdt_internal.h | 1 + lustre/mdt/mdt_mds.c | 4 +- lustre/ptlrpc/layout.c | 18 +++ lustre/ptlrpc/pack_generic.c | 10 ++ lustre/ptlrpc/wiretest.c | 48 ++++++- lustre/tests/copytool.c | 52 ++++---- lustre/utils/lfs.c | 256 ++++++++++++++++++++++++++++++++++++ lustre/utils/liblustreapi_hsm.c | 47 ++++++- lustre/utils/req-layout.c | 1 + lustre/utils/wirecheck.c | 27 +++- lustre/utils/wiretest.c | 48 ++++++- 19 files changed, 721 insertions(+), 72 deletions(-) diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index e75d288..9b3a848 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -3338,6 +3338,6 @@ extern void lustre_swab_hsm_current_action(struct hsm_current_action *action); extern void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk); extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus); extern void lustre_swab_hsm_user_item(struct hsm_user_item *hui); - +extern void lustre_swab_hsm_request(struct hsm_request *hr); #endif /** @} lustreidl */ diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index b98c6ed..686d4e9 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -855,35 +855,52 @@ static inline char *hsm_user_action2name(enum hsm_user_action a) } } +/* + * List of hr_flags (bit field) + */ +#define HSM_FORCE_ACTION 0x0001 +/* used by CT, connot be set by user */ +#define HSM_GHOST_COPY 0x0002 + +/** + * Contains all the fixed part of struct hsm_user_request. + * + */ +struct hsm_request { + __u32 hr_action; /* enum hsm_user_action */ + __u32 hr_archive_id; /* archive id, used only with HUA_ARCHIVE */ + __u64 hr_flags; /* request flags */ + __u32 hr_itemcount; /* item count in hur_user_item vector */ + __u32 hr_data_len; +}; + struct hsm_user_item { lustre_fid hui_fid; struct hsm_extent hui_extent; } __attribute__((packed)); struct hsm_user_request { - __u32 hur_action; /* enum hsm_user_action */ - __u32 hur_archive_num; /* archive number, used only with HUA_ARCHIVE */ - __u32 hur_itemcount; - __u32 hur_data_len; - struct hsm_user_item hur_user_item[0]; - /* extra data blob at end of struct (after all - * hur_user_items), only use helpers to access it - */ + struct hsm_request hur_request; + struct hsm_user_item hur_user_item[0]; + /* extra data blob at end of struct (after all + * hur_user_items), only use helpers to access it + */ } __attribute__((packed)); /** Return pointer to data field in a hsm user request */ static inline void *hur_data(struct hsm_user_request *hur) { - return &(hur->hur_user_item[hur->hur_itemcount]); + return &(hur->hur_user_item[hur->hur_request.hr_itemcount]); } /** Compute the current length of the provided hsm_user_request. */ static inline int hur_len(struct hsm_user_request *hur) { - int data_offset; + int data_offset; - data_offset = hur_data(hur) - (void *)hur; - return (data_offset + hur->hur_data_len); + data_offset = hur_data(hur) - (void *)hur; + data_offset += hur->hur_request.hr_data_len; + return data_offset; } /****** HSM RPCs to copytool *****/ @@ -963,7 +980,7 @@ struct hsm_action_list { __u32 hal_count; /* number of hai's to follow */ __u64 hal_compound_id; /* returned by coordinator */ __u64 hal_flags; - __u32 hal_archive_num; /* which archive backend */ + __u32 hal_archive_id; /* which archive backend */ __u32 padding1; char hal_fsname[0]; /* null-terminated */ /* struct hsm_action_item[hal_count] follows, aligned on 8-byte diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 1d10f7f..c7a2bb1 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -278,15 +278,16 @@ extern int llapi_hsm_copy_start(char *mnt, struct hsm_copy *copy, const struct hsm_action_item *hai); extern int llapi_hsm_copy_end(char *mnt, struct hsm_copy *copy, const struct hsm_progress *hp); -extern int llapi_hsm_request(char *mnt, struct hsm_user_request *request); extern int llapi_hsm_progress(char *mnt, struct hsm_progress *hp); -extern struct hsm_user_request *llapi_hsm_user_request_alloc(int itemcount, - int data_len); extern int llapi_hsm_import(const char *dst, int archive, struct stat *st, unsigned long long stripe_size, int stripe_offset, int stripe_count, int stripe_pattern, char *pool_name, lustre_fid *newfid); + /* HSM user interface */ +extern struct hsm_user_request *llapi_hsm_user_request_alloc(int itemcount, + int data_len); +extern int llapi_hsm_request(char *mnt, struct hsm_user_request *request); extern int llapi_hsm_current_action(const char *path, struct hsm_current_action *hca); /** @} llapi */ diff --git a/lustre/include/lustre_req_layout.h b/lustre/include/lustre_req_layout.h index 9d1d2be..f2d65cc 100644 --- a/lustre/include/lustre_req_layout.h +++ b/lustre/include/lustre_req_layout.h @@ -193,6 +193,7 @@ extern struct req_format RQF_MDS_HSM_ACTION; extern struct req_format RQF_MDS_HSM_PROGRESS; extern struct req_format RQF_MDS_HSM_CT_REGISTER; extern struct req_format RQF_MDS_HSM_CT_UNREGISTER; +extern struct req_format RQF_MDS_HSM_REQUEST; /* OST req_format */ extern struct req_format RQF_OST_CONNECT; extern struct req_format RQF_OST_DISCONNECT; @@ -286,6 +287,7 @@ extern struct req_msg_field RMF_MDS_HSM_ARCHIVE; extern struct req_msg_field RMF_HSM_USER_STATE; extern struct req_msg_field RMF_HSM_STATE_SET; extern struct req_msg_field RMF_MDS_HSM_CURRENT_ACTION; +extern struct req_msg_field RMF_MDS_HSM_REQUEST; /* seq-mgr fields */ extern struct req_msg_field RMF_SEQ_OPC; diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 1fef702..d0cfb2a 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -1630,6 +1630,40 @@ out_free: RETURN(rc); case OBD_IOC_FID2PATH: RETURN(ll_fid2path(inode, (void *)arg)); + case LL_IOC_HSM_REQUEST: { + struct hsm_user_request *hur; + int totalsize; + + OBD_ALLOC_PTR(hur); + if (hur == NULL) + RETURN(-ENOMEM); + + /* We don't know the true size yet; copy the fixed-size part */ + if (cfs_copy_from_user(hur, (void *)arg, sizeof(*hur))) { + OBD_FREE_PTR(hur); + RETURN(-EFAULT); + } + + /* Compute the whole struct size */ + totalsize = hur_len(hur); + OBD_FREE_PTR(hur); + OBD_ALLOC_LARGE(hur, totalsize); + if (hur == NULL) + RETURN(-ENOMEM); + + /* Copy the whole struct */ + if (cfs_copy_from_user(hur, (void *)arg, totalsize)) { + OBD_FREE_LARGE(hur, totalsize); + RETURN(-EFAULT); + } + + rc = obd_iocontrol(cmd, ll_i2mdexp(inode), totalsize, + hur, NULL); + + OBD_FREE_LARGE(hur, totalsize); + + RETURN(rc); + } case LL_IOC_HSM_PROGRESS: { struct hsm_progress_kernel hpk; struct hsm_progress hp; diff --git a/lustre/mdc/lproc_mdc.c b/lustre/mdc/lproc_mdc.c index 509fd59..7d4fa12 100644 --- a/lustre/mdc/lproc_mdc.c +++ b/lustre/mdc/lproc_mdc.c @@ -108,7 +108,7 @@ static int mdc_wr_kuc(struct file *file, const char *buffer, hal = (struct hsm_action_list *)(lh + 1); hal->hal_version = HAL_VERSION; - hal->hal_archive_num = 1; + hal->hal_archive_id = 1; hal->hal_flags = 0; obd_uuid2fsname(hal->hal_fsname, obd->obd_name, MTI_NAME_MAXLEN); diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 2853268..ec9a6d4 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -1322,7 +1322,6 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp, struct md_op_data *op_data) { struct hsm_user_state *hus = op_data->op_data; - struct obd_import *imp = class_exp2cliimp(exp); struct hsm_user_state *req_hus; struct ptlrpc_request *req; int rc; @@ -1347,12 +1346,8 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp, ptlrpc_request_set_replen(req); rc = ptlrpc_queue_wait(req); - if (rc) { - /* check connection error first */ - if (imp->imp_connect_error) - rc = imp->imp_connect_error; + if (rc) GOTO(out, rc); - } req_hus = req_capsule_server_get(&req->rq_pill, &RMF_HSM_USER_STATE); if (req_hus == NULL) @@ -1370,7 +1365,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, struct md_op_data *op_data) { struct hsm_state_set *hss = op_data->op_data; - struct obd_import *imp = class_exp2cliimp(exp); struct hsm_state_set *req_hss; struct ptlrpc_request *req; int rc; @@ -1400,12 +1394,7 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, ptlrpc_request_set_replen(req); rc = ptlrpc_queue_wait(req); - if (rc) { - /* check connection error first */ - if (imp->imp_connect_error) - rc = imp->imp_connect_error; - GOTO(out, rc); - } + GOTO(out, rc); EXIT; out: @@ -1413,6 +1402,60 @@ out: return rc; } +static int mdc_ioc_hsm_request(struct obd_export *exp, + struct hsm_user_request *hur) +{ + struct obd_import *imp = class_exp2cliimp(exp); + struct ptlrpc_request *req; + struct hsm_request *req_hr; + struct hsm_user_item *req_hui; + char *req_opaque; + int rc; + ENTRY; + + req = ptlrpc_request_alloc(imp, &RQF_MDS_HSM_REQUEST); + if (req == NULL) + GOTO(out, rc = -ENOMEM); + + req_capsule_set_size(&req->rq_pill, &RMF_MDS_HSM_USER_ITEM, RCL_CLIENT, + hur->hur_request.hr_itemcount + * sizeof(struct hsm_user_item)); + req_capsule_set_size(&req->rq_pill, &RMF_GENERIC_DATA, RCL_CLIENT, + hur->hur_request.hr_data_len); + + rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_REQUEST); + if (rc) { + ptlrpc_request_free(req); + RETURN(rc); + } + + mdc_pack_body(req, NULL, NULL, OBD_MD_FLRMTPERM, 0, 0, 0); + + /* Copy hsm_request struct */ + req_hr = req_capsule_client_get(&req->rq_pill, &RMF_MDS_HSM_REQUEST); + LASSERT(req_hr); + *req_hr = hur->hur_request; + + /* Copy hsm_user_item structs */ + req_hui = req_capsule_client_get(&req->rq_pill, &RMF_MDS_HSM_USER_ITEM); + LASSERT(req_hui); + memcpy(req_hui, hur->hur_user_item, + hur->hur_request.hr_itemcount * sizeof(struct hsm_user_item)); + + /* Copy opaque field */ + req_opaque = req_capsule_client_get(&req->rq_pill, &RMF_GENERIC_DATA); + LASSERT(req_opaque); + memcpy(req_opaque, hur_data(hur), hur->hur_request.hr_data_len); + + ptlrpc_request_set_replen(req); + + rc = ptlrpc_queue_wait(req); + GOTO(out, rc); + +out: + ptlrpc_req_finished(req); + return rc; +} static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags) { @@ -1703,6 +1746,9 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case LL_IOC_HSM_ACTION: rc = mdc_ioc_hsm_current_action(exp, karg); GOTO(out, rc); + case LL_IOC_HSM_REQUEST: + rc = mdc_ioc_hsm_request(exp, karg); + GOTO(out, rc); case OBD_IOC_CLIENT_RECOVER: rc = ptlrpc_recover_import(imp, data->ioc_inlbuf1, 0); if (rc < 0) @@ -1868,7 +1914,7 @@ static void lustre_swab_hal(struct hsm_action_list *h) __swab32s(&h->hal_version); __swab32s(&h->hal_count); - __swab32s(&h->hal_archive_num); + __swab32s(&h->hal_archive_id); __swab64s(&h->hal_flags); hai = hai_zero(h); for (i = 0; i < h->hal_count; i++) { diff --git a/lustre/mdt/mdt_hsm.c b/lustre/mdt/mdt_hsm.c index 3dc19b9..face836 100644 --- a/lustre/mdt/mdt_hsm.c +++ b/lustre/mdt/mdt_hsm.c @@ -75,6 +75,14 @@ static int mdt_hsm_coordinator_get_actions(struct mdt_thread_info *mti, return 0; } +static int mdt_hsm_coordinator_actions(struct mdt_thread_info *info, + struct hsm_action_list *hal, + __u64 *compound_id, + int mti_attr_is_valid) +{ + return 0; +} + /** * Update on-disk HSM attributes. */ @@ -349,7 +357,7 @@ int mdt_hsm_action(struct mdt_thread_info *info) GOTO(out_ucred, -ENOMEM); hal->hal_version = HAL_VERSION; - hal->hal_archive_num = 0; + hal->hal_archive_id = 0; hal->hal_flags = 0; obd_uuid2fsname(hal->hal_fsname, mdt2obd_dev(info->mti_mdt)->obd_name, MTI_NAME_MAXLEN); @@ -404,3 +412,110 @@ out_ucred: mdt_exit_ucred(info); return rc; } + +/** + * Process the HSM actions described in a struct hsm_user_request. + * + * The action described in hur will be send to coordinator to be saved and + * processed later or either handled directly if hur.hur_action is HUA_RELEASE. + * + * This is MDS_HSM_REQUEST RPC handler. + */ +int mdt_hsm_request(struct mdt_thread_info *info) +{ + struct req_capsule *pill = info->mti_pill; + struct mdt_body *body; + struct hsm_request *hr; + struct hsm_user_item *hui; + struct hsm_action_list *hal; + struct hsm_action_item *hai; + char *opaque; + enum hsm_copytool_action action = HSMA_NONE; + __u64 compound_id; + int len, i, rc; + ENTRY; + + body = req_capsule_client_get(pill, &RMF_MDT_BODY); + LASSERT(body); + + hr = req_capsule_client_get(pill, &RMF_MDS_HSM_REQUEST); + LASSERT(hr); + + hui = req_capsule_client_get(pill, &RMF_MDS_HSM_USER_ITEM); + LASSERT(hui); + + opaque = req_capsule_client_get(pill, &RMF_GENERIC_DATA); + LASSERT(opaque); + + /* Sanity check. Nothing to do with an empty list */ + if (hr->hr_itemcount == 0) + RETURN(0); + + /* Only valid if client is remote */ + rc = mdt_init_ucred(info, body); + if (rc) + RETURN(err_serious(rc)); + + switch (hr->hr_action) { + /* code to be removed in hsm1_merge and final patch */ + case HUA_RELEASE: + CERROR("Release action is not working in hsm1_coord\n"); + GOTO(out_ucred, rc = -EINVAL); + break; + /* end of code to be removed */ + case HUA_ARCHIVE: + action = HSMA_ARCHIVE; + break; + case HUA_RESTORE: + action = HSMA_RESTORE; + break; + case HUA_REMOVE: + action = HSMA_REMOVE; + break; + case HUA_CANCEL: + action = HSMA_CANCEL; + break; + default: + CERROR("Unknown hsm action: %d\n", hr->hr_action); + GOTO(out_ucred, rc = -EINVAL); + } + + len = sizeof(*hal) + MTI_NAME_MAXLEN /* fsname */ + + cfs_size_round(sizeof(*hai) * hr->hr_itemcount) + + cfs_size_round(hr->hr_data_len * hr->hr_itemcount); + + OBD_ALLOC(hal, len); + if (hal == NULL) + GOTO(out_ucred, rc = -ENOMEM); + + hal->hal_version = HAL_VERSION; + hal->hal_archive_id = hr->hr_archive_id; + hal->hal_flags = hr->hr_flags; + obd_uuid2fsname(hal->hal_fsname, mdt2obd_dev(info->mti_mdt)->obd_name, + MTI_NAME_MAXLEN); + + hal->hal_count = hr->hr_itemcount; + hai = hai_zero(hal); + for (i = 0; i < hr->hr_itemcount; i++) { + hai->hai_action = action; + hai->hai_cookie = 0; + hai->hai_gid = 0; + hai->hai_fid = hui[i].hui_fid; + hai->hai_extent = hui[i].hui_extent; + memcpy(hai->hai_data, opaque, hr->hr_data_len); + hai->hai_len = sizeof(*hai) + hr->hr_data_len; + hai = hai_next(hai); + } + + rc = mdt_hsm_coordinator_actions(info, hal, &compound_id, 0); + /* ENODATA error code is needed only for implicit requests */ + if (rc == -ENODATA) + rc = 0; + + OBD_FREE(hal, len); + EXIT; +out_ucred: + mdt_exit_ucred(info); + return rc; +} + diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 19e92bb..9abfbe6 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -779,6 +779,7 @@ int mdt_hsm_action(struct mdt_thread_info *info); int mdt_hsm_progress(struct mdt_thread_info *info); int mdt_hsm_ct_register(struct mdt_thread_info *info); int mdt_hsm_ct_unregister(struct mdt_thread_info *info); +int mdt_hsm_request(struct mdt_thread_info *info); extern struct lu_context_key mdt_thread_key; /* debug issues helper starts here*/ diff --git a/lustre/mdt/mdt_mds.c b/lustre/mdt/mdt_mds.c index 8bef043..0a15bd3 100644 --- a/lustre/mdt/mdt_mds.c +++ b/lustre/mdt/mdt_mds.c @@ -151,8 +151,8 @@ DEF_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_HSM_STATE_GET, mdt_hsm_state_get), DEF_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_HSM_STATE_SET, mdt_hsm_state_set), -DEF_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_HSM_ACTION, - mdt_hsm_action), +DEF_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_HSM_ACTION, mdt_hsm_action), +DEF_MDT_HDL(0 | HABEO_REFERO, MDS_HSM_REQUEST, mdt_hsm_request), }; #define DEF_OBD_HDL(flags, name, fn) \ diff --git a/lustre/ptlrpc/layout.c b/lustre/ptlrpc/layout.c index 2044bab..2903d1e 100644 --- a/lustre/ptlrpc/layout.c +++ b/lustre/ptlrpc/layout.c @@ -613,6 +613,14 @@ static const struct req_msg_field *mdt_hsm_state_set[] = { &RMF_HSM_STATE_SET, }; +static const struct req_msg_field *mdt_hsm_request[] = { + &RMF_PTLRPC_BODY, + &RMF_MDT_BODY, + &RMF_MDS_HSM_REQUEST, + &RMF_MDS_HSM_USER_ITEM, + &RMF_GENERIC_DATA, +}; + static struct req_format *req_formats[] = { &RQF_OBD_PING, &RQF_OBD_SET_INFO, @@ -658,6 +666,7 @@ static struct req_format *req_formats[] = { &RQF_MDS_HSM_STATE_GET, &RQF_MDS_HSM_STATE_SET, &RQF_MDS_HSM_ACTION, + &RQF_MDS_HSM_REQUEST, &RQF_QC_CALLBACK, &RQF_OST_CONNECT, &RQF_OST_DISCONNECT, @@ -1067,6 +1076,11 @@ struct req_msg_field RMF_MDS_HSM_ARCHIVE = sizeof(__u32), lustre_swab_generic_32s, NULL); EXPORT_SYMBOL(RMF_MDS_HSM_ARCHIVE); +struct req_msg_field RMF_MDS_HSM_REQUEST = + DEFINE_MSGF("hsm_request", 0, sizeof(struct hsm_request), + lustre_swab_hsm_request, NULL); +EXPORT_SYMBOL(RMF_MDS_HSM_REQUEST); + /* * Request formats. */ @@ -1391,6 +1405,10 @@ struct req_format RQF_MDS_HSM_STATE_SET = DEFINE_REQ_FMT0("MDS_HSM_STATE_SET", mdt_hsm_state_set, empty); EXPORT_SYMBOL(RQF_MDS_HSM_STATE_SET); +struct req_format RQF_MDS_HSM_REQUEST = + DEFINE_REQ_FMT0("MDS_HSM_REQUEST", mdt_hsm_request, empty); +EXPORT_SYMBOL(RQF_MDS_HSM_REQUEST); + /* This is for split */ struct req_format RQF_MDS_WRITEPAGE = DEFINE_REQ_FMT0("MDS_WRITEPAGE", diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index 05d422d..fb8a810 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -2534,3 +2534,13 @@ void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk) } EXPORT_SYMBOL(lustre_swab_hsm_progress_kernel); +void lustre_swab_hsm_request(struct hsm_request *hr) +{ + __swab32s(&hr->hr_action); + __swab32s(&hr->hr_archive_id); + __swab64s(&hr->hr_flags); + __swab32s(&hr->hr_itemcount); + __swab32s(&hr->hr_data_len); +} +EXPORT_SYMBOL(lustre_swab_hsm_request); + diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index 67f4304..b14eb56 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -4209,10 +4209,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct hsm_action_list, hal_flags)); LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_flags) == 8, "found %lld\n", (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_flags)); - LASSERTF((int)offsetof(struct hsm_action_list, hal_archive_num) == 24, "found %lld\n", - (long long)(int)offsetof(struct hsm_action_list, hal_archive_num)); - LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_archive_num) == 4, "found %lld\n", - (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_archive_num)); + LASSERTF((int)offsetof(struct hsm_action_list, hal_archive_id) == 24, "found %lld\n", + (long long)(int)offsetof(struct hsm_action_list, hal_archive_id)); + LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_archive_id) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_archive_id)); LASSERTF((int)offsetof(struct hsm_action_list, padding1) == 28, "found %lld\n", (long long)(int)offsetof(struct hsm_action_list, padding1)); LASSERTF((int)sizeof(((struct hsm_action_list *)0)->padding1) == 4, "found %lld\n", @@ -4382,5 +4382,45 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct hsm_current_action, hca_location)); LASSERTF((int)sizeof(((struct hsm_current_action *)0)->hca_location) == 16, "found %lld\n", (long long)(int)sizeof(((struct hsm_current_action *)0)->hca_location)); + + /* Checks for struct hsm_request */ + LASSERTF((int)sizeof(struct hsm_request) == 24, "found %lld\n", + (long long)(int)sizeof(struct hsm_request)); + LASSERTF((int)offsetof(struct hsm_request, hr_action) == 0, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_action)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_action) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_action)); + LASSERTF((int)offsetof(struct hsm_request, hr_archive_id) == 4, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_archive_id)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_archive_id) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_archive_id)); + LASSERTF((int)offsetof(struct hsm_request, hr_flags) == 8, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_flags)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_flags) == 8, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_flags)); + LASSERTF((int)offsetof(struct hsm_request, hr_itemcount) == 16, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_itemcount)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_itemcount) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_itemcount)); + LASSERTF((int)offsetof(struct hsm_request, hr_data_len) == 20, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_data_len)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_data_len) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_data_len)); + LASSERTF(HSM_FORCE_ACTION == 0x00000001UL, "found 0x%.8xUL\n", + (unsigned)HSM_FORCE_ACTION); + LASSERTF(HSM_GHOST_COPY == 0x00000002UL, "found 0x%.8xUL\n", + (unsigned)HSM_GHOST_COPY); + + /* Checks for struct hsm_user_request */ + LASSERTF((int)sizeof(struct hsm_user_request) == 24, "found %lld\n", + (long long)(int)sizeof(struct hsm_user_request)); + LASSERTF((int)offsetof(struct hsm_user_request, hur_request) == 0, "found %lld\n", + (long long)(int)offsetof(struct hsm_user_request, hur_request)); + LASSERTF((int)sizeof(((struct hsm_user_request *)0)->hur_request) == 24, "found %lld\n", + (long long)(int)sizeof(((struct hsm_user_request *)0)->hur_request)); + LASSERTF((int)offsetof(struct hsm_user_request, hur_user_item) == 24, "found %lld\n", + (long long)(int)offsetof(struct hsm_user_request, hur_user_item)); + LASSERTF((int)sizeof(((struct hsm_user_request *)0)->hur_user_item) == 0, "found %lld\n", + (long long)(int)sizeof(((struct hsm_user_request *)0)->hur_user_item)); } diff --git a/lustre/tests/copytool.c b/lustre/tests/copytool.c index 1e17584..9f66168 100644 --- a/lustre/tests/copytool.c +++ b/lustre/tests/copytool.c @@ -110,34 +110,34 @@ int main(int argc, char **argv) { signal(SIGINT, handler); while(1) { - struct hsm_action_list *hal; - struct hsm_action_item *hai; - int msgsize, i = 0; + struct hsm_action_list *hal; + struct hsm_action_item *hai; + int msgsize, i = 0; rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize); - if (rc == -ESHUTDOWN) { - fprintf(stderr, "shutting down"); - break; - } - if (rc < 0) { - fprintf(stderr, "Message receive: %s", strerror(-rc)); - break; - } - if (msgsize == 0) - continue; /* msg not for us */ - - printf("Copytool fs=%s archive#=%d item_count=%d\n", - hal->hal_fsname, hal->hal_archive_num, hal->hal_count); - - hai = hai_zero(hal); - while (++i <= hal->hal_count) { - printf("Item %d: action %d reclen %d\n", i, - hai->hai_action, hai->hai_len); - printf(" "DFID" gid="LPU64" cookie="LPU64"\n", - PFID(&hai->hai_fid), hai->hai_gid, - hai->hai_cookie); - hai = hai_next(hai); - } + if (rc == -ESHUTDOWN) { + fprintf(stderr, "shutting down"); + break; + } + if (rc < 0) { + fprintf(stderr, "Message receive: %s", strerror(-rc)); + break; + } + if (msgsize == 0) + continue; /* msg not for us */ + + printf("Copytool fs=%s archive#=%d item_count=%d\n", + hal->hal_fsname, hal->hal_archive_id, hal->hal_count); + + hai = hai_zero(hal); + while (++i <= hal->hal_count) { + printf("Item %d: action %d reclen %d\n", i, + hai->hai_action, hai->hai_len); + printf(" "DFID" gid="LPU64" cookie="LPU64"\n", + PFID(&hai->hai_fid), hai->hai_gid, + hai->hai_cookie); + hai = hai_next(hai); + } llapi_hsm_copytool_free(&hal); } diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 5c6f1ca..7662063 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -108,6 +108,12 @@ static int lfs_hsm_state(int argc, char **argv); static int lfs_hsm_set(int argc, char **argv); static int lfs_hsm_clear(int argc, char **argv); static int lfs_hsm_action(int argc, char **argv); +static int lfs_hsm_archive(int argc, char **argv); +static int lfs_hsm_restore(int argc, char **argv); +static int lfs_hsm_release(int argc, char **argv); +static int lfs_hsm_remove(int argc, char **argv); +static int lfs_hsm_cancel(int argc, char **argv); + /* all avaialable commands */ command_t cmdlist[] = { @@ -253,6 +259,22 @@ command_t cmdlist[] = { "[--archived] [--lost] ..."}, {"hsm_action", lfs_hsm_action, 0, "Display current HSM request for " "given files.\n" "usage: hsm_action ..."}, + {"hsm_archive", lfs_hsm_archive, 0, + "Archive file to external storage.\n" + "usage: hsm_archive [--filelist FILELIST] [--data DATA] [--archive NUM] " + " ..."}, + {"hsm_restore", lfs_hsm_restore, 0, + "Restore file from external storage.\n" + "usage: hsm_restore [--filelist FILELIST] [--data DATA] ..."}, + {"hsm_release", lfs_hsm_release, 0, + "Release files from Lustre.\n" + "usage: hsm_release [--filelist FILELIST] [--data DATA] ..."}, + {"hsm_remove", lfs_hsm_remove, 0, + "Remove file copy from external storage.\n" + "usage: hsm_remove [--filelist FILELIST] [--data DATA] ..."}, + {"hsm_cancel", lfs_hsm_cancel, 0, + "Cancel requests related to specified files.\n" + "usage: hsm_cancel [--filelist FILELIST] [--data DATA] ..."}, {"help", Parser_help, 0, "help"}, {"exit", Parser_quit, 0, "quit"}, {"quit", Parser_quit, 0, "quit"}, @@ -2917,6 +2939,240 @@ static int lfs_hsm_clear(int argc, char **argv) return lfs_hsm_change_flags(argc, argv, LFS_HSM_CLEAR); } +/** + * Check file state and return its fid, to be used by lfs_hsm_request(). + * + * \param[in] file Path to file to check + * \param[in,out] fid Pointer to allocated lu_fid struct. + * \param[in,out] last_dev Pointer to last device id used. + * + * \return 0 on success. + */ +static int lfs_hsm_prepare_file(char *file, struct lu_fid *fid, + dev_t *last_dev) +{ + struct stat st; + int rc; + + rc = lstat(file, &st); + if (rc) { + fprintf(stderr, "Cannot stat %s: %s\n", file, strerror(-errno)); + return -errno; + } + /* A request should be ... */ + if (*last_dev != st.st_dev && *last_dev != 0) { + fprintf(stderr, "All files should be " + "on the same filesystem: %s\n", file); + return -EINVAL; + } + *last_dev = st.st_dev; + + rc = llapi_path2fid(file, fid); + if (rc) { + fprintf(stderr, "Cannot read FID of %s: %s\n", + file, strerror(-rc)); + return rc; + } + return 0; +} + +static int lfs_hsm_request(int argc, char **argv, int action) +{ + struct option long_opts[] = { + {"filelist", 1, 0, 'l'}, + {"data", 1, 0, 'D'}, + {"archive", 1, 0, 'a'}, + {0, 0, 0, 0} + }; + dev_t last_dev = 0; + char short_opts[] = "l:D:a:"; + struct hsm_user_request *hur, *oldhur; + int c, i; + size_t len; + int nbfile; + char *line = NULL; + char *filelist = NULL; + char fullpath[PATH_MAX]; + char *opaque = NULL; + int opaque_len = 0; + int archive_id = 0; + FILE *fp; + int nbfile_alloc = 0; + char some_file[PATH_MAX+1] = ""; + int rc; + + if (argc < 2) + return CMD_HELP; + + optind = 0; + while ((c = getopt_long(argc, argv, short_opts, + long_opts, NULL)) != -1) { + switch (c) { + case 'l': + filelist = optarg; + break; + case 'D': + opaque = optarg; + break; + case 'a': + if (action != HUA_ARCHIVE) { + fprintf(stderr, + "error: -a is supported only " + "when archiving\n"); + return CMD_HELP; + } + archive_id = atoi(optarg); + break; + case '?': + return CMD_HELP; + default: + fprintf(stderr, "error: %s: option '%s' unrecognized\n", + argv[0], argv[optind - 1]); + return CMD_HELP; + } + } + + /* All remaining args are files, so we have at least nbfile */ + nbfile = argc - optind; + + if ((nbfile == 0) && (filelist == NULL)) + return CMD_HELP; + + if (opaque != NULL) + opaque_len = strlen(opaque); + + /* Alloc the request structure with enough place to store all files + * from command line. */ + hur = llapi_hsm_user_request_alloc(nbfile, opaque_len); + if (hur == NULL) { + fprintf(stderr, "Cannot create the request: %s\n", + strerror(errno)); + return errno; + } + nbfile_alloc = nbfile; + + hur->hur_request.hr_action = action; + hur->hur_request.hr_archive_id = archive_id; + hur->hur_request.hr_flags = 0; + + /* All remaining args are files, add them */ + if (nbfile != 0) + strcpy(some_file, argv[optind]); + + for (i = 0; i < nbfile; i++) { + hur->hur_user_item[i].hui_extent.length = -1; + rc = lfs_hsm_prepare_file(argv[optind + i], + &hur->hur_user_item[i].hui_fid, + &last_dev); + hur->hur_request.hr_itemcount++; + if (rc) + goto out_free; + } + + /* from here stop using nb_file, use hur->hur_request.hr_itemcount */ + + /* If a filelist was specified, read the filelist from it. */ + if (filelist != NULL) { + fp = fopen(filelist, "r"); + if (fp == NULL) { + fprintf(stderr, "Cannot read the file list %s: %s\n", + filelist, strerror(errno)); + rc = -errno; + goto out_free; + } + + while ((rc = getline(&line, &len, fp)) != -1) { + struct hsm_user_item *hui; + + /* If allocated buffer was too small, gets something + * bigger */ + if (nbfile_alloc <= hur->hur_request.hr_itemcount) { + nbfile_alloc = nbfile_alloc * 2 + 1; + oldhur = hur; + hur = llapi_hsm_user_request_alloc(nbfile_alloc, + opaque_len); + if (hur == NULL) { + fprintf(stderr, "Cannot allocate " + "the request: %s\n", + strerror(errno)); + hur = oldhur; + rc = -errno; + goto out_free; + } + memcpy(hur, oldhur, hur_len(oldhur)); + free(oldhur); + } + + /* Chop CR */ + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + hui = + &hur->hur_user_item[hur->hur_request.hr_itemcount]; + hui->hui_extent.length = -1; + rc = lfs_hsm_prepare_file(line, &hui->hui_fid, + &last_dev); + hur->hur_request.hr_itemcount++; + if (rc) + goto out_free; + + if ((some_file[0] == '\0') && + (strlen(line) < sizeof(some_file))) + strcpy(some_file, line); + } + + rc = fclose(fp); + if (line) + free(line); + } + + /* If a --data was used, add it to the request */ + hur->hur_request.hr_data_len = opaque_len; + if (opaque != NULL) + memcpy(hur_data(hur), opaque, opaque_len); + + /* Send the HSM request */ + if (realpath(some_file, fullpath) == NULL) { + fprintf(stderr, "Could not find path '%s': %s\n", + some_file, strerror(errno)); + } + rc = llapi_hsm_request(fullpath, hur); + if (rc) { + fprintf(stderr, "Cannot send HSM request (use of %s): %s\n", + some_file, strerror(-rc)); + goto out_free; + } + +out_free: + free(hur); + return rc; +} + +static int lfs_hsm_archive(int argc, char **argv) +{ + return lfs_hsm_request(argc, argv, HUA_ARCHIVE); +} + +static int lfs_hsm_restore(int argc, char **argv) +{ + return lfs_hsm_request(argc, argv, HUA_RESTORE); +} + +static int lfs_hsm_release(int argc, char **argv) +{ + return lfs_hsm_request(argc, argv, HUA_RELEASE); +} + +static int lfs_hsm_remove(int argc, char **argv) +{ + return lfs_hsm_request(argc, argv, HUA_REMOVE); +} + +static int lfs_hsm_cancel(int argc, char **argv) +{ + return lfs_hsm_request(argc, argv, HUA_CANCEL); +} + int main(int argc, char **argv) { int rc; diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 3bf8cfa..814ab2c 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -235,12 +235,12 @@ int llapi_hsm_copytool_recv(void *priv, struct hsm_action_list **halh, /* Check that we have registered for this archive # * if 0 registered, we serve any archive */ if (ct->archives && - ((1 << (hal->hal_archive_num - 1)) & ct->archives) == 0) { + ((1 << (hal->hal_archive_id - 1)) & ct->archives) == 0) { llapi_err_noerrno(LLAPI_MSG_INFO, "This copytool does not service archive #%d," " ignoring this request." " Mask of served archive is 0x%.8X", - hal->hal_archive_num, ct->archives); + hal->hal_archive_id, ct->archives); rc = -EAGAIN; goto out_free; @@ -539,3 +539,46 @@ int llapi_hsm_current_action(const char *path, struct hsm_current_action *hca) return rc; } +/** + * Allocate a hsm_user_request with the specified carateristics. + * This structure should be freed with free(). + * + * \return an allocated structure on success, NULL otherwise. + */ +struct hsm_user_request *llapi_hsm_user_request_alloc(int itemcount, + int data_len) +{ + int len = 0; + + len += sizeof(struct hsm_user_request); + len += sizeof(struct hsm_user_item) * itemcount; + len += data_len; + + return (struct hsm_user_request *)malloc(len); +} + +/** + * Send a HSM request to Lustre, described in \param request. + * + * This request should be allocated with llapi_hsm_user_request_alloc(). + * + * \param mnt Should be the Lustre moint point. + * \return 0 on success, an error code otherwise. + */ +int llapi_hsm_request(char *mnt, struct hsm_user_request *request) +{ + int rc; + int fd; + + rc = get_root_path(WANT_FD, NULL, &fd, mnt, -1); + if (rc) + return rc; + + rc = ioctl(fd, LL_IOC_HSM_REQUEST, request); + /* If error, save errno value */ + rc = rc ? -errno : 0; + + close(fd); + return rc; +} + diff --git a/lustre/utils/req-layout.c b/lustre/utils/req-layout.c index c45eb2a..cf41176 100644 --- a/lustre/utils/req-layout.c +++ b/lustre/utils/req-layout.c @@ -88,6 +88,7 @@ #define lustre_swab_hsm_user_state NULL #define lustre_swab_hsm_state_set NULL #define lustre_swab_hsm_current_action NULL +#define lustre_swab_hsm_request NULL #define dump_rniobuf NULL #define dump_ioo NULL #define dump_obdo NULL diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index 913f72b..56b9eab 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -1891,7 +1891,7 @@ check_hsm_action_list(void) CHECK_MEMBER(hsm_action_list, hal_count); CHECK_MEMBER(hsm_action_list, hal_compound_id); CHECK_MEMBER(hsm_action_list, hal_flags); - CHECK_MEMBER(hsm_action_list, hal_archive_num); + CHECK_MEMBER(hsm_action_list, hal_archive_id); CHECK_MEMBER(hsm_action_list, padding1); CHECK_MEMBER(hsm_action_list, hal_fsname); } @@ -1977,6 +1977,29 @@ check_hsm_current_action(void) } static void +check_hsm_request(void) +{ + BLANK_LINE(); + CHECK_STRUCT(hsm_request); + CHECK_MEMBER(hsm_request, hr_action); + CHECK_MEMBER(hsm_request, hr_archive_id); + CHECK_MEMBER(hsm_request, hr_flags); + CHECK_MEMBER(hsm_request, hr_itemcount); + CHECK_MEMBER(hsm_request, hr_data_len); + CHECK_VALUE_X(HSM_FORCE_ACTION); + CHECK_VALUE_X(HSM_GHOST_COPY); +} + +static void +check_hsm_user_request(void) +{ + BLANK_LINE(); + CHECK_STRUCT(hsm_user_request); + CHECK_MEMBER(hsm_user_request, hur_request); + CHECK_MEMBER(hsm_user_request, hur_user_item); +} + +static void system_string (char *cmdline, char *str, int len) { int fds[2]; @@ -2344,6 +2367,8 @@ main(int argc, char **argv) check_hsm_user_state(); check_hsm_state_set(); check_hsm_current_action(); + check_hsm_request(); + check_hsm_user_request(); printf("}\n\n"); diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index 95a32d5..306a444 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -4217,10 +4217,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct hsm_action_list, hal_flags)); LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_flags) == 8, "found %lld\n", (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_flags)); - LASSERTF((int)offsetof(struct hsm_action_list, hal_archive_num) == 24, "found %lld\n", - (long long)(int)offsetof(struct hsm_action_list, hal_archive_num)); - LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_archive_num) == 4, "found %lld\n", - (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_archive_num)); + LASSERTF((int)offsetof(struct hsm_action_list, hal_archive_id) == 24, "found %lld\n", + (long long)(int)offsetof(struct hsm_action_list, hal_archive_id)); + LASSERTF((int)sizeof(((struct hsm_action_list *)0)->hal_archive_id) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_action_list *)0)->hal_archive_id)); LASSERTF((int)offsetof(struct hsm_action_list, padding1) == 28, "found %lld\n", (long long)(int)offsetof(struct hsm_action_list, padding1)); LASSERTF((int)sizeof(((struct hsm_action_list *)0)->padding1) == 4, "found %lld\n", @@ -4390,5 +4390,45 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct hsm_current_action, hca_location)); LASSERTF((int)sizeof(((struct hsm_current_action *)0)->hca_location) == 16, "found %lld\n", (long long)(int)sizeof(((struct hsm_current_action *)0)->hca_location)); + + /* Checks for struct hsm_request */ + LASSERTF((int)sizeof(struct hsm_request) == 24, "found %lld\n", + (long long)(int)sizeof(struct hsm_request)); + LASSERTF((int)offsetof(struct hsm_request, hr_action) == 0, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_action)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_action) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_action)); + LASSERTF((int)offsetof(struct hsm_request, hr_archive_id) == 4, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_archive_id)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_archive_id) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_archive_id)); + LASSERTF((int)offsetof(struct hsm_request, hr_flags) == 8, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_flags)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_flags) == 8, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_flags)); + LASSERTF((int)offsetof(struct hsm_request, hr_itemcount) == 16, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_itemcount)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_itemcount) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_itemcount)); + LASSERTF((int)offsetof(struct hsm_request, hr_data_len) == 20, "found %lld\n", + (long long)(int)offsetof(struct hsm_request, hr_data_len)); + LASSERTF((int)sizeof(((struct hsm_request *)0)->hr_data_len) == 4, "found %lld\n", + (long long)(int)sizeof(((struct hsm_request *)0)->hr_data_len)); + LASSERTF(HSM_FORCE_ACTION == 0x00000001UL, "found 0x%.8xUL\n", + (unsigned)HSM_FORCE_ACTION); + LASSERTF(HSM_GHOST_COPY == 0x00000002UL, "found 0x%.8xUL\n", + (unsigned)HSM_GHOST_COPY); + + /* Checks for struct hsm_user_request */ + LASSERTF((int)sizeof(struct hsm_user_request) == 24, "found %lld\n", + (long long)(int)sizeof(struct hsm_user_request)); + LASSERTF((int)offsetof(struct hsm_user_request, hur_request) == 0, "found %lld\n", + (long long)(int)offsetof(struct hsm_user_request, hur_request)); + LASSERTF((int)sizeof(((struct hsm_user_request *)0)->hur_request) == 24, "found %lld\n", + (long long)(int)sizeof(((struct hsm_user_request *)0)->hur_request)); + LASSERTF((int)offsetof(struct hsm_user_request, hur_user_item) == 24, "found %lld\n", + (long long)(int)offsetof(struct hsm_user_request, hur_user_item)); + LASSERTF((int)sizeof(((struct hsm_user_request *)0)->hur_user_item) == 0, "found %lld\n", + (long long)(int)sizeof(((struct hsm_user_request *)0)->hur_user_item)); } -- 1.8.3.1