X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi_hsm.c;h=0b12f373688f6544de6179be595d2a09c891c0df;hp=3f1b8b9fe2282b39dce381a652050a327c4bfb17;hb=5fbb786b96b7db3a977dd8a8fca9a40f52f66b82;hpb=45c9ef1dfff207086665c764c7d500c00aa03c7f diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 3f1b8b9..0b12f37 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, 2015, 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,8 @@ #include #endif -#include #include -#include +#include #include #include "lustreapi_internal.h" @@ -66,9 +69,10 @@ struct hsm_copytool_private { int magic; char *mnt; + struct kuc_hdr *kuch; int mnt_fd; int open_by_fid_fd; - lustre_kernelcomm kuc; + struct lustre_kernelcomm kuc; __u32 archives; }; @@ -78,11 +82,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, @@ -113,7 +115,8 @@ enum ct_event { }; /* initialized in llapi_hsm_register_event_fifo() */ -FILE *llapi_hsm_event_fp; +static int llapi_hsm_event_fd = -1; +static bool created_hsm_event_fifo; static inline const char *llapi_hsm_ct_ev2str(int type) { @@ -169,16 +172,18 @@ 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]; + char json_buf[PIPE_BUF]; + FILE *buf_file; time_t event_time = time(0); struct tm time_components; struct llapi_json_item_list *json_items; - /* Noop unless the event fp was initialized */ - if (llapi_hsm_event_fp == NULL) + /* Noop unless the event fd was initialized */ + if (llapi_hsm_event_fd < 0) return 0; if (event == NULL || *event == NULL) @@ -203,21 +208,24 @@ int llapi_hsm_write_json_event(struct llapi_json_item_list **event) return rc; } - rc = llapi_json_write_list(event, llapi_hsm_event_fp); - if (rc < 0) { - /* Ignore write failures due to missing reader. */ - if (rc == -EPIPE) - return 0; + buf_file = fmemopen(json_buf, sizeof(json_buf), "w"); + if (buf_file == NULL) + return -errno; - /* Skip llapi_error() here because there's no point - * in creating a JSON-formatted error message about - * failing to write a JSON-formatted message. - */ - fprintf(stderr, - "\nFATAL ERROR IN llapi_hsm_write_list(): rc %d", rc); + rc = llapi_json_write_list(event, buf_file); + if (rc < 0) { + fclose(buf_file); return rc; } + fclose(buf_file); + + if (write(llapi_hsm_event_fd, json_buf, strlen(json_buf)) < 0) { + /* Ignore write failures due to missing reader. */ + if (errno != EPIPE) + return -errno; + } + return 0; } @@ -232,14 +240,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; @@ -304,16 +316,28 @@ out_free: * llapi_hsm_write_json_event: * * Copytool registration and deregistration: - * {"event_time": "2014-02-26 14:58:01 -0500", "event_type": "REGISTER", "archive": 0, "mount_point": "/mnt/lustre", "uuid": "80379a60-1f8a-743f-daf2-307cde793ec2"} - * {"event_time": "2014-02-26 14:58:01 -0500", "event_type": "UNREGISTER", "archive": 0, "mount_point": "/mnt/lustre", "uuid": "80379a60-1f8a-743f-daf2-307cde793ec2"} + * {"event_time": "2014-02-26 14:58:01 -0500", "event_type": "REGISTER", + * "archive": 0, "mount_point": "/mnt/lustre", + * "uuid": "80379a60-1f8a-743f-daf2-307cde793ec2"} + * {"event_time": "2014-02-26 14:58:01 -0500", "event_type": "UNREGISTER", + * "archive": 0, "mount_point": "/mnt/lustre", + * "uuid": "80379a60-1f8a-743f-daf2-307cde793ec2"} * * An archive action, start to completion: - * {"event_time": "2014-02-26 14:50:13 -0500", "event_type": "ARCHIVE_START", "total_bytes": 0, "lustre_path": "d71.sanity-hsm/f71.sanity-hsm", "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} - * {"event_time": "2014-02-26 14:50:18 -0500", "event_type": "ARCHIVE_RUNNING", "current_bytes": 5242880, "total_bytes": 39000000, "lustre_path": "d71.sanity-hsm/f71.sanity-hsm", "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} - * {"event_time": "2014-02-26 14:50:50 -0500", "event_type": "ARCHIVE_FINISH", "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} + * {"event_time": "2014-02-26 14:50:13 -0500", "event_type": "ARCHIVE_START", + * "total_bytes": 0, "lustre_path": "d71.sanity-hsm/f71.sanity-hsm", + * "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} + * {"event_time": "2014-02-26 14:50:18 -0500", "event_type": "ARCHIVE_RUNNING", + * "current_bytes": 5242880, "total_bytes": 39000000, + * "lustre_path": "d71.sanity-hsm/f71.sanity-hsm", + * "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} + * {"event_time": "2014-02-26 14:50:50 -0500", "event_type": "ARCHIVE_FINISH", + * "source_fid": "0x2000013a1:0x2:0x0", "data_fid": "0x2000013a1:0x2:0x0"} * * A log message: - * {"event_time": "2014-02-26 14:50:13 -0500", "event_type": "LOGGED_MESSAGE", "level": "INFO", "message": "lhsmtool_posix[59401]: copytool fs=lustre archive#=2 item_count=1"} + * {"event_time": "2014-02-26 14:50:13 -0500", "event_type": "LOGGED_MESSAGE", + * "level": "INFO", + * "message": "lhsmtool_posix[42]: copytool fs=lustre archive#=2 item_count=1"} * * \param hcp Opaque action handle returned by * llapi_hsm_action_start. @@ -325,9 +349,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; @@ -337,6 +362,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; @@ -441,10 +470,12 @@ 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, write_fd; + int read_fd; struct stat statbuf; + struct sigaction ignore_action; + int rc; /* Create the FIFO if necessary. */ if ((mkfifo(path, 0644) < 0) && (errno != EEXIST)) { @@ -463,6 +494,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 @@ -476,30 +509,25 @@ int llapi_hsm_register_event_fifo(char *path) /* Open the FIFO for writes, but don't block on waiting * for a reader. */ - write_fd = open(path, O_WRONLY | O_NONBLOCK); - if (write_fd < 0) { - llapi_error(LLAPI_MSG_ERROR, errno, - "cannot open(%s) for write", path); - return -errno; - } + llapi_hsm_event_fd = open(path, O_WRONLY | O_NONBLOCK); + 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); - llapi_hsm_event_fp = fdopen(write_fd, "w"); - if (llapi_hsm_event_fp == NULL) { - llapi_error(LLAPI_MSG_ERROR, errno, - "cannot fdopen(%s) for write", path); - return -errno; + 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); - - /* Don't buffer the event stream. */ - setbuf(llapi_hsm_event_fp, NULL); + 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; } @@ -512,18 +540,21 @@ 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 fp was initialized */ - if (llapi_hsm_event_fp == NULL) + /* Noop unless the event fd was initialized */ + if (llapi_hsm_event_fd < 0) return 0; - if (fclose(llapi_hsm_event_fp) != 0) + 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_fp = NULL; + llapi_hsm_event_fd = -1; return 0; } @@ -550,8 +581,8 @@ void llapi_hsm_log_error(enum llapi_message_level level, int _rc, va_list args2; struct llapi_json_item_list *json_items; - /* Noop unless the event fp was initialized */ - if (llapi_hsm_event_fp == NULL) + /* Noop unless the event fd was initialized */ + if (llapi_hsm_event_fd < 0) return; rc = llapi_json_init_list(&json_items); @@ -631,15 +662,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; @@ -650,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; @@ -666,6 +709,12 @@ int llapi_hsm_copytool_register(struct hsm_copytool_private **priv, goto out_err; } + ct->kuch = malloc(HAL_MAXSIZE + sizeof(*ct->kuch)); + if (ct->kuch == NULL) { + rc = -ENOMEM; + goto out_err; + } + ct->mnt_fd = open(ct->mnt, O_RDONLY); if (ct->mnt_fd < 0) { rc = -errno; @@ -681,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) { @@ -698,7 +748,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; @@ -709,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); @@ -719,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: @@ -736,8 +782,9 @@ out_err: if (!(ct->open_by_fid_fd < 0)) close(ct->open_by_fid_fd); - if (ct->mnt != NULL) - free(ct->mnt); + free(ct->mnt); + + free(ct->kuch); free(ct); @@ -760,30 +807,50 @@ 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); close(ct->mnt_fd); free(ct->mnt); + free(ct->kuch); free(ct); *priv = NULL; 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 * \param msgsize Number of bytes in the message, will be set here * \return 0 valid message received; halh and msgsize are set * <0 error code + * Note: The application must not call llapi_hsm_copytool_recv until it has + * cleared the data in ct->kuch from the previous call. */ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct, struct hsm_action_list **halh, int *msgsize) @@ -798,21 +865,20 @@ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct, if (halh == NULL || msgsize == NULL) return -EINVAL; - kuch = malloc(HAL_MAXSIZE + sizeof(*kuch)); - if (kuch == NULL) - return -ENOMEM; + kuch = ct->kuch; +repeat: rc = libcfs_ukuc_msg_get(&ct->kuc, (char *)kuch, HAL_MAXSIZE + sizeof(*kuch), KUC_TRANSPORT_HSM); if (rc < 0) - goto out_free; + goto out_err; /* Handle generic messages */ if (kuch->kuc_transport == KUC_TRANSPORT_GENERIC && kuch->kuc_msgtype == KUC_MSG_SHUTDOWN) { rc = -ESHUTDOWN; - goto out_free; + goto out_err; } if (kuch->kuc_transport != KUC_TRANSPORT_HSM || @@ -821,14 +887,14 @@ int llapi_hsm_copytool_recv(struct hsm_copytool_private *ct, "Unknown HSM message type %d:%d\n", kuch->kuc_transport, kuch->kuc_msgtype); rc = -EPROTO; - goto out_free; + goto out_err; } if (kuch->kuc_msglen < sizeof(*kuch) + sizeof(*hal)) { llapi_err_noerrno(LLAPI_MSG_ERROR, "Short HSM message %d", kuch->kuc_msglen); rc = -EPROTO; - goto out_free; + goto out_err; } /* Our message is a hsm_action_list. Use pointer math to skip @@ -845,29 +911,20 @@ 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_free; + goto repeat; } *halh = hal; *msgsize = kuch->kuc_msglen - sizeof(*kuch); return 0; -out_free: +out_err: *halh = NULL; *msgsize = 0; - free(kuch); return rc; } -/** Release the action list when done with it. */ -void llapi_hsm_action_list_free(struct hsm_action_list **hal) -{ - /* Reuse the llapi_changelog_free function */ - llapi_changelog_free((struct changelog_ext_rec **)hal); -} - /** Get parent path from mount point and fid. * * \param mnt Filesystem root path. @@ -914,21 +971,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; + + 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 fstatat(ct->open_by_fid_fd, fid_name, buf, 0); + return rc; } /** Create the destination volatile file for a restore operation. @@ -1019,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; @@ -1079,19 +1175,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; @@ -1199,17 +1299,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; + } } /** @@ -1243,9 +1346,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 @@ -1268,8 +1371,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; }