]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 5.2 compat: rw_tryupgrade()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 23 May 2019 20:46:33 +0000 (13:46 -0700)
committerGitHub <noreply@github.com>
Thu, 23 May 2019 20:46:33 +0000 (13:46 -0700)
Commit torvalds/linux@46ad0840b has removed the architecture specific
rwsem source and headers leaving only the generic version.  As part
of this change the RWSEM_ACTIVE_READ_BIAS and RWSEM_ACTIVE_WRITE_BIAS
macros were moved to the private kernel/locking/rwsem.h header.
This results in a build failure because these macros were required
to implement the rw_tryupgrade() compatibility function.

In practice, this isn't a major problem because there are only a
few consumers of rw_tryupgrade() and because consumers of rw_tryupgrade
should be written to retry using rw_enter(RW_WRITER).

After auditing all of the callers only dmu_zfetch() was determined
not to perform a retry.  It has been updated in this commit to
resolve this issue.

That said, the rw_tryupgrade() functionality should be considered
for possible removal in a future release due to the difficultly
in supporting the interface.

Reviewed-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #8730

include/spl/sys/rwlock.h
module/spl/spl-rwlock.c
module/zfs/dmu_zfetch.c

index a1c1fd469f9473f4817e2a1af291b6a6061b0089..408defac20d36248848b923e235824a931a758b5 100644 (file)
@@ -36,7 +36,7 @@
 #elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
 #define        SPL_RWSEM_SINGLE_READER_VALUE   (1)
 #define        SPL_RWSEM_SINGLE_WRITER_VALUE   (-1)
-#else
+#elif defined(RWSEM_ACTIVE_MASK)
 #define        SPL_RWSEM_SINGLE_READER_VALUE   (RWSEM_ACTIVE_READ_BIAS)
 #define        SPL_RWSEM_SINGLE_WRITER_VALUE   (RWSEM_ACTIVE_WRITE_BIAS)
 #endif
index 4ffebc8ea646c12ce575c5065ed95539c98a8323..86727ed1957c59b0b76c42e4a42a978081de7dcc 100644 (file)
@@ -85,7 +85,8 @@ __rwsem_tryupgrade(struct rw_semaphore *rwsem)
        spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags);
        return (ret);
 }
-#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
+#elif defined(RWSEM_ACTIVE_MASK)
+#if defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
 static int
 __rwsem_tryupgrade(struct rw_semaphore *rwsem)
 {
@@ -104,6 +105,13 @@ __rwsem_tryupgrade(struct rw_semaphore *rwsem)
        return (val == SPL_RWSEM_SINGLE_READER_VALUE);
 }
 #endif
+#else
+static int
+__rwsem_tryupgrade(struct rw_semaphore *rwsem)
+{
+       return (0);
+}
+#endif
 
 int
 rwsem_tryupgrade(struct rw_semaphore *rwsem)
index 2133518ff4ef5a97e42e28061468aecc45d214c9..364e4d7aa86751ccf6501c72b7747b684d074a5b 100644 (file)
@@ -214,6 +214,7 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data)
        uint64_t end_of_access_blkid;
        end_of_access_blkid = blkid + nblks;
        spa_t *spa = zf->zf_dnode->dn_objset->os_spa;
+       krw_t rw = RW_READER;
 
        if (zfs_prefetch_disable)
                return;
@@ -234,7 +235,8 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data)
        if (blkid == 0)
                return;
 
-       rw_enter(&zf->zf_rwlock, RW_READER);
+retry:
+       rw_enter(&zf->zf_rwlock, rw);
 
        /*
         * Find matching prefetch stream.  Depending on whether the accesses
@@ -272,8 +274,13 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data)
                 * a new stream for it.
                 */
                ZFETCHSTAT_BUMP(zfetchstat_misses);
-               if (rw_tryupgrade(&zf->zf_rwlock))
-                       dmu_zfetch_stream_create(zf, end_of_access_blkid);
+               if (rw == RW_READER && !rw_tryupgrade(&zf->zf_rwlock)) {
+                       rw_exit(&zf->zf_rwlock);
+                       rw = RW_WRITER;
+                       goto retry;
+               }
+
+               dmu_zfetch_stream_create(zf, end_of_access_blkid);
                rw_exit(&zf->zf_rwlock);
                return;
        }