Whamcloud - gitweb
LU-3916 lprocfs: export lprocfs setup race
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
index 46eb347..885287c 100644 (file)
@@ -272,13 +272,13 @@ int lprocfs_evict_client_open(struct inode *inode, struct file *f)
 
 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
 {
-        struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
-        struct obd_device *obd = dp->data;
+       struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
+       struct obd_device *obd = dp->data;
 
-        cfs_atomic_dec(&obd->obd_evict_inprogress);
-        cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
+       cfs_atomic_dec(&obd->obd_evict_inprogress);
+       wake_up(&obd->obd_evict_inprogress_waitq);
 
-        return 0;
+       return 0;
 }
 
 struct file_operations lprocfs_evict_client_fops = {
@@ -1969,6 +1969,13 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
         if (!nid || *nid == LNET_NID_ANY)
                 RETURN(0);
 
+       spin_lock(&exp->exp_lock);
+       if (exp->exp_nid_stats != NULL) {
+               spin_unlock(&exp->exp_lock);
+               RETURN(-EALREADY);
+       }
+       spin_unlock(&exp->exp_lock);
+
         obd = exp->exp_obd;
 
         CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
@@ -1988,19 +1995,12 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
                old_stat, libcfs_nid2str(*nid),
                cfs_atomic_read(&new_stat->nid_exp_ref_count));
 
-        /* We need to release old stats because lprocfs_exp_cleanup() hasn't
-         * been and will never be called. */
-        if (exp->exp_nid_stats) {
-                nidstat_putref(exp->exp_nid_stats);
-                exp->exp_nid_stats = NULL;
-        }
-
-        /* Return -EALREADY here so that we know that the /proc
-         * entry already has been created */
-        if (old_stat != new_stat) {
-                exp->exp_nid_stats = old_stat;
-                GOTO(destroy_new, rc = -EALREADY);
-        }
+       /* Return -EALREADY here so that we know that the /proc
+        * entry already has been created */
+       if (old_stat != new_stat) {
+               nidstat_putref(old_stat);
+               GOTO(destroy_new, rc = -EALREADY);
+       }
         /* not found - create */
         OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
         if (buffer == NULL)
@@ -2036,7 +2036,9 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
                 GOTO(destroy_new_ns, rc);
         }
 
-        exp->exp_nid_stats = new_stat;
+       spin_lock(&exp->exp_lock);
+       exp->exp_nid_stats = new_stat;
+       spin_unlock(&exp->exp_lock);
         *newnid = 1;
         /* protect competitive add to list, not need locking on destroy */
        spin_lock(&obd->obd_nid_lock);
@@ -2343,12 +2345,12 @@ EXPORT_SYMBOL(lprocfs_oh_tally);
 
 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
 {
-        unsigned int val;
+       unsigned int val = 0;
 
-        for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
-                ;
+       if (likely(value != 0))
+               val = min(fls(value - 1), OBD_HIST_MAX);
 
-        lprocfs_oh_tally(oh, val);
+       lprocfs_oh_tally(oh, val);
 }
 EXPORT_SYMBOL(lprocfs_oh_tally_log2);