Whamcloud - gitweb
LU-1484 lprocfs: handle hidden proc_dir_entry users
authorAndreas Dilger <andreas.dilger@intel.com>
Sat, 2 Feb 2013 00:22:13 +0000 (17:22 -0700)
committerJohann Lombardi <johann.lombardi@intel.com>
Tue, 5 Feb 2013 13:51:44 +0000 (08:51 -0500)
The RHEL 5.9 2.6.18-348.1.1.el5 kernel uses both the new style
"pde_users" and the old style "deleted" flags for marking a
proc_dir_entry as deleted.  Unfortunately, the new "pde_users"
data is hidden in an external structure that is not visible to
the callers or in the headers (for binary compatibility I guess?)
so our configure checks cannot find it.

Instead, just check for proc_fops == NULL in a racy manner on
such kernels, since we cannot do locking and the locking is
mostly just needed as a memory barrier since pde_fops could
become NULL at any time after dropping the lock.

Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Change-Id: I05cae305e24ffff09a06e3ad17c28c175c3ebbe5
Reviewed-on: http://review.whamcloud.com/5253
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Johann Lombardi <johann.lombardi@intel.com>
lustre/include/lprocfs_status.h
lustre/obdclass/lprocfs_status.c

index f1cffb3..93a2ab2 100644 (file)
@@ -547,55 +547,38 @@ extern struct rw_semaphore _lprocfs_lock;
  * isn't necessary anymore for lprocfs_generic_fops(e.g. lprocfs_fops_read).
  * see bug19706 for detailed information.
  */
-#ifndef HAVE_PROCFS_USERS
-
-#define LPROCFS_ENTRY()           do {  \
-        down_read(&_lprocfs_lock);      \
-} while(0)
-#define LPROCFS_EXIT()            do {  \
-        up_read(&_lprocfs_lock);        \
-} while(0)
-
-#else
-
+#ifdef HAVE_PROCFS_USERS /* added in 2.6.23 */
 #define LPROCFS_ENTRY()
 #define LPROCFS_EXIT()
+#else
+#define LPROCFS_ENTRY() down_read(&_lprocfs_lock)
+#define LPROCFS_EXIT()  up_read(&_lprocfs_lock)
 #endif
 
-#ifdef HAVE_PROCFS_DELETED
-
-#define LPROCFS_ENTRY_AND_CHECK(dp) do {        \
-        typecheck(struct proc_dir_entry *, dp); \
-        LPROCFS_ENTRY();                        \
-        if ((dp)->deleted) {                    \
-                LPROCFS_EXIT();                 \
-                return -ENODEV;                 \
-        }                                       \
-} while(0)
-#define LPROCFS_CHECK_DELETED(dp) ((dp)->deleted)
-
-#elif defined HAVE_PROCFS_USERS
-
-#define LPROCFS_CHECK_DELETED(dp) ({            \
-        int deleted = 0;                        \
-        spin_lock(&(dp)->pde_unload_lock);      \
-        if (dp->proc_fops == NULL)              \
-                deleted = 1;                    \
-        spin_unlock(&(dp)->pde_unload_lock);    \
-        deleted;                                \
-})
-
-#define LPROCFS_ENTRY_AND_CHECK(dp) do {        \
-        if (LPROCFS_CHECK_DELETED(dp))          \
-                return -ENODEV;                 \
-} while(0)
+static inline int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp)
+{
+        int deleted = 0;
 
-#else
+#if (defined(HAVE_PROCFS_USERS) && !defined(HAVE_PROCFS_DELETED))
+        spin_lock(&dp->pde_unload_lock);
+#endif
+        if (unlikely(dp->proc_fops == NULL))
+                deleted = 1;
+#if (defined(HAVE_PROCFS_USERS) && !defined(HAVE_PROCFS_DELETED))
+        spin_unlock(&dp->pde_unload_lock);
+#endif
+        if (unlikely(deleted == 1))
+                return deleted;
 
-#define LPROCFS_ENTRY_AND_CHECK(dp) \
         LPROCFS_ENTRY();
-#define LPROCFS_CHECK_DELETED(dp) (0)
+#if defined(HAVE_PROCFS_DELETED)
+        if (unlikely(dp->deleted)) {
+                LPROCFS_EXIT();
+                deleted = 1;
+        }
 #endif
+        return deleted;
+}
 
 #define LPROCFS_SRCH_ENTRY()      do {  \
         down_read(&_lprocfs_lock);      \
index 6d68fc5..51748b9 100644 (file)
@@ -158,12 +158,12 @@ static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, size_t size,
         if (page == NULL)
                 return -ENOMEM;
 
-        LPROCFS_ENTRY();
-        OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
-        if (!LPROCFS_CHECK_DELETED(dp) && dp->read_proc)
+        if (LPROCFS_ENTRY_AND_CHECK(dp) == 0 && dp->read_proc != NULL) {
+                OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
                 rc = dp->read_proc(page, &start, *ppos, PAGE_SIZE,
                         &eof, dp->data);
-        LPROCFS_EXIT();
+                LPROCFS_EXIT();
+        }
         if (rc <= 0)
                 goto out;
 
@@ -199,10 +199,10 @@ static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
         int rc = -EIO;
 
-        LPROCFS_ENTRY();
-        if (!LPROCFS_CHECK_DELETED(dp) && dp->write_proc)
+        if (LPROCFS_ENTRY_AND_CHECK(dp) == 0 && dp->write_proc != NULL) {
                 rc = dp->write_proc(f, buf, size, dp->data);
-        LPROCFS_EXIT();
+                LPROCFS_EXIT();
+        }
         return rc;
 }