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 */
}
}
+/*
+ * 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 *****/
__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
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 */
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;
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;
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;
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);
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;
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)
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;
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:
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)
{
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)
__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++) {
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.
*/
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);
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;
+}
+
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*/
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) \
&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,
&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,
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.
*/
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",
}
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);
+
(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",
(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));
}
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);
}
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[] = {
"[--archived] [--lost] <file> ..."},
{"hsm_action", lfs_hsm_action, 0, "Display current HSM request for "
"given files.\n" "usage: hsm_action <file> ..."},
+ {"hsm_archive", lfs_hsm_archive, 0,
+ "Archive file to external storage.\n"
+ "usage: hsm_archive [--filelist FILELIST] [--data DATA] [--archive NUM] "
+ "<file> ..."},
+ {"hsm_restore", lfs_hsm_restore, 0,
+ "Restore file from external storage.\n"
+ "usage: hsm_restore [--filelist FILELIST] [--data DATA] <file> ..."},
+ {"hsm_release", lfs_hsm_release, 0,
+ "Release files from Lustre.\n"
+ "usage: hsm_release [--filelist FILELIST] [--data DATA] <file> ..."},
+ {"hsm_remove", lfs_hsm_remove, 0,
+ "Remove file copy from external storage.\n"
+ "usage: hsm_remove [--filelist FILELIST] [--data DATA] <file> ..."},
+ {"hsm_cancel", lfs_hsm_cancel, 0,
+ "Cancel requests related to specified files.\n"
+ "usage: hsm_cancel [--filelist FILELIST] [--data DATA] <file> ..."},
{"help", Parser_help, 0, "help"},
{"exit", Parser_quit, 0, "quit"},
{"quit", Parser_quit, 0, "quit"},
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;
/* 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;
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;
+}
+
#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
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);
}
}
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];
check_hsm_user_state();
check_hsm_state_set();
check_hsm_current_action();
+ check_hsm_request();
+ check_hsm_user_request();
printf("}\n\n");
(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",
(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));
}