From 6eee4ea5b63e592eb3eb0cc5a91f787226a863e2 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 13 Sep 2023 12:24:12 -0400 Subject: [PATCH] LU-6174 lov: use standard Linux 64 divison macros For the case of 64 bit platforms lov_do_div64() is basically the same as div_u64_rem(). For the 32 bit platform case lustre tries to work around the issue of the divisor being larger than 32 bits. We can also use div64_u64_rem() as well for 32 bit platforms since Linux supports that as well. With the move to Linux div64 operations we need to migrate fields related to 64 bit size fields. To pick the correct div64 function we need to select the proper sign value. The lov layer often uses loff_t, which is signed, for stripe sizes which doesn't make sense since sizes should always be positive. Creating a negative size by mistake will give an bizarre offset into a file. Avoid any potential issues with signed vs unsigned issues by replacing the loff_t use in this case with u64. Test-Parameters: testlist=large-lun env=ONLY=5,REFORMAT=yes Change-Id: Ieadc266d43d6be1d6d47ee14ba9ac0dab01e7d86 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/39343 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Shaun Tancheff Reviewed-by: Andreas Dilger Reviewed-by: Timothy Day Reviewed-by: Oleg Drokin --- lustre/lov/lov_internal.h | 38 ++--------------------------------- lustre/lov/lov_io.c | 8 ++++---- lustre/lov/lov_offset.c | 49 +++++++++++++++++++++------------------------- lustre/lov/lov_request.c | 4 ++-- lustre/tests/large-lun.sh | 16 +++++++++++++++ lustre/tests/sanity-pfl.sh | 0 6 files changed, 46 insertions(+), 69 deletions(-) mode change 100644 => 100755 lustre/tests/sanity-pfl.sh diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index 4a45578..581c167 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -190,40 +190,6 @@ static inline bool lov_supported_comp_magic(unsigned int magic) magic == LOV_MAGIC_FOREIGN; } -/* lov_do_div64(a, b) returns a % b, and a = a / b. - * The 32-bit code is LOV-specific due to knowing about stripe limits in - * order to reduce the divisor to a 32-bit number. If the divisor is - * already a 32-bit value the compiler handles this directly. */ -#if BITS_PER_LONG == 64 -# define lov_do_div64(n, base) ({ \ - uint64_t __base = (base); \ - uint64_t __rem; \ - __rem = ((uint64_t)(n)) % __base; \ - (n) = ((uint64_t)(n)) / __base; \ - __rem; \ -}) -#elif BITS_PER_LONG == 32 -# define lov_do_div64(n, base) ({ \ - uint64_t __num = (n); \ - uint64_t __rem; \ - if ((sizeof(base) > 4) && (((base) & 0xffffffff00000000ULL) != 0)) { \ - int __remainder; \ - LASSERTF(!((base) & (LOV_MIN_STRIPE_SIZE - 1)), \ - "64 bit lov division %llu / %llu\n", \ - __num, (uint64_t)(base)); \ - __remainder = __num & (LOV_MIN_STRIPE_SIZE - 1); \ - __num >>= LOV_MIN_STRIPE_BITS; \ - __rem = do_div(__num, (base) >> LOV_MIN_STRIPE_BITS); \ - __rem <<= LOV_MIN_STRIPE_BITS; \ - __rem += __remainder; \ - } else { \ - __rem = do_div(__num, base); \ - } \ - (n) = __num; \ - __rem; \ -}) -#endif - #define pool_tgt_count(p) ((p)->pool_obds.op_count) #define pool_tgt_array(p) ((p)->pool_obds.op_array) #define pool_tgt_rw_sem(p) ((p)->pool_obds.op_rw_sem) @@ -270,7 +236,7 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, int index, struct cl_attr *attr); /* lov_offset.c */ -loff_t stripe_width(struct lov_stripe_md *lsm, unsigned int index); +u64 stripe_width(struct lov_stripe_md *lsm, unsigned int index); u64 lov_stripe_size(struct lov_stripe_md *lsm, int index, u64 ost_size, int stripeno); int lov_stripe_offset(struct lov_stripe_md *lsm, int index, loff_t lov_off, @@ -279,7 +245,7 @@ loff_t lov_size_to_stripe(struct lov_stripe_md *lsm, int index, u64 file_size, int stripeno); int lov_stripe_intersects(struct lov_stripe_md *lsm, int index, int stripeno, struct lu_extent *ext, u64 *obd_start, u64 *obd_end); -int lov_stripe_number(struct lov_stripe_md *lsm, int index, loff_t lov_off); +int lov_stripe_number(struct lov_stripe_md *lsm, int index, u64 lov_off); pgoff_t lov_stripe_pgoff(struct lov_stripe_md *lsm, int index, pgoff_t stripe_index, int stripe); diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index 8dc3b8e..49615cb 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -878,9 +878,9 @@ static int lov_io_iter_init(const struct lu_env *env, /* need previous stripe involvement */ lio->lis_trunc_stripe_index[index] = prev; } else { - tr_start = ext.e_start; - tr_start = lov_do_div64(tr_start, - stripe_width(lsm, index)); + div64_u64_rem(ext.e_start, + stripe_width(lsm, index), + &tr_start); /* tr_start %= stripe_swidth */ if (tr_start == stripe * lsm-> lsm_entries[index]-> @@ -981,7 +981,7 @@ static int lov_io_rw_iter_init(const struct lu_env *env, if (lse->lsme_stripe_count > 1) { unsigned long ssize = lse->lsme_stripe_size; - lov_do_div64(start, ssize); + start = div64_u64(start, ssize); next = (start + 1) * ssize; if (next <= start * ssize) next = MAX_LFS_FILESIZE; diff --git a/lustre/lov/lov_offset.c b/lustre/lov/lov_offset.c index 86d4ae9..55504008 100644 --- a/lustre/lov/lov_offset.c +++ b/lustre/lov/lov_offset.c @@ -37,26 +37,26 @@ #include "lov_internal.h" -loff_t stripe_width(struct lov_stripe_md *lsm, unsigned int index) +u64 stripe_width(struct lov_stripe_md *lsm, unsigned int index) { struct lov_stripe_md_entry *entry = lsm->lsm_entries[index]; LASSERT(index < lsm->lsm_entry_count); if (lsme_is_dom(entry)) - return (loff_t)entry->lsme_stripe_size; + return entry->lsme_stripe_size; - return (loff_t)entry->lsme_stripe_size * entry->lsme_stripe_count; + return (u64)entry->lsme_stripe_size * entry->lsme_stripe_count; } /* compute object size given "stripeno" and the ost size */ u64 lov_stripe_size(struct lov_stripe_md *lsm, int index, u64 ost_size, int stripeno) { - unsigned long ssize = lsm->lsm_entries[index]->lsme_stripe_size; - unsigned long stripe_size; - loff_t swidth; - loff_t lov_size; + u32 ssize = lsm->lsm_entries[index]->lsme_stripe_size; + u32 stripe_size; + u64 swidth; + u64 lov_size; ENTRY; @@ -65,8 +65,7 @@ u64 lov_stripe_size(struct lov_stripe_md *lsm, int index, u64 ost_size, swidth = stripe_width(lsm, index); - /* lov_do_div64(a, b) returns a % b, and a = a / b */ - stripe_size = lov_do_div64(ost_size, ssize); + ost_size = div_u64_rem(ost_size, ssize, &stripe_size); if (stripe_size) lov_size = ost_size * swidth + stripeno * ssize + stripe_size; else @@ -143,9 +142,7 @@ int lov_stripe_offset(struct lov_stripe_md *lsm, int index, loff_t lov_off, int stripeno, loff_t *obdoff) { unsigned long ssize = lsm->lsm_entries[index]->lsme_stripe_size; - loff_t stripe_off; - loff_t this_stripe; - loff_t swidth; + u64 stripe_off, this_stripe, swidth; int ret = 0; if (lov_off == OBD_OBJECT_EOF) { @@ -155,10 +152,9 @@ int lov_stripe_offset(struct lov_stripe_md *lsm, int index, loff_t lov_off, swidth = stripe_width(lsm, index); - /* lov_do_div64(a, b) returns a % b, and a = a / b */ - stripe_off = lov_do_div64(lov_off, swidth); + lov_off = div64_u64_rem(lov_off, swidth, &stripe_off); - this_stripe = (loff_t)stripeno * ssize; + this_stripe = (u64)stripeno * ssize; if (stripe_off < this_stripe) { stripe_off = 0; ret = -1; @@ -199,19 +195,18 @@ loff_t lov_size_to_stripe(struct lov_stripe_md *lsm, int index, u64 file_size, int stripeno) { unsigned long ssize = lsm->lsm_entries[index]->lsme_stripe_size; - loff_t stripe_off; - loff_t this_stripe; - loff_t swidth; + u64 stripe_off; + u64 this_stripe; + u64 swidth; if (file_size == OBD_OBJECT_EOF) return OBD_OBJECT_EOF; swidth = stripe_width(lsm, index); - /* lov_do_div64(a, b) returns a % b, and a = a / b */ - stripe_off = lov_do_div64(file_size, swidth); + file_size = div64_u64_rem(file_size, swidth, &stripe_off); - this_stripe = (loff_t)stripeno * ssize; + this_stripe = (u64)stripeno * ssize; if (stripe_off < this_stripe) { /* Move to end of previous stripe, or zero */ if (file_size > 0) { @@ -291,18 +286,18 @@ int lov_stripe_intersects(struct lov_stripe_md *lsm, int index, int stripeno, } /* compute which stripe number "lov_off" will be written into */ -int lov_stripe_number(struct lov_stripe_md *lsm, int index, loff_t lov_off) +int lov_stripe_number(struct lov_stripe_md *lsm, int index, u64 lov_off) { unsigned long ssize = lsm->lsm_entries[index]->lsme_stripe_size; - loff_t stripe_off; - loff_t swidth; + u64 stripe_off; + u64 swidth; swidth = stripe_width(lsm, index); - stripe_off = lov_do_div64(lov_off, swidth); + lov_off = div64_u64_rem(lov_off, swidth, &stripe_off); /* Puts stripe_off/ssize result into stripe_off */ - lov_do_div64(stripe_off, ssize); + stripe_off = div_u64(stripe_off, ssize); - return stripe_off; + return (int) stripe_off; } diff --git a/lustre/lov/lov_request.c b/lustre/lov/lov_request.c index 76074ed..83cb50b 100644 --- a/lustre/lov/lov_request.c +++ b/lustre/lov/lov_request.c @@ -151,9 +151,9 @@ lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs, int success) __u32 expected_stripes = lov_get_stripe_count(&obd->u.lov, LOV_MAGIC, 0); if (osfs->os_files != U64_MAX) - lov_do_div64(osfs->os_files, expected_stripes); + do_div(osfs->os_files, expected_stripes); if (osfs->os_ffree != U64_MAX) - lov_do_div64(osfs->os_ffree, expected_stripes); + do_div(osfs->os_ffree, expected_stripes); spin_lock(&obd->obd_osfs_lock); memcpy(&obd->obd_osfs, osfs, sizeof(*osfs)); diff --git a/lustre/tests/large-lun.sh b/lustre/tests/large-lun.sh index 41a5d2c..d22e67a 100644 --- a/lustre/tests/large-lun.sh +++ b/lustre/tests/large-lun.sh @@ -330,6 +330,22 @@ test_4 () { } run_test 4 "run llverfs on lustre filesystem" +test_5() { + # Setup the Lustre filesystem. + log "setup the lustre filesystem" + REFORMAT="yes" check_and_setup_lustre + + $LFS setstripe -C 1024 $MOUNT/$tfile || error "creating $MOUNT/$tfile" + stack_trap "rm -f $MOUNT/$tfile" + + # Create a 32TB size file and write 4K every GB offset + log "run_llverdev $MOUNT/$tfile -p -c 4096 -s 32T" + run_llverdev $MOUNT/$tfile -o 18T -s 33554432 || + error "llverdev failed with rc=$?" + stopall +} +run_test 5 "run llverdev on lustre filesystem" + complete_test $SECONDS $LARGE_LUN_RESTORE_MOUNT && setupall check_and_cleanup_lustre diff --git a/lustre/tests/sanity-pfl.sh b/lustre/tests/sanity-pfl.sh old mode 100644 new mode 100755 -- 1.8.3.1