X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi_hsm.c;h=ba99cd30cef48659d126c5e4d4bb56ea8619cbee;hp=ad9f229df367450ec9f2f60ff4932ccd16be79f6;hb=5b09f471e5e22466a59e64168d21898c73167c4f;hpb=d92bd22523aa9bb1cdb91ded3d46fb180f68a93c diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index ad9f229..ba99cd3 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -6,7 +6,7 @@ * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies * alternatives * - * Copyright (c) 2013, 2016, Intel Corporation. + * Copyright (c) 2013, 2017, Intel Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License @@ -58,7 +58,6 @@ #endif #include -#include #include #include "lustreapi_internal.h" @@ -67,22 +66,22 @@ /****** 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 struct hsm_copyaction_private { __u32 magic; + __u32 source_fd; __s32 data_fd; const struct hsm_copytool_private *ct_priv; struct hsm_copy copy; - lstat_t stat; + lstatx_t statx; }; enum ct_progress_type { @@ -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; @@ -413,8 +412,9 @@ static int llapi_hsm_log_ct_progress(struct hsm_copyaction_private **phcp, /* lustre_path isn't available after a restore completes */ /* total_bytes isn't available after a restore or archive completes */ if (progress_type != CT_FINISH) { - rc = llapi_fid2path(hcp->ct_priv->mnt, strfid, lustre_path, - sizeof(lustre_path), &recno, &linkno); + rc = llapi_fid2path_at(hcp->ct_priv->mnt_fd, &hai->hai_dfid, + lustre_path, sizeof(lustre_path), + &recno, &linkno); if (rc < 0) goto err; @@ -658,8 +658,6 @@ err: out_free: if (json_items != NULL) llapi_json_destroy_list(&json_items); - - return; } /** Register a copytool @@ -687,11 +685,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 +702,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 +709,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 +727,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; + goto out_kuc; } - /* 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; - } - 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 +765,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 +815,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 +827,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 +844,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 +872,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 +908,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; @@ -934,25 +938,22 @@ out_err: * \param parent_len Destination buffer size. * \return 0 on success. */ -static int fid_parent(const char *mnt, const lustre_fid *fid, char *parent, - size_t parent_len) +static int fid_parent(const struct hsm_copytool_private *ct, + const struct lu_fid *fid, char *parent, size_t parent_len) { int rc; int linkno = 0; long long recno = -1; char file[PATH_MAX]; - char strfid[FID_NOBRACE_LEN + 1]; char *ptr; - snprintf(strfid, sizeof(strfid), DFID_NOBRACE, PFID(fid)); - - rc = llapi_fid2path(mnt, strfid, file, sizeof(file), - &recno, &linkno); + rc = llapi_fid2path_at(ct->mnt_fd, fid, file, sizeof(file), + &recno, &linkno); if (rc < 0) return rc; /* fid2path returns a relative path */ - rc = snprintf(parent, parent_len, "%s/%s", mnt, file); + rc = snprintf(parent, parent_len, "%s/%s", ct->mnt, file); if (rc >= parent_len) return -ENAMETOOLONG; @@ -991,37 +992,35 @@ static int ct_open_by_fid(const struct hsm_copytool_private *ct, */ static int ct_md_getattr(const struct hsm_copytool_private *ct, const struct lu_fid *fid, - lstat_t *st) + lstatx_t *stx) { struct lov_user_mds_data *lmd; + char fname[FID_NOBRACE_LEN + 1] = ""; size_t lmd_size; int rc; - lmd_size = sizeof(lmd->lmd_st) + - lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3); + rc = snprintf(fname, sizeof(fname), DFID_NOBRACE, PFID(fid)); + if (rc < 0) + return rc; + if (rc >= sizeof(fname) || rc == 0) + return -EINVAL; - if (lmd_size < sizeof(lmd->lmd_st) + XATTR_SIZE_MAX) - lmd_size = sizeof(lmd->lmd_st) + XATTR_SIZE_MAX; + lmd_size = offsetof(typeof(*lmd), lmd_lmm) + + lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3); - if (lmd_size < FID_NOBRACE_LEN + 1) - lmd_size = FID_NOBRACE_LEN + 1; + if (lmd_size < offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX) + lmd_size = offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX; lmd = malloc(lmd_size); if (lmd == NULL) return -ENOMEM; - snprintf((char *)lmd, lmd_size, DFID_NOBRACE, PFID(fid)); - - rc = ioctl(ct->open_by_fid_fd, IOC_MDC_GETFILEINFO, lmd); - if (rc != 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "cannot get metadata attributes of "DFID" in '%s'", - PFID(fid), ct->mnt); + rc = get_lmd_info_fd(fname, ct->open_by_fid_fd, -1, + lmd, lmd_size, GET_LMD_INFO); + if (rc) goto out; - } - *st = lmd->lmd_st; + *stx = lmd->lmd_stx; out: free(lmd); @@ -1038,26 +1037,26 @@ out: static int create_restore_volatile(struct hsm_copyaction_private *hcp, int mdt_index, int open_flags) { - int rc; - int fd; - char parent[PATH_MAX + 1]; - const char *mnt = hcp->ct_priv->mnt; - struct hsm_action_item *hai = &hcp->copy.hc_hai; + const struct hsm_copytool_private *ct = hcp->ct_priv; + struct hsm_action_item *hai = &hcp->copy.hc_hai; + char parent[PATH_MAX + 1]; + int fd; + int rc; - rc = fid_parent(mnt, &hai->hai_fid, parent, sizeof(parent)); + rc = fid_parent(ct, &hai->hai_fid, parent, sizeof(parent)); if (rc < 0) { /* fid_parent() failed, try to keep on going */ llapi_error(LLAPI_MSG_ERROR, rc, "cannot get parent path to restore "DFID" " - "using '%s'", PFID(&hai->hai_fid), mnt); - snprintf(parent, sizeof(parent), "%s", mnt); + "using '%s'", PFID(&hai->hai_fid), ct->mnt); + snprintf(parent, sizeof(parent), "%s", ct->mnt); } fd = llapi_create_volatile_idx(parent, mdt_index, open_flags); if (fd < 0) return fd; - rc = fchown(fd, hcp->stat.st_uid, hcp->stat.st_gid); + rc = fchown(fd, hcp->statx.stx_uid, hcp->statx.stx_gid); if (rc < 0) goto err_cleanup; @@ -1100,13 +1099,15 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, int restore_mdt_index, int restore_open_flags, bool is_error) { - struct hsm_copyaction_private *hcp; - int rc; + struct hsm_copyaction_private *hcp; + int fd; + int rc; hcp = calloc(1, sizeof(*hcp)); if (hcp == NULL) return -ENOMEM; + hcp->source_fd = -1; hcp->data_fd = -1; hcp->ct_priv = ct; hcp->copy.hc_hai = *hai; @@ -1115,8 +1116,17 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, if (is_error) goto ok_out; - if (hai->hai_action == HSMA_RESTORE) { - rc = ct_md_getattr(hcp->ct_priv, &hai->hai_fid, &hcp->stat); + if (hai->hai_action == HSMA_ARCHIVE) { + fd = ct_open_by_fid(hcp->ct_priv, &hai->hai_dfid, + O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NONBLOCK); + if (fd < 0) { + rc = fd; + goto err_out; + } + + hcp->source_fd = fd; + } else if (hai->hai_action == HSMA_RESTORE) { + rc = ct_md_getattr(hcp->ct_priv, &hai->hai_fid, &hcp->statx); if (rc < 0) goto err_out; @@ -1124,12 +1134,41 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, restore_open_flags); if (rc < 0) goto err_out; - } + } else if (hai->hai_action == HSMA_REMOVE) { + /* Since remove is atomic there is no need to send an + * initial MDS_HSM_PROGRESS RPC. + * RW-PCC uses Lustre HSM mechanism for data synchronization. + * At the beginning of RW-PCC attach, the client tries to + * exclusively open the file by using a lease lock. A + * successful lease open ensures that the current attach + * process is the unique opener for the file. + * After taking the lease, the file data is then copied from + * OSTs into PCC and then the client closes the lease with + * with a PCC attach intent. + * However, for a file with HSM exists, archived state (i.e. a + * cached file just was detached from PCC and restore into + * OST), a HSM REMOVE request may delete the above PCC copy + * during RW-PCC attach wrongly. + * Thus, a open/close on the corresponding Lustre file is added + * for HSMA_REMOVE here to solve this conflict. + */ + fd = ct_open_by_fid(hcp->ct_priv, &hai->hai_fid, + O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NONBLOCK); + if (fd < 0) { + rc = fd; + /* ignore the error in case of Remove Archive on Last + * Unlink (RAoLU). + */ + if (rc == -ENOENT) { + rc = 0; + goto out_log; + } + goto err_out; + } - /* Since remove is atomic there is no need to send an initial - * MDS_HSM_PROGRESS RPC. */ - if (hai->hai_action == HSMA_REMOVE) + hcp->source_fd = fd; goto out_log; + } rc = ioctl(ct->mnt_fd, LL_IOC_HSM_COPY_START, &hcp->copy); if (rc < 0) { @@ -1146,6 +1185,9 @@ ok_out: return 0; err_out: + if (!(hcp->source_fd < 0)) + close(hcp->source_fd); + if (!(hcp->data_fd < 0)) close(hcp->data_fd); @@ -1183,12 +1225,12 @@ int llapi_hsm_action_end(struct hsm_copyaction_private **phcp, if (hai->hai_action == HSMA_RESTORE && errval == 0) { struct ll_futimes_3 lfu = { - .lfu_atime_sec = hcp->stat.st_atim.tv_sec, - .lfu_atime_nsec = hcp->stat.st_atim.tv_nsec, - .lfu_mtime_sec = hcp->stat.st_mtim.tv_sec, - .lfu_mtime_nsec = hcp->stat.st_mtim.tv_nsec, - .lfu_ctime_sec = hcp->stat.st_ctim.tv_sec, - .lfu_ctime_nsec = hcp->stat.st_ctim.tv_nsec, + .lfu_atime_sec = hcp->statx.stx_atime.tv_sec, + .lfu_atime_nsec = hcp->statx.stx_atime.tv_nsec, + .lfu_mtime_sec = hcp->statx.stx_mtime.tv_sec, + .lfu_mtime_nsec = hcp->statx.stx_mtime.tv_nsec, + .lfu_ctime_sec = hcp->statx.stx_ctime.tv_sec, + .lfu_ctime_nsec = hcp->statx.stx_ctime.tv_nsec, }; rc = fsync(hcp->data_fd); @@ -1227,6 +1269,9 @@ end: llapi_hsm_log_ct_progress(&hcp, hai, CT_FINISH, 0, 0); err_cleanup: + if (!(hcp->source_fd < 0)) + close(hcp->source_fd); + if (!(hcp->data_fd < 0)) close(hcp->data_fd); @@ -1281,7 +1326,7 @@ int llapi_hsm_action_progress(struct hsm_copyaction_private *hcp, * @return error code if the action is not a copy operation. */ int llapi_hsm_action_get_dfid(const struct hsm_copyaction_private *hcp, - lustre_fid *fid) + struct lu_fid *fid) { const struct hsm_action_item *hai = &hcp->copy.hc_hai; @@ -1312,8 +1357,8 @@ int llapi_hsm_action_get_fd(const struct hsm_copyaction_private *hcp) return -EINVAL; if (hai->hai_action == HSMA_ARCHIVE) { - return ct_open_by_fid(hcp->ct_priv, &hai->hai_dfid, - O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NONBLOCK); + fd = dup(hcp->source_fd); + return fd < 0 ? -errno : fd; } else if (hai->hai_action == HSMA_RESTORE) { fd = dup(hcp->data_fd); return fd < 0 ? -errno : fd; @@ -1338,7 +1383,7 @@ int llapi_hsm_action_get_fd(const struct hsm_copyaction_private *hcp) int llapi_hsm_import(const char *dst, int archive, const struct stat *st, unsigned long long stripe_size, int stripe_offset, int stripe_count, int stripe_pattern, char *pool_name, - lustre_fid *newfid) + struct lu_fid *newfid) { struct hsm_user_import hui; int fd;