From 89736d502cc99f095237dde7520fc4ca86191882 Mon Sep 17 00:00:00 2001 From: Mikhail Pershin Date: Sun, 22 Aug 2021 22:41:33 +0300 Subject: [PATCH] LU-13397 llite: support fallocate() on selected mirror - add ability to do fallocate() on designated mirror in FLR file - add missing FALLOC_FL_KEEP_SIZE flag to fallocate() call in llapi_hole_punch(). It was just not working without that flag silently - add corresponding test_50d in sanity-flr.sh Fixes: 4126fbb30c ("LU-13397 lfs: mirror resync to keep sparseness") Signed-off-by: Mikhail Pershin Change-Id: I8d700fce904c84458a50650f1d3cb09d23989eba Reviewed-on: https://review.whamcloud.com/44721 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Arshad Hussain Reviewed-by: Oleg Drokin --- lustre/llite/file.c | 9 ++++-- lustre/lov/lov_io.c | 3 +- lustre/tests/sanity-flr.sh | 59 +++++++++++++++++++++++++++++++++++++++ lustre/utils/liblustreapi_lseek.c | 3 +- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 75a01e4..0021c76 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -5335,7 +5335,8 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) } #endif -int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len) +int cl_falloc(struct file *file, struct inode *inode, int mode, loff_t offset, + loff_t len) { struct lu_env *env; struct cl_io *io; @@ -5351,6 +5352,8 @@ int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len) io = vvp_env_thread_io(env); io->ci_obj = ll_i2info(inode)->lli_clob; + ll_io_set_mirror(io, file); + io->ci_verify_layout = 1; io->u.ci_setattr.sa_parent_fid = lu_object_fid(&io->ci_obj->co_lu); io->u.ci_setattr.sa_falloc_mode = mode; @@ -5389,7 +5392,7 @@ out: long ll_fallocate(struct file *filp, int mode, loff_t offset, loff_t len) { - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); int rc; if (offset < 0 || len <= 0) @@ -5414,7 +5417,7 @@ long ll_fallocate(struct file *filp, int mode, loff_t offset, loff_t len) ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FALLOCATE, 1); - rc = cl_falloc(inode, mode, offset, len); + rc = cl_falloc(filp, inode, mode, offset, len); /* * ENOTSUPP (524) is an NFSv3 specific error code erroneously * used by Lustre in several places. Retuning it here would diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index 56706b4..b3fd6d8 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -331,7 +331,8 @@ static int lov_io_mirror_init(struct lov_io *lio, struct lov_object *obj, CDEBUG(D_LAYOUT, "designated I/O mirror state: %d\n", lov_flr_state(obj)); - if ((cl_io_is_trunc(io) || io->ci_type == CIT_WRITE) && + if ((cl_io_is_trunc(io) || io->ci_type == CIT_WRITE || + cl_io_is_fallocate(io)) && (io->ci_layout_version != obj->lo_lsm->lsm_layout_gen)) { /* * For resync I/O, the ci_layout_version was the layout diff --git a/lustre/tests/sanity-flr.sh b/lustre/tests/sanity-flr.sh index cff383e..a6dc15d 100644 --- a/lustre/tests/sanity-flr.sh +++ b/lustre/tests/sanity-flr.sh @@ -2674,6 +2674,65 @@ test_50c() { } run_test 50c "punch_hole/mmap_write stale other mirrors" +test_50d() { + $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' || + skip "OST does not support SEEK_HOLE" + (( $LINUX_VERSION_CODE > $(version_code 3.0.0) )) || + skip "client kernel does not support SEEK_HOLE" + + local file=$DIR/$tdir/$tfile + local offset + local prt + local rc + + mkdir -p $DIR/$tdir + + echo " ** create mirrored file $file" + $LFS mirror create -N -E1M -c1 -S1M -E eof \ + -N -E2M -S1M -E eof -S2M $file || + error "cannot create mirrored file" + echo " ** write data chunk at 1M boundary" + dd if=/dev/urandom of=$file bs=1k count=20 seek=1021 || + error "cannot write data at 1M boundary" + echo " ** create hole at the file start" + prt=$(fallocate -p -o 0 -l 1M $file 2>&1) + rc=$? + + if [[ $rc -eq 0 ]]; then + verify_flr_state $file "wp" + elif [[ ! $prt =~ "unsupported" ]]; then + error "punch hole in $file failed: $prt" + else + skip "Fallocate punch is not supported" + fi + + echo " ** verify sparseness" + offset=$(lseek_test -d 1000 $file) + echo " first data offset: $offset" + (( $offset >= 1024 * 1024 )) || + error "src: data is not expected at offset $offset" + + echo " ** resync mirror #2" + $LFS mirror resync $file + + # check llapi_mirror_copy_many correctness + sum_1=$($LFS mirror read -N 1 $file | md5sum) + sum_2=$($LFS mirror read -N 2 $file | md5sum) + [[ $sum_1 == $sum_2 ]] || + error "data mismatch: \'$sum_1\' vs. \'$sum_2\'" + + cancel_lru_locks osc + + # stale first component in mirror #1 + $LFS setstripe --comp-set -I0x10001 --comp-flags=stale,nosync $file + echo " ** verify sparseness of mirror #2" + offset=$(lseek_test -d 1000 $file) + echo " first data offset: $offset" + (( $offset >= 1024 * 1024 )) || + error "src: data is not expected at offset $offset" +} +run_test 50d "mirror rsync keep holes" + test_60a() { $LCTL get_param osc.*.import | grep -q 'connect_flags:.*seek' || skip "OST does not support SEEK_HOLE" diff --git a/lustre/utils/liblustreapi_lseek.c b/lustre/utils/liblustreapi_lseek.c index cd3f008..9073999 100644 --- a/lustre/utils/liblustreapi_lseek.c +++ b/lustre/utils/liblustreapi_lseek.c @@ -127,7 +127,8 @@ int llapi_hole_punch(int fd, off_t start, size_t length) { int rc; - rc = fallocate(fd, FALLOC_FL_PUNCH_HOLE, start, length); + rc = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + start, length); if (rc) rc = -errno; return rc; -- 1.8.3.1