Whamcloud - gitweb
LU-12193 quota: use rw_sem to protect lqs_hash 95/36795/3
authorSergey Cheremencev <c17829@cray.com>
Tue, 19 Nov 2019 13:09:14 +0000 (16:09 +0300)
committerOleg Drokin <green@whamcloud.com>
Sat, 14 Dec 2019 05:57:59 +0000 (05:57 +0000)
Patch introduces rw semaphore for locking
in cfs_hash_lock. It is used to protect lqs_hash
instead of rw_lock to avoid sleeping in atomic:

BUG: sleeping function called from invalid context at kernel/rwsem.c:51
in_atomic(): 1, irqs_disabled(): 0, pid: 11265, name: mdt00_004
CPU: 0 PID: 11265 Comm: mdt00_004 Kdump: loaded Tainted: P
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Call Trace:
 [<ffffffff817b5bf2>] dump_stack+0x19/0x1b
 [<ffffffff810c3bc9>] __might_sleep+0xd9/0x100
 [<ffffffff817bc470>] down_write+0x20/0x50
 [<ffffffffa0a7dad9>] qmt_set_with_lqe+0x3a9/0x750 [lquota]
 [<ffffffffa0a7dede>] qmt_entry_iter_cb+0x5e/0xa0 [lquota]
 [<ffffffffa01b327c>] cfs_hash_for_each_tight+0x10c/0x300 [libcfs]
 [<ffffffffa01b3503>] cfs_hash_for_each_safe+0x13/0x20 [libcfs]
 [<ffffffffa0a7db4f>] qmt_set_with_lqe+0x41f/0x750 [lquota]
 [<ffffffffa0a7dfa9>] qmt_set.constprop.15+0x89/0x2a0 [lquota]
 [<ffffffffa0a7e649>] qmt_quotactl+0x489/0x560 [lquota]
 [<ffffffffa0cc3a90>] mdt_quotactl+0x620/0x770 [mdt]
 [<ffffffffa06860f5>] tgt_request_handle+0x915/0x15c0 [ptlrpc]
 [<ffffffffa0628639>] ptlrpc_server_handle_request+0x259/0xad0 [ptlrpc]
 [<ffffffffa062c771>] ptlrpc_main+0xca1/0x2290 [ptlrpc]
 [<ffffffff810b4ed4>] kthread+0xe4/0xf0
 [<ffffffff817cac77>] ret_from_fork_nospec_begin+0x21/0x21
[  280.258396] BUG: scheduling while atomic: mdt00_004/11265/0x10000003

Change-Id: Id9238f9001c38105fb91d29c47fa34ad35158b40
Signed-off-by: Sergey Cheremencev <c17829@cray.com>
Reviewed-on: https://review.whamcloud.com/36795
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alexandr Boyko <c17825@cray.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/include/libcfs/libcfs_hash.h
libcfs/libcfs/hash.c
lustre/quota/lquota_entry.c

index bd3d7d0..b541fe3 100644 (file)
@@ -74,6 +74,7 @@ struct cfs_hash_hlist_ops;
 union cfs_hash_lock {
        rwlock_t                rw;             /**< rwlock */
        spinlock_t              spin;           /**< spinlock */
+       struct rw_semaphore     rw_sem;         /**< rwsem */
 };
 
 /**
@@ -155,6 +156,8 @@ enum cfs_hash_tag {
          * change on hash table is non-blocking
          */
         CFS_HASH_NBLK_CHANGE    = 1 << 13,
+       /** rw semaphore lock to protect bucket */
+       CFS_HASH_RW_SEM_BKTLOCK = 1 << 14,
         /** NB, we typed hs_flags as  __u16, please change it
          * if you need to extend >=16 flags */
 };
@@ -360,6 +363,13 @@ cfs_hash_with_spin_bktlock(struct cfs_hash *hs)
 }
 
 static inline int
+cfs_hash_with_rw_sem_bktlock(struct cfs_hash *hs)
+{
+       /* rw sem lock to protect hash bucket */
+       return (hs->hs_flags & CFS_HASH_RW_SEM_BKTLOCK) != 0;
+}
+
+static inline int
 cfs_hash_with_add_tail(struct cfs_hash *hs)
 {
         return (hs->hs_flags & CFS_HASH_ADD_TAIL) != 0;
index 3d2127f..9fee65e 100644 (file)
@@ -156,6 +156,26 @@ cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive)
                write_unlock(&lock->rw);
 }
 
+static inline void
+cfs_hash_rw_sem_lock(union cfs_hash_lock *lock, int exclusive)
+       __acquires(&lock->rw_sem)
+{
+       if (!exclusive)
+               down_read(&lock->rw_sem);
+       else
+               down_write(&lock->rw_sem);
+}
+
+static inline void
+cfs_hash_rw_sem_unlock(union cfs_hash_lock *lock, int exclusive)
+       __releases(&lock->rw_sem)
+{
+       if (!exclusive)
+               up_read(&lock->rw_sem);
+       else
+               up_write(&lock->rw_sem);
+}
+
 /** No lock hash */
 static struct cfs_hash_lock_ops cfs_hash_nl_lops = {
        .hs_lock        = cfs_hash_nl_lock,
@@ -204,6 +224,22 @@ static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_lops = {
        .hs_bkt_unlock  = cfs_hash_rw_unlock,
 };
 
+/** rw_sem bucket lock, rehash is disabled */
+static struct cfs_hash_lock_ops cfs_hash_nr_bkt_rw_sem_lops = {
+       .hs_lock        = cfs_hash_nl_lock,
+       .hs_unlock      = cfs_hash_nl_unlock,
+       .hs_bkt_lock    = cfs_hash_rw_sem_lock,
+       .hs_bkt_unlock  = cfs_hash_rw_sem_unlock,
+};
+
+/** rw_sem bucket lock, rehash is enabled */
+static struct cfs_hash_lock_ops cfs_hash_bkt_rw_sem_lops = {
+       .hs_lock        = cfs_hash_rw_sem_lock,
+       .hs_unlock      = cfs_hash_rw_sem_unlock,
+       .hs_bkt_lock    = cfs_hash_rw_sem_lock,
+       .hs_bkt_unlock  = cfs_hash_rw_sem_unlock,
+};
+
 static void
 cfs_hash_lock_setup(struct cfs_hash *hs)
 {
@@ -215,19 +251,26 @@ cfs_hash_lock_setup(struct cfs_hash *hs)
                spin_lock_init(&hs->hs_lock.spin);
 
        } else if (cfs_hash_with_rehash(hs)) {
-               rwlock_init(&hs->hs_lock.rw);
-
-                if (cfs_hash_with_rw_bktlock(hs))
-                        hs->hs_lops = &cfs_hash_bkt_rw_lops;
-                else if (cfs_hash_with_spin_bktlock(hs))
-                        hs->hs_lops = &cfs_hash_bkt_spin_lops;
-                else
-                        LBUG();
+               if (cfs_hash_with_rw_sem_bktlock(hs)) {
+                       init_rwsem(&hs->hs_lock.rw_sem);
+                       hs->hs_lops = &cfs_hash_bkt_rw_sem_lops;
+               } else {
+                       rwlock_init(&hs->hs_lock.rw);
+
+                       if (cfs_hash_with_rw_bktlock(hs))
+                               hs->hs_lops = &cfs_hash_bkt_rw_lops;
+                       else if (cfs_hash_with_spin_bktlock(hs))
+                               hs->hs_lops = &cfs_hash_bkt_spin_lops;
+                       else
+                               LBUG();
+               }
         } else {
                 if (cfs_hash_with_rw_bktlock(hs))
                         hs->hs_lops = &cfs_hash_nr_bkt_rw_lops;
                 else if (cfs_hash_with_spin_bktlock(hs))
                         hs->hs_lops = &cfs_hash_nr_bkt_spin_lops;
+               else if (cfs_hash_with_rw_sem_bktlock(hs))
+                       hs->hs_lops = &cfs_hash_nr_bkt_rw_sem_lops;
                 else
                         LBUG();
         }
@@ -925,6 +968,8 @@ cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
                        rwlock_init(&new_bkts[i]->hsb_lock.rw);
                else if (cfs_hash_with_spin_bktlock(hs))
                        spin_lock_init(&new_bkts[i]->hsb_lock.spin);
+               else if (cfs_hash_with_rw_sem_bktlock(hs))
+                       init_rwsem(&new_bkts[i]->hsb_lock.rw_sem);
                else
                        LBUG(); /* invalid use-case */
        }
index 3cc8fb2..ee73c16 100644 (file)
@@ -228,7 +228,11 @@ struct lquota_site *lquota_site_alloc(const struct lu_env *env, void *parent,
                                            HASH_LQE_BKT_BITS),
                                        0, CFS_HASH_MIN_THETA,
                                        CFS_HASH_MAX_THETA, &lqe64_hash_ops,
-                                       CFS_HASH_DEFAULT|CFS_HASH_BIGNAME);
+                                       CFS_HASH_RW_SEM_BKTLOCK |
+                                       CFS_HASH_COUNTER |
+                                       CFS_HASH_REHASH |
+                                       CFS_HASH_BIGNAME);
+
        if (site->lqs_hash == NULL) {
                OBD_FREE_PTR(site);
                RETURN(ERR_PTR(-ENOMEM));