}
run_test 60b "mirror merge/split cancel client's in-memory layout gen"
+get_times_61() {
+ stat --format='%X %Y %Z' $file || error "$file: cannot get times"
+}
+
+check_times_61() {
+ local file=$1
+ local -a old=( $2 $3 $4 )
+ local -a new
+
+ new=( $(get_times_61 $file) )
+ ((${old[0]} == ${new[0]})) ||
+ error "$file: atime: old '${old[0]}' != new '${new[0]}'"
+
+ ((${old[1]} == ${new[1]})) ||
+ error "$file: mtime: old '${old[1]}' != new '${new[1]}'"
+}
+
+test_61a() { # LU-14508
+ local file=$DIR/$tdir/$tfile
+ local -a tim
+ local nap=5
+
+ mkdir -p $DIR/$tdir
+ echo "create $file"
+ $LFS setstripe -E1M -Eeof $file || error "setstripe $file failed"
+ echo "create $file-2"
+ $LFS setstripe -E2M -Eeof $file-2 || error "setstripe $file-2 failed"
+
+ echo XXX > $file || error "write $file failed"
+ chown $RUNAS_ID $DIR/$tdir $file || error "chown $file failed"
+
+ echo "sleep $nap seconds, then cat $tfile"
+ sleep $nap
+ cat $file || error "cat $file failed"
+
+ echo "sleep $nap seconds, then re-write $tfile"
+ sleep $nap
+ echo XXXX > $file || error "write $file failed"
+ cp -p $file $file-2 || error "copy $file-2 failed"
+
+ echo "sleep $nap seconds"
+ sleep $nap
+
+ tim=( $(get_times_61 $file) )
+
+ echo "mirror merge $tfile-2 to $tfile and test timestamps"
+ $LFS mirror extend -N -f $file-2 $file ||
+ error "cannot mirror merge $file-2 to $file"
+ check_times_61 $file ${tim[@]}
+
+ echo "mirror extend $tfile and test timestamps"
+ $LFS mirror extend -N -c1 -i1 $file ||
+ error "cannot extend mirror $file"
+ check_times_61 $file ${tim[@]}
+
+ echo "migrate $tfile and test timestamps"
+ $LFS migrate -n $file || error "cannot migrate $file"
+ check_times_61 $file ${tim[@]}
+
+ echo "normal user migrate $tfile and test timestamps"
+ $RUNAS $LFS migrate -n $file || error "cannot migrate $file"
+ check_times_61 $file ${tim[@]}
+}
+run_test 61a "mirror extend and migrate preserve timestamps"
+
+test_61b() { # LU-14508
+ local file=$DIR/$tdir/$tfile
+ local -a tim
+ local nap=5
+
+ mkdir -p $DIR/$tdir
+ echo "create $file"
+ echo XXX > $file || error "create $file failed"
+ chown $RUNAS_ID $DIR/$tdir $file || error "chown $file failed"
+
+ echo "sleep $nap seconds, then cat $tfile"
+ sleep $nap
+ cat $file || error "cat $file failed"
+
+ echo "sleep $nap seconds, then re-write $tfile"
+ sleep $nap
+ echo XXXX > $file || error "write $file failed"
+
+ echo "sleep $nap seconds, then test timestamps"
+ sleep $nap
+
+ tim=( $(get_times_61 $file) )
+
+ echo "mirror extend $tfile and test timestamps"
+ $LFS mirror extend -N -c1 -i1 $file ||
+ error "cannot extend mirror $file"
+ check_times_61 $file ${tim[@]}
+
+ echo "mirror split $tfile and test timestamps"
+ $LFS mirror split -d --mirror-id=1 $file ||
+ error "cannot split mirror 1 off $file"
+ check_times_61 $file ${tim[@]}
+
+ echo "normal user mirror extend $tfile and test timestamps"
+ $RUNAS $LFS mirror extend -N -c1 -i1 $file ||
+ error "cannot extend mirror $file"
+ check_times_61 $file ${tim[@]}
+}
+run_test 61b "mirror extend and split preserve timestamps"
+
+test_61c() { # LU-14508
+ local file=$DIR/$tdir/$tfile
+ local -a tim
+ local nap=5
+
+ mkdir -p $DIR/$tdir
+ echo "create $file"
+ echo XXX > $file || error "create $file failed"
+ chown $RUNAS_ID $DIR/$tdir $file || error "chown $file failed"
+
+ echo "sleep $nap seconds, then cat $tfile"
+ sleep $nap
+ cat $file || error "cat $file failed"
+
+ echo "sleep $nap seconds, then mirror extend $tfile and write it"
+ sleep $nap
+ $LFS mirror extend -N -c1 -i1 $file ||
+ error "cannot extend mirror $file"
+ echo XXXX > $file || error "write $file failed"
+
+ echo "sleep $nap seconds, then resync $tfile and test timestamps"
+ tim=( $(get_times_61 $file) )
+ sleep $nap
+ $LFS mirror resync $file || error "cannot resync mirror $file"
+ check_times_61 $file ${tim[@]}
+
+ echo XXXXXX > $file || error "write $tfile failed"
+
+ echo "normal user resync $tfile and test timestamps"
+ tim=( $(get_times_61 $file) )
+ $RUNAS $LFS mirror resync $file || error "cannot resync mirror $file"
+ check_times_61 $file ${tim[@]}
+}
+run_test 61c "mirror resync preserves timestamps"
+
test_70() {
local tf=$DIR/$tdir/$tfile
echo -n "resync file $tf with '$cmd' .."
if [[ $lock_taken = "true" ]]; then
- flock -x 200 -c "$cmd $tf &> /dev/null" &&
- echo "done" || echo "failed"
+ flock -x 200
+ $cmd $tf &> /dev/null && echo "done" || echo "failed"
flock -u 200
else
$cmd $tf &> /dev/null && echo "done" || echo "failed"
/* even if the file is only read, WR mode is nedeed to allow
* layout swap on fd
*/
- rflags = O_RDWR;
+ rflags = O_RDWR | O_NOATIME;
if (!(migration_flags & MIGRATION_NONDIRECT))
rflags |= O_DIRECT;
fd = open(name, rflags);
return rc;
}
-static int migrate_copy_timestamps(int fd, int fdv)
+static int migrate_set_timestamps(int fd, const struct stat *st)
{
- struct stat st;
-
- if (fstat(fd, &st) == 0) {
- struct timeval tv[2] = {
- {.tv_sec = st.st_atime},
- {.tv_sec = st.st_mtime}
- };
-
- return futimes(fdv, tv);
- }
+ struct timeval tv[2] = {
+ {.tv_sec = st->st_atime},
+ {.tv_sec = st->st_mtime}
+ };
- return -errno;
+ return futimes(fd, tv);
}
static int migrate_block(int fd, int fdv)
{
+ struct stat st;
__u64 dv1;
int gid;
int rc;
int rc2;
+ rc = fstat(fd, &st);
+ if (rc < 0) {
+ error_loc = "cannot stat source file";
+ return -errno;
+ }
+
rc = llapi_get_data_version(fd, &dv1, LL_DV_RD_FLUSH);
if (rc < 0) {
error_loc = "cannot get dataversion";
}
/* Make sure we keep original atime/mtime values */
- rc = migrate_copy_timestamps(fd, fdv);
+ rc = migrate_set_timestamps(fdv, &st);
if (rc < 0) {
- error_loc = "timestamp copy failed";
+ error_loc = "set target file timestamp failed";
goto out_unlock;
}
static int migrate_nonblock(int fd, int fdv)
{
+ struct stat st;
__u64 dv1;
__u64 dv2;
int rc;
+ rc = fstat(fd, &st);
+ if (rc < 0) {
+ error_loc = "cannot stat source file";
+ return -errno;
+ }
+
rc = llapi_get_data_version(fd, &dv1, LL_DV_RD_FLUSH);
if (rc < 0) {
error_loc = "cannot get data version";
}
/* Make sure we keep original atime/mtime values */
- rc = migrate_copy_timestamps(fd, fdv);
+ rc = migrate_set_timestamps(fdv, &st);
if (rc < 0) {
- error_loc = "timestamp copy failed";
- return rc;
+ error_loc = "set target file timestamp failed";
+ return -errno;
}
-
return 0;
}
goto out;
}
- /* Make sure we keep original atime/mtime values */
- rc = migrate_copy_timestamps(fd, fdv);
+ rc = migrate_set_timestamps(fd, &stbuf);
if (rc < 0) {
- error_loc = "cannot copy timestamp";
+ error_loc = "cannot set source file timestamp";
goto out;
}
{
struct llapi_layout *f_layout = NULL;
struct ll_ioc_lease *data = NULL;
+ struct stat st;
int fd = -1;
int fdv = -1;
int rc = 0;
goto out;
}
+ rc = fstat(fd, &st);
+ if (rc < 0) {
+ error_loc = "cannot stat source file";
+ goto out;
+ }
+
rc = migrate_nonblock(fd, fdv);
if (rc < 0) {
llapi_lease_release(fd);
goto out;
}
+ rc = migrate_set_timestamps(fd, &st);
+ if (rc < 0) {
+ error_loc = "cannot set source file timestamp";
+ goto out;
+ }
+
/* Atomically put lease, merge layouts and close. */
data = calloc(1, offsetof(typeof(*data), lil_ids[1]));
if (!data) {
fprintf(stderr, "%s: '%s' llapi_mirror_resync_many: %s.\n",
progname, fname, strerror(-rc));
+ rc = migrate_set_timestamps(fd, &stbuf);
+ if (rc < 0) {
+ fprintf(stderr, "%s: '%s' cannot set timestamps: %s\n",
+ progname, fname, strerror(-rc));
+ goto free_layout;
+ }
+
/* need to do the lease unlock even resync fails */
ioc->lil_mode = LL_LEASE_UNLCK;
ioc->lil_flags = LL_LEASE_RESYNC_DONE;
/* rc2 == 0 means lost lease lock */
if (rc2 == 0 && rc == 0)
rc = -EBUSY;
+ else
+ rc = rc2;
fprintf(stderr, "%s: resync file '%s' failed: %s.\n",
progname, fname,
rc2 == 0 ? "lost lease lock" : strerror(-rc2));
+
+ llapi_lease_release(fd);
+ goto free_layout;
}
free_layout: