Whamcloud - gitweb
LU-6174 lov: use standard Linux 64 divison macros 43/39343/12
authorJames Simmons <jsimmons@infradead.org>
Wed, 13 Sep 2023 16:24:12 +0000 (12:24 -0400)
committerOleg Drokin <green@whamcloud.com>
Wed, 25 Oct 2023 18:02:07 +0000 (18:02 +0000)
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 <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/39343
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: Timothy Day <timday@amazon.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/lov/lov_internal.h
lustre/lov/lov_io.c
lustre/lov/lov_offset.c
lustre/lov/lov_request.c
lustre/tests/large-lun.sh
lustre/tests/sanity-pfl.sh [changed mode: 0644->0755]

index 4a45578..581c167 100644 (file)
@@ -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);
 
index 8dc3b8e..49615cb 100644 (file)
@@ -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;
index 86d4ae9..5550400 100644 (file)
 
 #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;
 }
index 76074ed..83cb50b 100644 (file)
@@ -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));
index 41a5d2c..d22e67a 100644 (file)
@@ -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
old mode 100644 (file)
new mode 100755 (executable)