Whamcloud - gitweb
LU-6213 llite: add LL_IOC_FUTIMES_3 65/13665/5
authorJohn L. Hammond <john.hammond@intel.com>
Thu, 5 Feb 2015 23:35:08 +0000 (17:35 -0600)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 26 Aug 2015 15:44:35 +0000 (15:44 +0000)
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 <john.hammond@intel.com>
Change-Id: I98a4913048f902892fdafc514547bbe4d51523d7
Reviewed-on: http://review.whamcloud.com/13665
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: frank zago <fzago@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre/lustre_user.h
lustre/include/lustre_ioctl.h
lustre/llite/file.c
lustre/llite/llite_lib.c
lustre/tests/sanity-hsm.sh
lustre/utils/liblustreapi_hsm.c

index 7f746e1..43c810a 100644 (file)
@@ -220,6 +220,15 @@ struct ost_id {
 #define DOSTID LPX64":"LPU64
 #define POSTID(oi) ostid_seq(oi), ostid_id(oi)
 
 #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
 /*
  * 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_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)
 /*     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)
index 83ef428..a7670f3 100644 (file)
@@ -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)
 #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 *)
 /*     LIBCFS_IOC_DEBUG_MASK   250 */
 
 #define IOC_OSC_SET_ACTIVE     _IOWR('h', 21, void *)
index f71cfb2..c81ff8b 100644 (file)
@@ -2175,6 +2175,42 @@ static inline long ll_lease_type_from_fmode(fmode_t fmode)
               ((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0);
 }
 
               ((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)
 {
 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);
        }
                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;
 
        default: {
                int err;
 
index 92f691f..4a21af3 100644 (file)
@@ -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 */
        }
 
         /* 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;
         }
                 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 |
 
        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
                /* 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
index 4051de9..d7eab96 100755 (executable)
@@ -1881,7 +1881,7 @@ test_24a() {
        [ $mtime0 -eq $mtime1 ] ||
                error "restore changed mtime from $mtime0 to $mtime1"
 
        [ $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
                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"
 
        [ $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)"
                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"
 
 }
 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
 test_25a() {
        # test needs a running copytool
        copytool_setup
index 78ab4d8..8f39ce7 100644 (file)
@@ -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) {
        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;
                }
                        errval = -errno;
                        goto end;
                }