Whamcloud - gitweb
LU-10114 hsm: increase upper limit of maximum HSM backends registered with MDT 97/32197/32
authorTeddy Zheng <teddy@ddn.com>
Tue, 13 Nov 2018 12:42:34 +0000 (07:42 -0500)
committerOleg Drokin <green@whamcloud.com>
Thu, 29 Nov 2018 22:55:54 +0000 (22:55 +0000)
Lustre only supports at most 32 HSM backends, which limits HSM to be applied
to other features, such as LPCC. This patch breaks the limitation by allowing
the system take any interger number as a valid archive-id.

Test-Parameters: clientjob=lustre-b2_10 clientbuildno=136 testlist=sanity-hsm
Test-Parameters: mdsjob=lustre-b2_10 ossjob=lustre-b2_10 serverbuildno=136 testlist=sanity-hsm

Change-Id: I9523b92500b962db3e45a2bd6a67dba54eef5335
Signed-off-by: Teddy Zheng <teddy@ddn.com>
Signed-off-by: Li Xi <lixi@ddn.com>
Reviewed-on: https://review.whamcloud.com/32197
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
14 files changed:
lustre/include/lustre_export.h
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/include/uapi/linux/lustre/lustre_kernelcomm.h
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_lib.c
lustre/lmv/lmv_obd.c
lustre/mdc/mdc_request.c
lustre/mdt/mdt_hsm.c
lustre/ptlrpc/layout.c
lustre/tests/llapi_hsm_test.c
lustre/tests/sanity-hsm.sh
lustre/utils/lhsmtool_posix.c
lustre/utils/liblustreapi_hsm.c

index 33b9aed..58f2764 100644 (file)
@@ -457,10 +457,23 @@ static inline int exp_connect_lock_convert(struct obd_export *exp)
 
 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 */
index 1275d41..1e18f32 100644 (file)
@@ -173,12 +173,14 @@ extern void lustre_loa_init(struct lustre_ost_attrs *loa,
                            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.
@@ -881,7 +883,8 @@ struct ptlrpc_body_v2 {
 #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 | \
index e8119f5..26819ff 100644 (file)
@@ -73,17 +73,26 @@ enum kuc_generic_message_type {
 #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__ */
index e85e975..554693d 100644 (file)
@@ -987,25 +987,110 @@ progress:
 }
 
 
-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;
 }
 
@@ -1738,8 +1823,8 @@ out_hur:
                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: {
index 9a4bd91..a2c7294 100644 (file)
@@ -2656,8 +2656,9 @@ free:
 
 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 */
@@ -2670,18 +2671,20 @@ int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
            !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);
 
index ad377fe..4d8ad57 100644 (file)
@@ -221,7 +221,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
        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)
index 329965e..e785fd9 100644 (file)
@@ -800,23 +800,42 @@ static int lmv_hsm_ct_register(struct obd_device *obd, unsigned int cmd,
                               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);
 
index bb53e0a..8aa80d7 100644 (file)
@@ -1684,29 +1684,53 @@ out:
        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);
 
@@ -2227,9 +2251,8 @@ static void lustre_swab_kuch(struct kuc_hdr *l)
 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);
@@ -2243,7 +2266,12 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp,
                /* 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;
@@ -2294,17 +2322,29 @@ static int mdc_hsm_copytool_send(const struct obd_uuid *uuid,
  */
 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;
 }
index e064cc1..1effc5a 100644 (file)
@@ -146,22 +146,49 @@ out:
 
 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);
@@ -313,6 +340,9 @@ int mdt_hsm_state_set(struct tgt_session_info *tsi)
 
        /* 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",
@@ -320,10 +350,11 @@ int mdt_hsm_state_set(struct tgt_session_info *tsi)
                        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);
                }
 
index 5d33739..281ad9c 100644 (file)
@@ -1193,7 +1193,7 @@ struct req_msg_field RMF_MDS_HSM_USER_ITEM =
 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);
 
index 1d90e60..01a701c 100644 (file)
@@ -47,6 +47,7 @@
 
 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",                     \
@@ -131,19 +132,26 @@ int test3(void)
        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? */
@@ -355,6 +363,7 @@ void test51(void)
        int rc;
        int fd;
        int i;
+       int test_count;
        struct hsm_user_state hus;
 
        fd = create_testfile(100);
@@ -363,13 +372,17 @@ void test51(void)
        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);
@@ -377,15 +390,20 @@ void test51(void)
                        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
@@ -1013,11 +1031,14 @@ static void process_args(int argc, char *argv[])
 {
        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);
index 32cd275..2035603 100755 (executable)
@@ -993,10 +993,26 @@ test_1c() {
        [[ $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
@@ -5307,7 +5323,16 @@ test_500()
                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"
 
index 2ad9f3f..083d4c6 100644 (file)
@@ -87,8 +87,9 @@ struct options {
        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;
@@ -250,11 +251,20 @@ static int ct_parseopts(int argc, char * const *argv)
                                                .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) {
@@ -268,16 +278,41 @@ static int ct_parseopts(int argc, char * const *argv)
                                         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 */
@@ -1426,7 +1461,8 @@ static int ct_import_one(const char *src, const char *dst)
                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);
@@ -1836,7 +1872,7 @@ static int ct_run(void)
        }
 
        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");
@@ -1969,6 +2005,12 @@ static int ct_cleanup(void)
                }
        }
 
+       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;
 }
 
index 41eac0f..39624f2 100644 (file)
 /****** 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
@@ -282,7 +281,7 @@ static int llapi_hsm_log_ct_registration(struct hsm_copytool_private **priv,
                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;
 
@@ -687,11 +686,14 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv,
                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));
@@ -701,8 +703,6 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv,
        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) {
@@ -710,7 +710,7 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv,
                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;
@@ -728,34 +728,34 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv,
                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,
@@ -766,15 +766,18 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv,
        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))
@@ -813,11 +816,11 @@ int llapi_hsm_copytool_unregister(struct hsm_copytool_private **priv)
         * 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);
 
@@ -825,6 +828,7 @@ int llapi_hsm_copytool_unregister(struct hsm_copytool_private **priv)
        close(ct->mnt_fd);
        free(ct->mnt);
        free(ct->kuch);
+       free(ct->kuc);
        free(ct);
        *priv = NULL;
 
@@ -841,7 +845,7 @@ int llapi_hsm_copytool_get_fd(struct hsm_copytool_private *ct)
        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
@@ -869,7 +873,7 @@ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct,
        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)
@@ -905,15 +909,16 @@ repeat:
 
        /* 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;