X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi_hsm.c;h=4c3c5b929098209c49b2e4ee7c13b6f6b8204966;hp=2ca1756605969dbc558ba5edd72302db8321b398;hb=f625f670afbe954030ff81f0f8522137d6cdd335;hpb=76dca841869d87df2b625cb9d186d531c406fc9b diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 2ca1756..4c3c5b9 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, 2014, 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. @@ -79,7 +81,7 @@ 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 @@ -114,7 +116,8 @@ enum ct_event { }; /* initialized in llapi_hsm_register_event_fifo() */ -int llapi_hsm_event_fd = -1; +static int llapi_hsm_event_fd = -1; +static bool created_hsm_event_fifo; static inline const char *llapi_hsm_ct_ev2str(int type) { @@ -170,7 +173,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]; @@ -238,14 +241,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; @@ -343,9 +350,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; @@ -355,6 +363,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; @@ -459,7 +471,7 @@ out_free: * \retval 0 on success. * \retval -errno on error. */ -int llapi_hsm_register_event_fifo(char *path) +int llapi_hsm_register_event_fifo(const char *path) { int read_fd; struct stat statbuf; @@ -481,6 +493,8 @@ int llapi_hsm_register_event_fifo(char *path) "not a pipe or has a wrong mode", path); return -errno; } + } else { + created_hsm_event_fifo = true; } /* Open the FIFO for read so that the subsequent open for write @@ -520,7 +534,7 @@ int llapi_hsm_register_event_fifo(char *path) * \retval 0 on success. * \retval -errno on error. */ -int llapi_hsm_unregister_event_fifo(char *path) +int llapi_hsm_unregister_event_fifo(const char *path) { /* Noop unless the event fd was initialized */ if (llapi_hsm_event_fd < 0) @@ -529,7 +543,10 @@ int llapi_hsm_unregister_event_fifo(char *path) if (close(llapi_hsm_event_fd) < 0) return -errno; - unlink(path); + if (created_hsm_event_fifo) { + unlink(path); + created_hsm_event_fifo = false; + } llapi_hsm_event_fd = -1; @@ -639,15 +656,20 @@ out_free: } /** Register a copytool - * \param[out] priv Opaque private control structure - * \param mnt Lustre filesystem mount point - * \param flags Open flags, currently unused (e.g. O_NONBLOCK) - * \param archive_count - * \param archives Which archive numbers this copytool is responsible for + * \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 flags, int archive_count, - int *archives) + const char *mnt, int archive_count, + int *archives, int rfd_flags) { struct hsm_copytool_private *ct; int rc; @@ -658,6 +680,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; @@ -695,13 +724,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) { @@ -712,7 +742,7 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, ct->archives |= (1 << (archives[rc] - 1)); } - rc = libcfs_ukuc_start(&ct->kuc, KUC_GRP_HSM); + rc = libcfs_ukuc_start(&ct->kuc, KUC_GRP_HSM, rfd_flags); if (rc < 0) goto out_err; @@ -723,9 +753,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); @@ -733,10 +761,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: @@ -794,6 +820,19 @@ int llapi_hsm_copytool_unregister(struct hsm_copytool_private **priv) return 0; } +/** Returns a file descriptor to poll/select on. + * \param ct Opaque private control structure + * \retval -EINVAL on error + * \retval the file descriptor for reading HSM events from the kernel + */ +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); +} + /** Wait for the next hsm_action_list * \param ct Opaque private control structure * \param halh Action list handle, will be allocated here @@ -818,6 +857,7 @@ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct, kuch = ct->kuch; +repeat: rc = libcfs_ukuc_msg_get(&ct->kuc, (char *)kuch, HAL_MAXSIZE + sizeof(*kuch), KUC_TRANSPORT_HSM); @@ -861,9 +901,8 @@ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct, " ignoring this request." " Mask of served archive is 0x%.8X", hal->hal_archive_id, ct->archives); - rc = -EAGAIN; - goto out_err; + goto repeat; } *halh = hal; @@ -922,21 +961,60 @@ static int ct_open_by_fid(const struct hsm_copytool_private *ct, const struct lu_fid *fid, int open_flags) { char fid_name[FID_NOBRACE_LEN + 1]; + int fd; snprintf(fid_name, sizeof(fid_name), DFID_NOBRACE, PFID(fid)); - return openat(ct->open_by_fid_fd, fid_name, open_flags); + fd = openat(ct->open_by_fid_fd, fid_name, open_flags); + 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; + + lmd = malloc(lmd_size); + if (lmd == NULL) + return -ENOMEM; - return fstatat(ct->open_by_fid_fd, fid_name, buf, 0); + 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. @@ -1027,7 +1105,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; @@ -1207,17 +1285,20 @@ int llapi_hsm_action_get_dfid(const struct hsm_copyaction_private *hcp, int llapi_hsm_action_get_fd(const struct hsm_copyaction_private *hcp) { const struct hsm_action_item *hai = &hcp->copy.hc_hai; + int fd; if (hcp->magic != CP_PRIV_MAGIC) return -EINVAL; - if (hai->hai_action == HSMA_ARCHIVE) + 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); - else if (hai->hai_action == HSMA_RESTORE) - return dup(hcp->data_fd); - else + } else if (hai->hai_action == HSMA_RESTORE) { + fd = dup(hcp->data_fd); + return fd < 0 ? -errno : fd; + } else { return -EINVAL; + } } /** @@ -1251,9 +1332,9 @@ int llapi_hsm_import(const char *dst, int archive, const struct stat *st, stripe_pattern | LOV_PATTERN_F_RELEASED, pool_name); if (fd < 0) { - llapi_error(LLAPI_MSG_ERROR, -errno, + llapi_error(LLAPI_MSG_ERROR, fd, "cannot create '%s' for import", dst); - return -errno; + return fd; } /* Get the new fid in Lustre. Caller needs to use this fid @@ -1276,8 +1357,8 @@ int llapi_hsm_import(const char *dst, int archive, const struct stat *st, hui.hui_mtime_ns = st->st_mtim.tv_nsec; rc = ioctl(fd, LL_IOC_HSM_IMPORT, &hui); if (rc != 0) { - llapi_error(LLAPI_MSG_ERROR, rc, "cannot import '%s'", dst); rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "cannot import '%s'", dst); goto out_unlink; }