Whamcloud - gitweb
LU-17533 llite: call merge attr on all writes 16/54016/9
authorPatrick Farrell <paf0187@gmail.com>
Wed, 13 Mar 2024 14:45:44 +0000 (10:45 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 23 Apr 2024 19:47:12 +0000 (19:47 +0000)
Because DIO writes do not update the inode size during the
write, when a file is closed and the LSOM update is sent,
the file size provided by the client is incorrect.

DIO writes don't cause consistency problems because ls and
other things which check the file size will get the correct
size and update the inode size then, but that just means
this issue isn't fatal - DIO should still update the inode
size.

This is best done by calling ll_merge_attr on all writes at
the end of the write, rather than just for async writes in
vvp_io_write_commit.

Signed-off-by: Patrick Farrell <patrick.farrell@oracle.com>
Change-Id: I856b319254ad7093e69e41613120e06b71f656cc
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54016
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/file.c
lustre/llite/vvp_io.c
lustre/mdt/mdt_som.c
lustre/tests/sanity.sh

index 660a966..bc8905b 100644 (file)
@@ -1962,6 +1962,10 @@ out:
                goto restart;
        }
 
+       /* update inode size */
+       if (io->ci_type == CIT_WRITE)
+               ll_merge_attr(env, inode);
+
        if (io->ci_dio_aio) {
                /* set the number of bytes successfully moved in the aio */
                if (result > 0)
index 393167a..ba73f4e 100644 (file)
@@ -1263,9 +1263,6 @@ int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io)
                lli->lli_async_rc = 0;
        }
 
-       /* update inode size */
-       ll_merge_attr(env, inode);
-
        /* Now the pages in queue were failed to commit, discard them
         * unless they were dirtied before.
         */
index c60b220..a7a38e5 100644 (file)
@@ -199,6 +199,10 @@ int mdt_lsom_update(struct mdt_thread_info *info,
        ma = &info->mti_attr;
        la = &ma->ma_attr;
 
+       CDEBUG(D_INODE,
+              "valid %llx, lsom init %d lsom size %llu size %llu lsom blocks %llu blocks %llu truncate %d\n",
+              la->la_valid, o->mot_lsom_inited, o->mot_lsom_size, la->la_size,
+              o->mot_lsom_blocks, la->la_blocks, truncate);
        if (!(la->la_valid & (LA_SIZE | LA_LSIZE) &&
              o->mot_lsom_size < la->la_size) &&
            !(la->la_valid & (LA_BLOCKS | LA_LBLOCKS) &&
index e5a43f5..3cc9051 100755 (executable)
@@ -31253,25 +31253,27 @@ check_lsom_data()
 {
        local file=$1
        local expect=$(stat -c %s $file)
+       local msg=$2
 
-       check_lsom_size $1 $expect
+       check_lsom_size $1 $expect $msg
 
        local blocks=$($LFS getsom -b $file)
        expect=$(stat -c %b $file)
        [[ $blocks == $expect ]] ||
-               error "$file expected blocks: $expect, got: $blocks"
+               error "$msg $file expected blocks: $expect, got: $blocks"
 }
 
 check_lsom_size()
 {
        local size
        local expect=$2
+       local msg=$3
 
        cancel_lru_locks mdc
 
        size=$($LFS getsom -s $1)
        [[ $size == $expect ]] ||
-               error "$file expected size: $expect, got: $size"
+               error "$msg $file expected size: $expect, got: $size"
 }
 
 test_806() {
@@ -31289,7 +31291,11 @@ test_806() {
        echo "Test SOM for single-threaded write"
        dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 ||
                error "write $tfile failed"
-       check_lsom_size $DIR/$tfile $bs
+       check_lsom_size $DIR/$tfile $bs "(0)"
+       # Test SOM with DIO write (dd truncates to 0)
+       dd if=/dev/zero of=$DIR/$tfile bs=$bs count=1 oflag=direct ||
+               error "write $tfile failed"
+       check_lsom_size $DIR/$tfile $bs "(1)"
 
        local num=32
        local size=$(($num * $bs))
@@ -31306,7 +31312,7 @@ test_806() {
        for (( i=0; i < $num; i++ )); do
                wait ${pids[$i]}
        done
-       check_lsom_size $DIR/$tfile $size
+       check_lsom_size $DIR/$tfile $size "(2)"
 
        $TRUNCATE $DIR/$tfile 0
        for ((i = 0; i < $num; i++)); do
@@ -31317,7 +31323,7 @@ test_806() {
        for (( i=0; i < $num; i++ )); do
                wait ${pids[$i]}
        done
-       check_lsom_size $DIR/$tfile $size
+       check_lsom_size $DIR/$tfile $size "(3)"
 
        # multi-client writes
        num=$(get_node_count ${CLIENTS//,/ })
@@ -31336,7 +31342,7 @@ test_806() {
        for (( i=0; i < $num; i++ )); do
                wait ${pids[$i]}
        done
-       check_lsom_size $DIR/$tfile $offset
+       check_lsom_size $DIR/$tfile $offset "(4)"
 
        i=0
        $TRUNCATE $DIR/$tfile 0
@@ -31349,37 +31355,37 @@ test_806() {
        for (( i=0; i < $num; i++ )); do
                wait ${pids[$i]}
        done
-       check_lsom_size $DIR/$tfile $size
+       check_lsom_size $DIR/$tfile $size "(5)"
 
        # verify SOM blocks count
        echo "Verify SOM block count"
        $TRUNCATE $DIR/$tfile 0
        $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs))YSc ||
                error "failed to write file $tfile with fdatasync and fstat"
-       check_lsom_data $DIR/$tfile
+       check_lsom_data $DIR/$tfile "(6)"
 
        $TRUNCATE $DIR/$tfile 0
        $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:w$((bs * 2))Yc ||
                error "failed to write file $tfile with fdatasync"
-       check_lsom_data $DIR/$tfile
+       check_lsom_data $DIR/$tfile "(7)"
 
        $TRUNCATE $DIR/$tfile 0
        $MULTIOP $DIR/$tfile oO_TRUNC:O_RDWR:O_SYNC:w$((bs * 3))c ||
                error "failed to write file $tfile with sync IO"
-       check_lsom_data $DIR/$tfile
+       check_lsom_data $DIR/$tfile "(8)"
 
        # verify truncate
        echo "Test SOM for truncate"
        # use ftruncate to sync blocks on close request
        $MULTIOP $DIR/$tfile oO_WRONLY:T16384c
-       check_lsom_size $DIR/$tfile 16384
-       check_lsom_data $DIR/$tfile
+       check_lsom_size $DIR/$tfile 16384 "(9)"
+       check_lsom_data $DIR/$tfile "(10)"
 
        $TRUNCATE $DIR/$tfile 1234
-       check_lsom_size $DIR/$tfile 1234
+       check_lsom_size $DIR/$tfile 1234 "(11)"
        # sync blocks on the MDT
        $MULTIOP $DIR/$tfile oc
-       check_lsom_data $DIR/$tfile
+       check_lsom_data $DIR/$tfile "(12)"
 }
 run_test 806 "Verify Lazy Size on MDS"
 
@@ -31428,9 +31434,9 @@ test_807() {
        do_rpc_nodes "$CLIENTS" cancel_lru_locks osc
        do_nodes "$CLIENTS" "sync ; sleep 5 ; sync"
        $LSOM_SYNC -u $cl_user -m $FSNAME-MDT0000 $MOUNT
-       check_lsom_data $DIR/$tdir/trunc
-       check_lsom_data $DIR/$tdir/single_dd
-       check_lsom_data $DIR/$tfile
+       check_lsom_data $DIR/$tdir/trunc "(0)"
+       check_lsom_data $DIR/$tdir/single_dd "(1)"
+       check_lsom_data $DIR/$tfile "(2)"
 
        rm -rf $DIR/$tdir
        # Deregistration step