From 12e4004656f3019d0195d46de6df94af7452fdf8 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Thu, 5 Feb 2015 17:35:08 -0600 Subject: [PATCH] LU-6213 llite: add LL_IOC_FUTIMES_3 Add a new regular file ioctl LL_IOC_FUTIMES_3 similar to futimes() but which allows setting of all three inode timestamps. Use this ioctl during HSM restore to ensure that the volatile file has the same timestamps as the file to be restored. Strengthen sanity-hsm test_24a to check that archive, release, and restore do not change a file's ctime. Add sanity-hsm test_24e to check that tar will succeed when it encounters a HSM released file. Signed-off-by: John L. Hammond Change-Id: I98a4913048f902892fdafc514547bbe4d51523d7 Reviewed-on: http://review.whamcloud.com/13665 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: frank zago Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustre_user.h | 10 +++++++++ lustre/include/lustre_ioctl.h | 2 +- lustre/llite/file.c | 45 +++++++++++++++++++++++++++++++++++++ lustre/llite/llite_lib.c | 6 +++-- lustre/tests/sanity-hsm.sh | 24 ++++++++++++++++++-- lustre/utils/liblustreapi_hsm.c | 19 +++++++++------- 6 files changed, 93 insertions(+), 13 deletions(-) diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index 7f746e1..43c810a 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -220,6 +220,15 @@ struct ost_id { #define DOSTID LPX64":"LPU64 #define POSTID(oi) ostid_seq(oi), ostid_id(oi) +struct ll_futimes_3 { + __u64 lfu_atime_sec; + __u64 lfu_atime_nsec; + __u64 lfu_mtime_sec; + __u64 lfu_mtime_nsec; + __u64 lfu_ctime_sec; + __u64 lfu_ctime_nsec; +}; + /* * The ioctl naming rules: * LL_* - works on the currently opened filehandle instead of parent dir @@ -256,6 +265,7 @@ struct ost_id { #define LL_IOC_PATH2FID _IOR ('f', 173, long) #define LL_IOC_GET_CONNECT_FLAGS _IOWR('f', 174, __u64 *) #define LL_IOC_GET_MDTIDX _IOR ('f', 175, int) +#define LL_IOC_FUTIMES_3 _IOWR('f', 176, struct ll_futimes_3) /* lustre_ioctl.h 177-210 */ #define LL_IOC_HSM_STATE_GET _IOR('f', 211, struct hsm_user_state) #define LL_IOC_HSM_STATE_SET _IOW('f', 212, struct hsm_state_set) diff --git a/lustre/include/lustre_ioctl.h b/lustre/include/lustre_ioctl.h index 83ef428..a7670f3 100644 --- a/lustre/include/lustre_ioctl.h +++ b/lustre/include/lustre_ioctl.h @@ -397,7 +397,7 @@ obd_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) #define OBD_IOC_ECHO_ALLOC_SEQ _IOWR('f', 222, struct obd_ioctl_data) #define OBD_IOC_START_LFSCK _IOWR('f', 230, OBD_IOC_DATA_TYPE) #define OBD_IOC_STOP_LFSCK _IOW ('f', 231, OBD_IOC_DATA_TYPE) -/* lustre/lustre_user.h 240-246 */ +/* lustre/lustre_user.h 240-249 */ /* LIBCFS_IOC_DEBUG_MASK 250 */ #define IOC_OSC_SET_ACTIVE _IOWR('h', 21, void *) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index f71cfb2..c81ff8b 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -2175,6 +2175,42 @@ static inline long ll_lease_type_from_fmode(fmode_t fmode) ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0); } +static int ll_file_futimes_3(struct file *file, const struct ll_futimes_3 *lfu) +{ + struct inode *inode = file->f_dentry->d_inode; + struct iattr ia = { + .ia_valid = ATTR_ATIME | ATTR_ATIME_SET | + ATTR_MTIME | ATTR_MTIME_SET | + ATTR_CTIME | ATTR_CTIME_SET, + .ia_atime = { + .tv_sec = lfu->lfu_atime_sec, + .tv_nsec = lfu->lfu_atime_nsec, + }, + .ia_mtime = { + .tv_sec = lfu->lfu_mtime_sec, + .tv_nsec = lfu->lfu_mtime_nsec, + }, + .ia_ctime = { + .tv_sec = lfu->lfu_ctime_sec, + .tv_nsec = lfu->lfu_ctime_nsec, + }, + }; + int rc; + ENTRY; + + if (!capable(CAP_SYS_ADMIN)) + RETURN(-EPERM); + + if (!S_ISREG(inode->i_mode)) + RETURN(-EINVAL); + + mutex_lock(&inode->i_mutex); + rc = ll_setattr_raw(file->f_dentry, &ia, false); + mutex_unlock(&inode->i_mutex); + + RETURN(rc); +} + static long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -2506,7 +2542,16 @@ out: OBD_FREE_PTR(hui); RETURN(rc); } + case LL_IOC_FUTIMES_3: { + struct ll_futimes_3 lfu; + + if (copy_from_user(&lfu, + (const struct ll_futimes_3 __user *)arg, + sizeof(lfu))) + RETURN(-EFAULT); + RETURN(ll_file_futimes_3(file, &lfu)); + } default: { int err; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 92f691f..4a21af3 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -1586,7 +1586,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) } /* We mark all of the fields "set" so MDS/OST does not re-set them */ - if (attr->ia_valid & ATTR_CTIME) { + if (!(attr->ia_valid & ATTR_CTIME_SET) && + (attr->ia_valid & ATTR_CTIME)) { attr->ia_ctime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_CTIME_SET; } @@ -1638,7 +1639,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (attr->ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET | - ATTR_MTIME | ATTR_MTIME_SET)) { + ATTR_MTIME | ATTR_MTIME_SET | + ATTR_CTIME | ATTR_CTIME_SET)) { /* For truncate and utimes sending attributes to OSTs, setting * mtime/atime to the past will be performed under PW [0:EOF] * extent lock (new_size:EOF for truncate). It may seem diff --git a/lustre/tests/sanity-hsm.sh b/lustre/tests/sanity-hsm.sh index 4051de9..d7eab96d 100755 --- a/lustre/tests/sanity-hsm.sh +++ b/lustre/tests/sanity-hsm.sh @@ -1881,7 +1881,7 @@ test_24a() { [ $mtime0 -eq $mtime1 ] || error "restore changed mtime from $mtime0 to $mtime1" - [ $ctime0 -le $ctime1 ] || + [ $ctime0 -eq $ctime1 ] || error "restore changed ctime from $ctime0 to $ctime1" copytool_cleanup @@ -1900,7 +1900,7 @@ test_24a() { [ $mtime0 -eq $mtime1 ] || error "remount changed mtime from $mtime0 to $mtime1" - [ $ctime0 -le $ctime1 ] || + [ $ctime0 -eq $ctime1 ] || error "remount changed ctime from $ctime0 to $ctime1" } run_test 24a "Archive, release, and restore does not change a/mtime (i/o)" @@ -2082,6 +2082,26 @@ test_24d() { } run_test 24d "check that read-only mounts are respected" +test_24e() { + copytool_setup + + mkdir -p $DIR/$tdir + + local f=$DIR/$tdir/$tfile + local fid + + fid=$(make_small $f) || error "cannot create $f" + $LFS hsm_archive $f || error "cannot archive $f" + wait_request_state $fid ARCHIVE SUCCEED + $LFS hsm_release $f || error "cannot release $f" + sleep 5 + + tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir" + + copytool_cleanup +} +run_test 24e "tar succeeds on HSM released files" # LU-6213 + test_25a() { # test needs a running copytool copytool_setup diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 78ab4d8..8f39ce7 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -1163,14 +1163,17 @@ 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, + }; + + /* Set {a,m,c}time of volatile file to that of original. */ + if (ioctl(hcp->data_fd, LL_IOC_FUTIMES_3, &lfu) < 0) { errval = -errno; goto end; } -- 1.8.3.1