extern struct obd_export *class_conn2export(struct lustre_handle *conn);
-#define KKUC_CT_DATA_MAGIC 0x092013cea
+static inline int exp_connect_archive_id_array(struct obd_export *exp)
+{
+ return !!(exp_connect_flags2(exp) & OBD_CONNECT2_ARCHIVE_ID_ARRAY);
+}
+
+enum {
+ /* archive_ids in array format */
+ KKUC_CT_DATA_ARRAY_MAGIC = 0x092013cea,
+ /* archive_ids in bitmap format */
+ KKUC_CT_DATA_BITMAP_MAGIC = 0x082018cea,
+};
+
+
struct kkuc_ct_data {
__u32 kcd_magic;
- __u32 kcd_archive;
+ __u32 kcd_nr_archives;
+ __u32 kcd_archives[0];
};
/** @} export */
const struct lu_fid *fid,
__u32 compat, __u32 incompat);
-/* copytool uses a 32b bitmask field to encode archive-Ids during register
- * with MDT thru kuc.
+/* copytool can use any nonnegative integer to represent archive-Ids during
+ * register with MDT thru kuc.
* archive num = 0 => all
- * archive num from 1 to 32
+ * archive num from 1 to MAX_U32
*/
-#define LL_HSM_MAX_ARCHIVE (sizeof(__u32) * 8)
+#define LL_HSM_ORIGIN_MAX_ARCHIVE (sizeof(__u32) * 8)
+/* the max count of archive ids that one agent can support */
+#define LL_HSM_MAX_ARCHIVES_PER_AGENT 1024
/**
* HSM on-disk attributes stored in a separate xattr.
#define MDT_CONNECT_SUPPORTED2 (OBD_CONNECT2_FILE_SECCTX | OBD_CONNECT2_FLR | \
OBD_CONNECT2_SUM_STATFS | \
OBD_CONNECT2_LOCK_CONVERT | \
- OBD_CONNECT2_DIR_MIGRATE)
+ OBD_CONNECT2_DIR_MIGRATE | \
+ OBD_CONNECT2_ARCHIVE_ID_ARRAY)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
#define KUC_GRP_HSM 0x02
#define KUC_GRP_MAX KUC_GRP_HSM
-#define LK_FLG_STOP 0x01
+enum lk_flags {
+ LK_FLG_STOP = 0x0001,
+ LK_FLG_DATANR = 0x0002,
+};
#define LK_NOFD -1U
-/* kernelcomm control structure, passed from userspace to kernel */
+/* kernelcomm control structure, passed from userspace to kernel.
+ * For compatibility with old copytools, users who pass ARCHIVE_IDs
+ * to kernel using lk_data_count and lk_data should fill lk_flags with
+ * LK_FLG_DATANR. Otherwise kernel will take lk_data_count as bitmap of
+ * ARCHIVE IDs.
+ */
struct lustre_kernelcomm {
__u32 lk_wfd;
__u32 lk_rfd;
__u32 lk_uid;
__u32 lk_group;
- __u32 lk_data;
+ __u32 lk_data_count;
__u32 lk_flags;
+ __u32 lk_data[0];
} __attribute__((packed));
#endif /* __UAPI_KERNELCOMM_H__ */
}
-static int copy_and_ioctl(int cmd, struct obd_export *exp,
- const void __user *data, size_t size)
+static int copy_and_ct_start(int cmd, struct obd_export *exp,
+ const struct lustre_kernelcomm __user *data)
{
- void *copy;
+ struct lustre_kernelcomm *lk;
+ struct lustre_kernelcomm *tmp;
+ size_t size = sizeof(*lk);
+ size_t new_size;
+ int i;
int rc;
- OBD_ALLOC(copy, size);
- if (copy == NULL)
+ /* copy data from userspace to get numbers of archive_id */
+ OBD_ALLOC(lk, size);
+ if (lk == NULL)
return -ENOMEM;
- if (copy_from_user(copy, data, size)) {
- rc = -EFAULT;
- goto out;
+ if (copy_from_user(lk, data, size))
+ GOTO(out_lk, rc = -EFAULT);
+
+ if (lk->lk_flags & LK_FLG_STOP)
+ goto do_ioctl;
+
+ if (!(lk->lk_flags & LK_FLG_DATANR)) {
+ __u32 archive_mask = lk->lk_data_count;
+ int count;
+
+ /* old hsm agent to old MDS */
+ if (!exp_connect_archive_id_array(exp))
+ goto do_ioctl;
+
+ /* old hsm agent to new MDS */
+ lk->lk_flags |= LK_FLG_DATANR;
+
+ if (archive_mask == 0)
+ goto do_ioctl;
+
+ count = hweight32(archive_mask);
+ new_size = offsetof(struct lustre_kernelcomm, lk_data[count]);
+ OBD_ALLOC(tmp, new_size);
+ if (tmp == NULL)
+ GOTO(out_lk, rc = -ENOMEM);
+
+ memcpy(tmp, lk, size);
+ tmp->lk_data_count = count;
+ OBD_FREE(lk, size);
+ lk = tmp;
+ size = new_size;
+
+ count = 0;
+ for (i = 0; i < sizeof(archive_mask) * 8; i++) {
+ if ((1 << i) & archive_mask) {
+ lk->lk_data[count] = i + 1;
+ count++;
+ }
+ }
+ goto do_ioctl;
}
- rc = obd_iocontrol(cmd, exp, size, copy, NULL);
-out:
- OBD_FREE(copy, size);
+ /* new hsm agent to new mds */
+ if (lk->lk_data_count > 0) {
+ new_size = offsetof(struct lustre_kernelcomm,
+ lk_data[lk->lk_data_count]);
+ OBD_ALLOC(tmp, new_size);
+ if (tmp == NULL)
+ GOTO(out_lk, rc = -ENOMEM);
+
+ OBD_FREE(lk, size);
+ lk = tmp;
+ size = new_size;
+
+ if (copy_from_user(lk, data, size))
+ GOTO(out_lk, rc = -EFAULT);
+ }
+
+ /* new hsm agent to old MDS */
+ if (!exp_connect_archive_id_array(exp)) {
+ __u32 archives = 0;
+
+ if (lk->lk_data_count > LL_HSM_ORIGIN_MAX_ARCHIVE)
+ GOTO(out_lk, rc = -EINVAL);
+
+ for (i = 0; i < lk->lk_data_count; i++) {
+ if (lk->lk_data[i] > LL_HSM_ORIGIN_MAX_ARCHIVE) {
+ rc = -EINVAL;
+ CERROR("%s: archive id %d requested but only "
+ "[0 - %zu] supported: rc = %d\n",
+ exp->exp_obd->obd_name, lk->lk_data[i],
+ LL_HSM_ORIGIN_MAX_ARCHIVE, rc);
+ GOTO(out_lk, rc);
+ }
+
+ if (lk->lk_data[i] == 0) {
+ archives = 0;
+ break;
+ }
+ archives |= (1 << (lk->lk_data[i] - 1));
+ }
+ lk->lk_flags &= ~LK_FLG_DATANR;
+ lk->lk_data_count = archives;
+ }
+do_ioctl:
+ rc = obd_iocontrol(cmd, exp, size, lk, NULL);
+out_lk:
+ OBD_FREE(lk, size);
return rc;
}
if (!cfs_capable(CFS_CAP_SYS_ADMIN))
RETURN(-EPERM);
- rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg,
- sizeof(struct lustre_kernelcomm));
+ rc = copy_and_ct_start(cmd, sbi->ll_md_exp,
+ (struct lustre_kernelcomm __user *)arg);
RETURN(rc);
case LL_IOC_HSM_COPY_START: {
int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
{
- struct md_op_data *op_data;
- int rc;
+ struct obd_export *exp = ll_i2mdexp(inode);
+ struct md_op_data *op_data;
+ int rc;
ENTRY;
/* Detect out-of range masks */
!cfs_capable(CFS_CAP_SYS_ADMIN))
RETURN(-EPERM);
- /* Detect out-of range archive id */
- if ((hss->hss_valid & HSS_ARCHIVE_ID) &&
- (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE))
- RETURN(-EINVAL);
+ if (!exp_connect_archive_id_array(exp)) {
+ /* Detect out-of range archive id */
+ if ((hss->hss_valid & HSS_ARCHIVE_ID) &&
+ (hss->hss_archive_id > LL_HSM_ORIGIN_MAX_ARCHIVE))
+ RETURN(-EINVAL);
+ }
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
LUSTRE_OPC_ANY, hss);
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
- rc = obd_iocontrol(LL_IOC_HSM_STATE_SET, ll_i2mdexp(inode),
- sizeof(*op_data), op_data, NULL);
+ rc = obd_iocontrol(LL_IOC_HSM_STATE_SET, exp, sizeof(*op_data),
+ op_data, NULL);
ll_finish_md_op_data(op_data);
data->ocd_connect_flags2 = OBD_CONNECT2_FLR |
OBD_CONNECT2_LOCK_CONVERT |
OBD_CONNECT2_DIR_MIGRATE |
- OBD_CONNECT2_SUM_STATFS;
+ OBD_CONNECT2_SUM_STATFS |
+ OBD_CONNECT2_ARCHIVE_ID_ARRAY;
#ifdef HAVE_LRU_RESIZE_SUPPORT
if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
void __user *uarg)
{
struct lmv_obd *lmv = &obd->u.lmv;
- struct file *filp;
- __u32 i, j;
- int err;
- bool any_set = false;
- struct kkuc_ct_data kcd = {
- .kcd_magic = KKUC_CT_DATA_MAGIC,
- .kcd_archive = lk->lk_data,
- };
- int rc = 0;
+ struct file *filp;
+ __u32 i, j;
+ int err;
+ bool any_set = false;
+ struct kkuc_ct_data *kcd;
+ size_t kcd_size;
+ int rc = 0;
ENTRY;
filp = fget(lk->lk_wfd);
if (!filp)
RETURN(-EBADF);
+ if (lk->lk_flags & LK_FLG_DATANR)
+ kcd_size = offsetof(struct kkuc_ct_data,
+ kcd_archives[lk->lk_data_count]);
+ else
+ kcd_size = sizeof(*kcd);
+
+ OBD_ALLOC(kcd, kcd_size);
+ if (kcd == NULL)
+ GOTO(err_fput, rc = -ENOMEM);
+
+ kcd->kcd_nr_archives = lk->lk_data_count;
+ if (lk->lk_flags & LK_FLG_DATANR) {
+ kcd->kcd_magic = KKUC_CT_DATA_ARRAY_MAGIC;
+ if (lk->lk_data_count > 0)
+ memcpy(kcd->kcd_archives, lk->lk_data,
+ sizeof(*kcd->kcd_archives) * lk->lk_data_count);
+ } else {
+ kcd->kcd_magic = KKUC_CT_DATA_BITMAP_MAGIC;
+ }
+
rc = libcfs_kkuc_group_add(filp, &obd->obd_uuid, lk->lk_uid,
- lk->lk_group, &kcd, sizeof(kcd));
+ lk->lk_group, kcd, kcd_size);
+ OBD_FREE(kcd, kcd_size);
if (rc)
GOTO(err_fput, rc);
ptlrpc_req_finished(req);
return rc;
}
-
-static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives)
+/**
+ * Send hsm_ct_register to MDS
+ *
+ * \param[in] imp import
+ * \param[in] archive_count if in bitmap format, it is the bitmap,
+ * else it is the count of archive_ids
+ * \param[in] archives if in bitmap format, it is NULL,
+ * else it is archive_id lists
+ */
+static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archive_count,
+ __u32 *archives)
{
- __u32 *archive_mask;
- struct ptlrpc_request *req;
- int rc;
+ struct ptlrpc_request *req;
+ __u32 *archive_array;
+ size_t archives_size;
+ int rc;
ENTRY;
- req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_CT_REGISTER,
- LUSTRE_MDS_VERSION,
- MDS_HSM_CT_REGISTER);
+ req = ptlrpc_request_alloc(imp, &RQF_MDS_HSM_CT_REGISTER);
if (req == NULL)
- GOTO(out, rc = -ENOMEM);
+ RETURN(-ENOMEM);
+
+ if (archives != NULL)
+ archives_size = sizeof(*archive_array) * archive_count;
+ else
+ archives_size = sizeof(archive_count);
+
+ req_capsule_set_size(&req->rq_pill, &RMF_MDS_HSM_ARCHIVE,
+ RCL_CLIENT, archives_size);
+
+ rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_HSM_CT_REGISTER);
+ if (rc) {
+ ptlrpc_request_free(req);
+ RETURN(-ENOMEM);
+ }
mdc_pack_body(req, NULL, 0, 0, -1, 0);
- /* Copy hsm_progress struct */
- archive_mask = req_capsule_client_get(&req->rq_pill,
- &RMF_MDS_HSM_ARCHIVE);
- if (archive_mask == NULL)
+ archive_array = req_capsule_client_get(&req->rq_pill,
+ &RMF_MDS_HSM_ARCHIVE);
+ if (archive_array == NULL)
GOTO(out, rc = -EPROTO);
- *archive_mask = archives;
+ if (archives != NULL)
+ memcpy(archive_array, archives, archives_size);
+ else
+ *archive_array = archive_count;
ptlrpc_request_set_replen(req);
static int mdc_ioc_hsm_ct_start(struct obd_export *exp,
struct lustre_kernelcomm *lk)
{
- struct obd_import *imp = class_exp2cliimp(exp);
- __u32 archive = lk->lk_data;
- int rc = 0;
+ struct obd_import *imp = class_exp2cliimp(exp);
+ int rc = 0;
if (lk->lk_group != KUC_GRP_HSM) {
CERROR("Bad copytool group %d\n", lk->lk_group);
/* Unregister with the coordinator */
rc = mdc_ioc_hsm_ct_unregister(imp);
} else {
- rc = mdc_ioc_hsm_ct_register(imp, archive);
+ __u32 *archives = NULL;
+
+ if ((lk->lk_flags & LK_FLG_DATANR) && lk->lk_data_count > 0)
+ archives = lk->lk_data;
+
+ rc = mdc_ioc_hsm_ct_register(imp, lk->lk_data_count, archives);
}
return rc;
*/
static int mdc_hsm_ct_reregister(void *data, void *cb_arg)
{
- struct kkuc_ct_data *kcd = data;
- struct obd_import *imp = (struct obd_import *)cb_arg;
- int rc;
+ struct obd_import *imp = (struct obd_import *)cb_arg;
+ struct kkuc_ct_data *kcd = data;
+ __u32 *archives = NULL;
+ int rc;
- if (kcd == NULL || kcd->kcd_magic != KKUC_CT_DATA_MAGIC)
+ if (kcd == NULL ||
+ (kcd->kcd_magic != KKUC_CT_DATA_ARRAY_MAGIC &&
+ kcd->kcd_magic != KKUC_CT_DATA_BITMAP_MAGIC))
return -EPROTO;
- CDEBUG(D_HA, "%s: recover copytool registration to MDT (archive=%#x)\n",
- imp->imp_obd->obd_name, kcd->kcd_archive);
- rc = mdc_ioc_hsm_ct_register(imp, kcd->kcd_archive);
+ if (kcd->kcd_magic == KKUC_CT_DATA_BITMAP_MAGIC) {
+ CDEBUG(D_HA, "%s: recover copytool registration to MDT "
+ "(archive=%#x)\n", imp->imp_obd->obd_name,
+ kcd->kcd_nr_archives);
+ } else {
+ CDEBUG(D_HA, "%s: recover copytool registration to MDT "
+ "(archive nr = %u)\n",
+ imp->imp_obd->obd_name, kcd->kcd_nr_archives);
+ if (kcd->kcd_nr_archives != 0)
+ archives = kcd->kcd_archives;
+ }
+ rc = mdc_ioc_hsm_ct_register(imp, kcd->kcd_nr_archives, archives);
/* ignore error if the copytool is already registered */
return (rc == -EEXIST) ? 0 : rc;
}
int mdt_hsm_ct_register(struct tgt_session_info *tsi)
{
- struct mdt_thread_info *info;
- __u32 *archives;
- int rc;
+ struct mdt_thread_info *info = tsi2mdt_info(tsi);
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct obd_export *exp = req->rq_export;
+ size_t archives_size;
+ __u32 *archives;
+ int archive_count;
+ int rc;
ENTRY;
+ if (!mdt_hsm_is_admin(info))
+ GOTO(out, rc = -EPERM);
+
archives = req_capsule_client_get(tsi->tsi_pill, &RMF_MDS_HSM_ARCHIVE);
if (archives == NULL)
- RETURN(err_serious(-EPROTO));
+ GOTO(out, rc = err_serious(-EPROTO));
- info = tsi2mdt_info(tsi);
- if (!mdt_hsm_is_admin(info))
- GOTO(out, rc = -EPERM);
+ archives_size = req_capsule_get_size(tsi->tsi_pill,
+ &RMF_MDS_HSM_ARCHIVE, RCL_CLIENT);
+
+ /* compatibility check for the old clients */
+ if (!exp_connect_archive_id_array(exp)) {
+ if (archives_size != sizeof(*archives))
+ GOTO(out, rc = err_serious(-EPROTO));
+
+ /* XXX: directly include this function here? */
+ rc = mdt_hsm_agent_register_mask(info,
+ &tsi->tsi_exp->exp_client_uuid,
+ *archives);
+ GOTO(out, rc);
+ }
+
+ if (archives_size % sizeof(*archives) != 0)
+ GOTO(out, rc = err_serious(-EPROTO));
+
+ archive_count = archives_size / sizeof(*archives);
+ if (archive_count == 1 && *archives == 0) {
+ archive_count = 0;
+ archives = NULL;
+ }
+
+ rc = mdt_hsm_agent_register(info, &tsi->tsi_exp->exp_client_uuid,
+ archive_count, archives);
- /* XXX: directly include this function here? */
- rc = mdt_hsm_agent_register_mask(info, &tsi->tsi_exp->exp_client_uuid,
- *archives);
out:
mdt_thread_info_fini(info);
RETURN(rc);
/* Change archive_id if provided. */
if (hss->hss_valid & HSS_ARCHIVE_ID) {
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct obd_export *exp = req->rq_export;
+
if (!(ma->ma_hsm.mh_flags & HS_EXISTS)) {
CDEBUG(D_HSM, "Could not set an archive number for "
DFID "if HSM EXISTS flag is not set.\n",
GOTO(out_unlock, rc);
}
- /* Detect out-of range archive id */
- if (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE) {
- CDEBUG(D_HSM, "archive id %u exceeds maximum %zu.\n",
- hss->hss_archive_id, LL_HSM_MAX_ARCHIVE);
+ if (!exp_connect_archive_id_array(exp) &&
+ hss->hss_archive_id > LL_HSM_ORIGIN_MAX_ARCHIVE) {
+ CDEBUG(D_HSM, "archive id %u from old clients "
+ "exceeds maximum %zu.\n",
+ hss->hss_archive_id, LL_HSM_ORIGIN_MAX_ARCHIVE);
GOTO(out_unlock, rc = -EINVAL);
}
EXPORT_SYMBOL(RMF_MDS_HSM_USER_ITEM);
struct req_msg_field RMF_MDS_HSM_ARCHIVE =
- DEFINE_MSGF("hsm_archive", 0,
+ DEFINE_MSGF("hsm_archive", RMF_F_STRUCT_ARRAY,
sizeof(__u32), lustre_swab_generic_32s, NULL);
EXPORT_SYMBOL(RMF_MDS_HSM_ARCHIVE);
static char fsmountdir[PATH_MAX]; /* Lustre mountpoint */
static char *lustre_dir; /* Test directory inside Lustre */
+static bool is_bitmap;
#define ERROR(fmt, ...) \
fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
int rc;
struct hsm_copytool_private *ctdata;
int archives[33];
+ int count = sizeof(archives) / sizeof(*archives);
rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 1, NULL, 0);
ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
strerror(-rc));
- rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 33, NULL, 0);
+ rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, count, NULL, 0);
ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
strerror(-rc));
- memset(archives, 1, sizeof(archives));
- rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 34, archives, 0);
- ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
- strerror(-rc));
+ if (is_bitmap) {
+ int i;
+
+ for (i = 0; i < count; i++)
+ archives[i] = i + 1;
+ rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
+ count, archives, 0);
+ ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
+ strerror(-rc));
+ }
#if 0
/* BUG? Should that fail or not? */
int rc;
int fd;
int i;
+ int test_count;
struct hsm_user_state hus;
fd = create_testfile(100);
ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
/* Set archive id */
- for (i = 0; i <= 32; i++) {
+ if (is_bitmap)
+ test_count = 32;
+ else
+ test_count = 48;
+ for (i = 0; i <= test_count; i++) {
rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, i);
ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s",
strerror(-rc));
rc = llapi_hsm_state_get_fd(fd, &hus);
- ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s",
+ ASSERTF(rc == 0, "llapi_hsm_state_get_fd failed: %s",
strerror(-rc));
ASSERTF(hus.hus_states == HS_EXISTS, "state=%u",
hus.hus_states);
hus.hus_archive_id, i);
}
- /* Invalid archive numbers */
- rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 33);
- ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s", strerror(-rc));
+ if (is_bitmap) {
+ /* Invalid archive numbers */
+ rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 33);
+ ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
+ strerror(-rc));
- rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 151);
- ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s", strerror(-rc));
+ rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 151);
+ ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
+ strerror(-rc));
- rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, -1789);
- ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s", strerror(-rc));
+ rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, -1789);
+ ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
+ strerror(-rc));
+ }
/* Settable flags, with respect of the HSM file state transition rules:
* DIRTY without EXISTS: no dirty if no archive was created
{
int c;
- while ((c = getopt(argc, argv, "d:")) != -1) {
+ while ((c = getopt(argc, argv, "bd:")) != -1) {
switch (c) {
case 'd':
lustre_dir = optarg;
break;
+ case 'b':
+ is_bitmap = true;
+ break;
case '?':
default:
fprintf(stderr, "Unknown option '%c'\n", optopt);
[[ $st == $LOCAL_HSM_ARCHIVE_NUMBER ]] ||
error "wrong archive number, $st != $LOCAL_HSM_ARCHIVE_NUMBER"
- # Test whether setting archive number > 32 results in error.
- $LFS hsm_set --exists --archive-id 33 $f &&
- error "archive number is larger than 32"
- check_hsm_flags_user $f "0x00000001"
+ LOCAL_HSM_ARCHIVE_NUMBER=33
+ if [ $(lustre_version_code client) -ge $(version_code 2.11.56) ] &&
+ [ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.11.56) ]; then
+ # lustre in the new version supports unlimited archiveID.
+ # Test whether setting archive number > 32 is supported
+ $LFS hsm_set --exists --archive-id $LOCAL_HSM_ARCHIVE_NUMBER $f ||
+ error "archive ID $LOCAL_HSM_ARCHIVE_NUMBER too large?"
+ check_hsm_flags_user $f "0x00000001"
+
+ echo "verifying archive number is $LOCAL_HSM_ARCHIVE_NUMBER"
+ st=$(get_hsm_archive_id $f)
+ [[ $st == $LOCAL_HSM_ARCHIVE_NUMBER ]] ||
+ error "wrong archive number, $st != $LOCAL_HSM_ARCHIVE_NUMBER"
+ else
+ # old client or old mds can only support at most 32 archiveID
+ # test whether setting archive number > 32 results in error.
+ $LFS hsm_set --exists --archive-id $LOCAL_HSM_ARCHIVE_NUMBER $f &&
+ error "bitmap archive number is larger than 32"
+ check_hsm_flags_user $f "0x00000001"
+ fi
# Test whether setting archive number 16 and archived flag.
LOCAL_HSM_ARCHIVE_NUMBER=16
skip "HSM migrate is not supported"
test_mkdir -p $DIR/$tdir
- llapi_hsm_test -d $DIR/$tdir || error "One llapi HSM test failed"
+
+ if [ $(lustre_version_code client) -lt $(version_code 2.11.56) ] ||
+ [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.56) ];
+ then
+ llapi_hsm_test -d $DIR/$tdir -b ||
+ error "One llapi HSM test failed"
+ else
+ llapi_hsm_test -d $DIR/$tdir ||
+ error "One llapi HSM test failed"
+ fi
}
run_test 500 "various LLAPI HSM tests"
int o_shadow_tree;
int o_verbose;
int o_copy_xattrs;
- int o_archive_cnt;
- int o_archive_id[LL_HSM_MAX_ARCHIVE + 1];
+ int o_archive_id_used;
+ int o_archive_id_cnt;
+ int *o_archive_id;
int o_report_int;
unsigned long long o_bandwidth;
size_t o_chunk_size;
.has_arg = required_argument },
{ .val = 'v', .name = "verbose", .has_arg = no_argument },
{ .name = NULL } };
- int c, rc;
- unsigned long long value;
- unsigned long long unit;
+ unsigned long long value;
+ unsigned long long unit;
+ bool all_id = false;
+ int c, rc;
+ int i;
optind = 0;
+
+ opt.o_archive_id_cnt = LL_HSM_ORIGIN_MAX_ARCHIVE;
+ opt.o_archive_id = malloc(opt.o_archive_id_cnt *
+ sizeof(*opt.o_archive_id));
+ if (opt.o_archive_id == NULL)
+ return -ENOMEM;
+repeat:
while ((c = getopt_long(argc, argv, "A:b:c:f:hiMp:qru:v",
long_opts, NULL)) != -1) {
switch (c) {
optarg);
return rc;
}
+ /* if archiveID is zero, any archiveID is accepted */
+ if (all_id == true)
+ goto repeat;
+
+ if (val == 0) {
+ free(opt.o_archive_id);
+ opt.o_archive_id = NULL;
+ opt.o_archive_id_cnt = 0;
+ opt.o_archive_id_used = 0;
+ all_id = true;
+ CT_WARN("archive-id = 0 is found, any backend"
+ "will be served\n");
+ goto repeat;
+ }
- if (opt.o_archive_cnt > LL_HSM_MAX_ARCHIVE ||
- val > LL_HSM_MAX_ARCHIVE) {
- rc = -EINVAL;
- CT_ERROR(rc, "archive number must be less"
- " than %zu", LL_HSM_MAX_ARCHIVE + 1);
- return rc;
+ /* skip the duplicated id */
+ for (i = 0; i < opt.o_archive_id_used; i++) {
+ if (opt.o_archive_id[i] == val)
+ goto repeat;
}
- opt.o_archive_id[opt.o_archive_cnt] = val;
- opt.o_archive_cnt++;
+ /* extend the space */
+ if (opt.o_archive_id_used >= opt.o_archive_id_cnt) {
+ int *tmp;
+
+ opt.o_archive_id_cnt *= 2;
+ tmp = realloc(opt.o_archive_id,
+ sizeof(*opt.o_archive_id) *
+ opt.o_archive_id_cnt);
+ if (tmp == NULL)
+ return -ENOMEM;
+
+ opt.o_archive_id = tmp;
+ }
+
+ opt.o_archive_id[opt.o_archive_id_used++] = val;
break;
}
case 'b': /* -b and -c have both a number with unit as arg */
return 0;
rc = llapi_hsm_import(dst,
- opt.o_archive_cnt ? opt.o_archive_id[0] : 0,
+ opt.o_archive_id_used ?
+ opt.o_archive_id[0] : 0,
&st, 0, 0, 0, 0, NULL, &fid);
if (rc < 0) {
CT_ERROR(rc, "cannot import '%s' from '%s'", dst, src);
}
rc = llapi_hsm_copytool_register(&ctdata, opt.o_mnt,
- opt.o_archive_cnt,
+ opt.o_archive_id_used,
opt.o_archive_id, 0);
if (rc < 0) {
CT_ERROR(rc, "cannot start copytool interface");
}
}
+ if (opt.o_archive_id_cnt > 0) {
+ free(opt.o_archive_id);
+ opt.o_archive_id = NULL;
+ opt.o_archive_id_cnt = 0;
+ }
+
return 0;
}
/****** HSM Copytool API ********/
#define CT_PRIV_MAGIC 0xC0BE2001
struct hsm_copytool_private {
- int magic;
- char *mnt;
- struct kuc_hdr *kuch;
- int mnt_fd;
- int open_by_fid_fd;
- struct lustre_kernelcomm kuc;
- __u32 archives;
+ int magic;
+ char *mnt;
+ struct kuc_hdr *kuch;
+ int mnt_fd;
+ int open_by_fid_fd;
+ struct lustre_kernelcomm *kuc;
};
#define CP_PRIV_MAGIC 0x19880429
goto err;
rc = llapi_json_add_item(&json_items, "archive", LLAPI_JSON_INTEGER,
- &ct->archives);
+ &ct->kuc->lk_data_count);
if (rc < 0)
goto err;
return -EINVAL;
}
- if (archive_count > LL_HSM_MAX_ARCHIVE) {
- llapi_err_noerrno(LLAPI_MSG_ERROR, "%d requested when maximum "
- "of %zu archives supported", archive_count,
- LL_HSM_MAX_ARCHIVE);
- return -EINVAL;
+ for (rc = 0; rc < archive_count; rc++) {
+ /* in the list we have an all archive wildcard
+ * so move to all archives mode
+ */
+ if (archives[rc] == 0) {
+ archive_count = 0;
+ break;
+ }
}
ct = calloc(1, sizeof(*ct));
ct->magic = CT_PRIV_MAGIC;
ct->mnt_fd = -1;
ct->open_by_fid_fd = -1;
- ct->kuc.lk_rfd = LK_NOFD;
- ct->kuc.lk_wfd = LK_NOFD;
ct->mnt = strdup(mnt);
if (ct->mnt == NULL) {
goto out_err;
}
- ct->kuch = malloc(HAL_MAXSIZE + sizeof(*ct->kuch));
+ ct->kuch = calloc(1, HAL_MAXSIZE + sizeof(*ct->kuch));
if (ct->kuch == NULL) {
rc = -ENOMEM;
goto out_err;
goto out_err;
}
- /* no archives specified means "match all". */
- ct->archives = 0;
+ ct->kuc = malloc(sizeof(*ct) + archive_count * sizeof(__u32));
+ if (ct->kuc == NULL) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ ct->kuc->lk_rfd = LK_NOFD;
+ ct->kuc->lk_wfd = LK_NOFD;
+
+ rc = libcfs_ukuc_start(ct->kuc, KUC_GRP_HSM, rfd_flags);
+ if (rc < 0)
+ goto out_free_kuc;
+
+ ct->kuc->lk_flags = LK_FLG_DATANR;
+ ct->kuc->lk_data_count = archive_count;
for (rc = 0; rc < archive_count; rc++) {
- if ((archives[rc] > LL_HSM_MAX_ARCHIVE) || (archives[rc] < 0)) {
+ if (archives[rc] < 0) {
llapi_err_noerrno(LLAPI_MSG_ERROR, "%d requested when "
- "archive id [0 - %zu] is supported",
- archives[rc], LL_HSM_MAX_ARCHIVE);
+ "archive id >= 0 is supported",
+ archives[rc]);
rc = -EINVAL;
- goto out_err;
- }
- /* in the list we have an all archive wildcard
- * so move to all archives mode
- */
- if (archives[rc] == 0) {
- ct->archives = 0;
- archive_count = 0;
- break;
+ goto out_kuc;
}
- ct->archives |= (1 << (archives[rc] - 1));
- }
- rc = libcfs_ukuc_start(&ct->kuc, KUC_GRP_HSM, rfd_flags);
- if (rc < 0)
- goto out_err;
+ ct->kuc->lk_data[rc] = archives[rc];
+ }
- /* Storing archive(s) in lk_data; see mdc_ioc_hsm_ct_start */
- ct->kuc.lk_data = ct->archives;
- rc = ioctl(ct->mnt_fd, LL_IOC_HSM_CT_START, &ct->kuc);
+ rc = ioctl(ct->mnt_fd, LL_IOC_HSM_CT_START, ct->kuc);
if (rc < 0) {
rc = -errno;
llapi_error(LLAPI_MSG_ERROR, rc,
llapi_hsm_log_ct_registration(&ct, CT_REGISTER);
/* Only the kernel reference keeps the write side open */
- close(ct->kuc.lk_wfd);
- ct->kuc.lk_wfd = LK_NOFD;
+ close(ct->kuc->lk_wfd);
+ ct->kuc->lk_wfd = LK_NOFD;
*priv = ct;
return 0;
out_kuc:
/* cleanup the kuc channel */
- libcfs_ukuc_stop(&ct->kuc);
+ libcfs_ukuc_stop(ct->kuc);
+
+out_free_kuc:
+ free(ct->kuc);
out_err:
if (!(ct->mnt_fd < 0))
* enters libcfs_kkuc_group_put() acquires kg_sem and blocks
* in pipe_write() due to full pipe; then we attempt to
* unregister and block on kg_sem. */
- libcfs_ukuc_stop(&ct->kuc);
+ libcfs_ukuc_stop(ct->kuc);
/* Tell the kernel to stop sending us messages */
- ct->kuc.lk_flags = LK_FLG_STOP;
- ioctl(ct->mnt_fd, LL_IOC_HSM_CT_START, &ct->kuc);
+ ct->kuc->lk_flags = LK_FLG_STOP;
+ ioctl(ct->mnt_fd, LL_IOC_HSM_CT_START, ct->kuc);
llapi_hsm_log_ct_registration(&ct, CT_UNREGISTER);
close(ct->mnt_fd);
free(ct->mnt);
free(ct->kuch);
+ free(ct->kuc);
free(ct);
*priv = NULL;
if (ct == NULL || ct->magic != CT_PRIV_MAGIC)
return -EINVAL;
- return libcfs_ukuc_get_rfd(&ct->kuc);
+ return libcfs_ukuc_get_rfd(ct->kuc);
}
/** Wait for the next hsm_action_list
kuch = ct->kuch;
repeat:
- rc = libcfs_ukuc_msg_get(&ct->kuc, (char *)kuch,
+ rc = libcfs_ukuc_msg_get(ct->kuc, (char *)kuch,
HAL_MAXSIZE + sizeof(*kuch),
KUC_TRANSPORT_HSM);
if (rc < 0)
/* Check that we have registered for this archive #
* if 0 registered, we serve any archive */
- if (ct->archives &&
- ((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_id, ct->archives);
-
- goto repeat;
+ if (ct->kuc != NULL && ct->kuc->lk_data_count != 0) {
+ int i;
+
+ for (i = 0; i < ct->kuc->lk_data_count; i++) {
+ if (hal->hal_archive_id == ct->kuc->lk_data[i])
+ break;
+ }
+
+ if (i >= ct->kuc->lk_data_count)
+ goto repeat;
}
*halh = hal;