X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi_hsm.c;h=486be878c32b3da343ecbfb288122e3339e93175;hp=4fe6ca44066eef833a384efec14839d5c9d2fee1;hb=06be2b427fbca4f8a9a2be37b951a47ef3315925;hpb=7b7e6e2fb692eb3fa8d386addbc33763acf1a397 diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 4fe6ca4..486be87 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -6,6 +6,8 @@ * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies * alternatives * + * Copyright (c) 2013, 2016, Intel Corporation. + * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 or (at your discretion) any later version. @@ -30,6 +32,7 @@ * Author: Henri Doreau */ +#include #include #include #include @@ -41,11 +44,12 @@ #include #include #include +#include #include +#include #include #include #include -#include #include #ifdef HAVE_LINUX_UNISTD_H #include @@ -53,9 +57,7 @@ #include #endif -#include -#include -#include +#include #include #include "lustreapi_internal.h" @@ -69,7 +71,7 @@ struct hsm_copytool_private { struct kuc_hdr *kuch; int mnt_fd; int open_by_fid_fd; - lustre_kernelcomm kuc; + struct lustre_kernelcomm kuc; __u32 archives; }; @@ -79,11 +81,9 @@ struct hsm_copyaction_private { __s32 data_fd; const struct hsm_copytool_private *ct_priv; struct hsm_copy copy; - struct stat stat; + lstat_t stat; }; -#include - enum ct_progress_type { CT_START = 0, CT_RUNNING = 50, @@ -171,7 +171,7 @@ static inline const char *llapi_hsm_ct_ev2str(int type) * \retval 0 on success. * \retval -errno on error. */ -int llapi_hsm_write_json_event(struct llapi_json_item_list **event) +static int llapi_hsm_write_json_event(struct llapi_json_item_list **event) { int rc; char time_string[40]; @@ -239,14 +239,18 @@ int llapi_hsm_write_json_event(struct llapi_json_item_list **event) * \retval 0 on success. * \retval -errno on error. */ -int llapi_hsm_log_ct_registration(struct hsm_copytool_private **priv, - __u32 event_type) +static int llapi_hsm_log_ct_registration(struct hsm_copytool_private **priv, + __u32 event_type) { int rc; char agent_uuid[UUID_MAX]; struct hsm_copytool_private *ct; struct llapi_json_item_list *json_items; + /* Noop unless the event fd was initialized */ + if (llapi_hsm_event_fd < 0) + return 0; + if (priv == NULL || *priv == NULL) return -EINVAL; @@ -344,9 +348,10 @@ out_free: * \retval 0 on success. * \retval -errno on error. */ -int llapi_hsm_log_ct_progress(struct hsm_copyaction_private **phcp, - const struct hsm_action_item *hai, __u32 progress_type, - __u64 total, __u64 current) +static int llapi_hsm_log_ct_progress(struct hsm_copyaction_private **phcp, + const struct hsm_action_item *hai, + __u32 progress_type, + __u64 total, __u64 current) { int rc; int linkno = 0; @@ -356,6 +361,10 @@ int llapi_hsm_log_ct_progress(struct hsm_copyaction_private **phcp, struct hsm_copyaction_private *hcp; struct llapi_json_item_list *json_items; + /* Noop unless the event fd was initialized */ + if (llapi_hsm_event_fd < 0) + return 0; + if (phcp == NULL || *phcp == NULL) return -EINVAL; @@ -419,11 +428,12 @@ int llapi_hsm_log_ct_progress(struct hsm_copyaction_private **phcp, goto err; } - if (progress_type == CT_RUNNING) + if (progress_type == CT_RUNNING) { rc = llapi_json_add_item(&json_items, "current_bytes", LLAPI_JSON_BIGNUM, ¤t); if (rc < 0) goto err; + } cancel: rc = llapi_json_add_item(&json_items, "event_type", LLAPI_JSON_STRING, @@ -464,6 +474,8 @@ int llapi_hsm_register_event_fifo(const char *path) { int read_fd; struct stat statbuf; + struct sigaction ignore_action; + int rc; /* Create the FIFO if necessary. */ if ((mkfifo(path, 0644) < 0) && (errno != EEXIST)) { @@ -498,19 +510,24 @@ int llapi_hsm_register_event_fifo(const char *path) /* Open the FIFO for writes, but don't block on waiting * for a reader. */ llapi_hsm_event_fd = open(path, O_WRONLY | O_NONBLOCK); - if (llapi_hsm_event_fd < 0) { - llapi_error(LLAPI_MSG_ERROR, errno, - "cannot open(%s) for write", path); - return -errno; - } + rc = -errno; /* Now close the reader. An external monitoring process can * now open the FIFO for reads. If no reader comes along the * events are lost. NOTE: Only one reader at a time! */ close(read_fd); + if (llapi_hsm_event_fd < 0) { + llapi_error(LLAPI_MSG_ERROR, -rc, + "cannot open(%s) for write", path); + return rc; + } + /* Ignore SIGPIPEs -- can occur if the reader goes away. */ - signal(SIGPIPE, SIG_IGN); + memset(&ignore_action, 0, sizeof(ignore_action)); + ignore_action.sa_handler = SIG_IGN; + sigemptyset(&ignore_action.sa_mask); + sigaction(SIGPIPE, &ignore_action, NULL); return 0; } @@ -645,11 +662,16 @@ out_free: } /** Register a copytool - * \param[out] priv Opaque private control structure - * \param mnt Lustre filesystem mount point - * \param archive_count - * \param archives Which archive numbers this copytool is responsible for - * \param rfd_flags flags applied to read fd of pipe (e.g. O_NONBLOCK) + * \param[out] priv Opaque private control structure + * \param mnt Lustre filesystem mount point + * \param archive_count Number of valid archive IDs in \a archives + * \param archives Which archive numbers this copytool is + * responsible for + * \param rfd_flags flags applied to read fd of pipe + * (e.g. O_NONBLOCK) + * + * \retval 0 on success. + * \retval -errno on error. */ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, const char *mnt, int archive_count, @@ -664,6 +686,13 @@ 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; + } + ct = calloc(1, sizeof(*ct)); if (ct == NULL) return -ENOMEM; @@ -701,13 +730,14 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, /* no archives specified means "match all". */ ct->archives = 0; for (rc = 0; rc < archive_count; rc++) { - if (archives[rc] > 8 * sizeof(ct->archives)) { - llapi_err_noerrno(LLAPI_MSG_ERROR, - "maximum of %zu archives supported", - 8 * sizeof(ct->archives)); + if ((archives[rc] > LL_HSM_MAX_ARCHIVE) || (archives[rc] < 0)) { + llapi_err_noerrno(LLAPI_MSG_ERROR, "%d requested when " + "archive id [0 - %zu] is supported", + archives[rc], LL_HSM_MAX_ARCHIVE); + rc = -EINVAL; goto out_err; } - /* in the list we have a all archive wildcard + /* in the list we have an all archive wildcard * so move to all archives mode */ if (archives[rc] == 0) { @@ -729,9 +759,7 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, "cannot start copytool on '%s'", mnt); - goto out_err; - } else { - rc = 0; + goto out_kuc; } llapi_hsm_log_ct_registration(&ct, CT_REGISTER); @@ -739,10 +767,8 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, /* Only the kernel reference keeps the write side open */ close(ct->kuc.lk_wfd); ct->kuc.lk_wfd = LK_NOFD; - if (rc < 0) - goto out_kuc; - *priv = ct; + return 0; out_kuc: @@ -781,13 +807,17 @@ int llapi_hsm_copytool_unregister(struct hsm_copytool_private **priv) if (ct->magic != CT_PRIV_MAGIC) return -EINVAL; + /* Close the read side of the KUC pipe. This should be done + * before unregistering to avoid deadlock: a ldlm_cb thread + * 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); + /* 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); - /* Shut down the kernelcomms */ - libcfs_ukuc_stop(&ct->kuc); - llapi_hsm_log_ct_registration(&ct, CT_UNREGISTER); close(ct->open_by_fid_fd); @@ -903,7 +933,7 @@ 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, +static int fid_parent(const char *mnt, const struct lu_fid *fid, char *parent, size_t parent_len) { int rc; @@ -949,17 +979,52 @@ static int ct_open_by_fid(const struct hsm_copytool_private *ct, return fd < 0 ? -errno : fd; } -static int ct_stat_by_fid(const struct hsm_copytool_private *ct, - const struct lu_fid *fid, - struct stat *buf) +/** + * Get metadata attributes of file by FID. + * + * Use the IOC_MDC_GETFILEINFO ioctl (to send a MDS_GETATTR_NAME RPC) + * to get the attributes of the file identified by \a fid. This + * returns only the attributes stored on the MDT and avoids taking + * layout locks or accessing OST objects. It also bypasses the inode + * cache. Attributes are returned in \a st. + */ +static int ct_md_getattr(const struct hsm_copytool_private *ct, + const struct lu_fid *fid, + lstat_t *st) { - char fid_name[FID_NOBRACE_LEN + 1]; + struct lov_user_mds_data *lmd; + size_t lmd_size; int rc; - snprintf(fid_name, sizeof(fid_name), DFID_NOBRACE, PFID(fid)); + lmd_size = sizeof(lmd->lmd_st) + + lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3); + + if (lmd_size < sizeof(lmd->lmd_st) + XATTR_SIZE_MAX) + lmd_size = sizeof(lmd->lmd_st) + XATTR_SIZE_MAX; + + if (lmd_size < FID_NOBRACE_LEN + 1) + lmd_size = FID_NOBRACE_LEN + 1; - rc = fstatat(ct->open_by_fid_fd, fid_name, buf, 0); - return rc ? -errno : 0; + 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); + goto out; + } + + *st = lmd->lmd_st; +out: + free(lmd); + + return rc; } /** Create the destination volatile file for a restore operation. @@ -1050,7 +1115,7 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, goto ok_out; if (hai->hai_action == HSMA_RESTORE) { - rc = ct_stat_by_fid(hcp->ct_priv, &hai->hai_fid, &hcp->stat); + rc = ct_md_getattr(hcp->ct_priv, &hai->hai_fid, &hcp->stat); if (rc < 0) goto err_out; @@ -1060,12 +1125,18 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp, 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) + goto out_log; + rc = ioctl(ct->mnt_fd, LL_IOC_HSM_COPY_START, &hcp->copy); if (rc < 0) { rc = -errno; goto err_out; } +out_log: llapi_hsm_log_ct_progress(&hcp, hai, CT_START, 0, 0); ok_out: @@ -1110,19 +1181,23 @@ int llapi_hsm_action_end(struct hsm_copyaction_private **phcp, hai = &hcp->copy.hc_hai; if (hai->hai_action == HSMA_RESTORE && errval == 0) { - struct timeval tv[2]; - - /* Set {a,m}time of volatile file to that of original. */ - tv[0].tv_sec = hcp->stat.st_atime; - tv[0].tv_usec = 0; - tv[1].tv_sec = hcp->stat.st_mtime; - tv[1].tv_usec = 0; - if (futimes(hcp->data_fd, tv) < 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, + }; + + rc = fsync(hcp->data_fd); + if (rc < 0) { errval = -errno; goto end; } - rc = fsync(hcp->data_fd); + /* Set {a,m,c}time of volatile file to that of original. */ + rc = ioctl(hcp->data_fd, LL_IOC_FUTIMES_3, &lfu); if (rc < 0) { errval = -errno; goto end; @@ -1205,7 +1280,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; @@ -1262,7 +1337,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;