From 81611d7a7cd87daae9bbdbebb028b434ddde57af Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Mon, 1 Apr 2024 11:28:49 -0400 Subject: [PATCH] LU-17550 lov: check for empty layout on DIO When a write crosses from an area of a file with a layout to one without, the write should return ENODATA. Due to layout caching in the direct IO path, we need an extra check for this to work correctly for DIO. Fixes: 14db1faa0f ("LU-13799 lov: Cache stripe offset calculation") Signed-off-by: Patrick Farrell Change-Id: Ib9a40dab7939d9420144ecaa7460625d6184aa0b Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54077 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Shaun Tancheff Reviewed-by: Oleg Drokin --- lustre/lov/lov_cl_internal.h | 1 + lustre/lov/lov_io.c | 13 +++++++++++++ lustre/lov/lov_page.c | 8 +++++++- lustre/tests/sanity-pfl.sh | 6 ++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lustre/lov/lov_cl_internal.h b/lustre/lov/lov_cl_internal.h index eabe028..9bccabc 100644 --- a/lustre/lov/lov_cl_internal.h +++ b/lustre/lov/lov_cl_internal.h @@ -596,6 +596,7 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env, struct lu_device *dev); int lov_io_layout_at(struct lov_io *lio, __u64 offset); +bool lov_io_layout_at_confirm(struct lov_io *lio, int entry, __u64 offset); #define lov_foreach_target(lov, var) \ for (var = 0; var < lov_targets_nr(lov); ++var) diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index aa3c71a..bd235b8 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -1999,6 +1999,19 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, RETURN(result); } +/* confirm this offset is in the given layout entry */ +bool lov_io_layout_at_confirm(struct lov_io *lio, int entry, __u64 offset) +{ + struct lov_object *lov = lio->lis_object; + struct lov_layout_entry *lle = lov_entry(lov, entry); + + if ((offset >= lle->lle_extent->e_start && + offset < lle->lle_extent->e_end) || + (offset == OBD_OBJECT_EOF && + lle->lle_extent->e_end == OBD_OBJECT_EOF)) + return true; + return false; +} /** * Return the index in composite:lo_entries by the file offset */ diff --git a/lustre/lov/lov_page.c b/lustre/lov/lov_page.c index 3bf4721..db0c852 100644 --- a/lustre/lov/lov_page.c +++ b/lustre/lov/lov_page.c @@ -77,13 +77,19 @@ int lov_page_init_composite(const struct lu_env *env, struct cl_object *obj, if (stripe_cached) { entry = lio->lis_cached_entry; + /* if there's no layout at this offset, we'll end up here with + * a cached layout entry, so we must verify the layout includes + * this offset + */ + if (!lov_io_layout_at_confirm(lio, entry, offset)) + return -ENODATA; stripe = lio->lis_cached_stripe; /* Offset can never go backwards in an i/o, so this is valid */ suboff = lio->lis_cached_suboff + offset - lio->lis_cached_off; } else { entry = lov_io_layout_at(lio, offset); if (entry < 0) - return(-ENODATA); + return -ENODATA; stripe = lov_stripe_number(loo->lo_lsm, entry, offset); rc = lov_stripe_offset(loo->lo_lsm, entry, offset, stripe, diff --git a/lustre/tests/sanity-pfl.sh b/lustre/tests/sanity-pfl.sh index cc78292..7544f3e 100755 --- a/lustre/tests/sanity-pfl.sh +++ b/lustre/tests/sanity-pfl.sh @@ -2565,6 +2565,8 @@ test_26a() { $LFS setstripe -E 1m -S 1M -c 1 $DIR/$tfile dd if=/dev/urandom bs=1M count=10 >> $DIR/$tfile [ $? != 0 ] || error "append must return an error" + dd if=/dev/urandom bs=1M count=10 oflag=direct >> $DIR/$tfile + [ $? != 0 ] || error "append must return an error" } run_test 26a "Append to not-existent component" @@ -2573,6 +2575,8 @@ test_26b() { dd if=/dev/urandom bs=1M count=1 > $DIR/$tfile dd if=/dev/urandom bs=1M count=1 >> $DIR/$tfile [ $? != 0 ] || error "append must return an error" + dd if=/dev/urandom bs=1M count=1 oflag=direct >> $DIR/$tfile + [ $? != 0 ] || error "append must return an error" } run_test 26b "Append to not-existend component, file size is unknown" @@ -2580,6 +2584,8 @@ test_26c() { $LFS setstripe -E 1m -S 1M -c 1 $DIR/$tfile dd if=/dev/urandom bs=2M count=1 >> $DIR/$tfile [ $? != 0 ] || error "append must return an error" + dd if=/dev/urandom bs=2M count=1 oflag=direct >> $DIR/$tfile + [ $? != 0 ] || error "append must return an error" } run_test 26c "Append to not-existend component, crossing the component border" -- 1.8.3.1