/* in lprocfs_stat.c, to protect the private data for proc entries */
extern cfs_rw_semaphore_t _lprocfs_lock;
+
+/* to begin from 2.6.23, Linux defines self file_operations (proc_reg_file_ops)
+ * in procfs, the proc file_operation defined by Lustre (lprocfs_generic_fops)
+ * will be wrapped into the new defined proc_reg_file_ops, which instroduces
+ * user count in proc_dir_entrey(pde_users) to protect the proc entry from
+ * being deleted. then the protection lock (_lprocfs_lock) defined by Lustre
+ * 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 { \
cfs_down_read(&_lprocfs_lock); \
} while(0)
+
#define LPROCFS_EXIT() \
do { \
cfs_up_read(&_lprocfs_lock); \
} while(0)
+#else
+#define LPROCFS_ENTRY() do{ }while(0)
+#define LPROCFS_EXIT() do{ }while(0)
+#endif
+
#ifdef HAVE_PROCFS_DELETED
+
+#ifdef HAVE_PROCFS_USERS
+#error proc_dir_entry->deleted is conflicted with proc_dir_entry->pde_users
+#endif
+
static inline
int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp)
{
}
return 0;
}
+#elif defined(HAVE_PROCFS_USERS) /* !HAVE_PROCFS_DELETED*/
+static inline
+int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp)
+{
+ int deleted = 0;
+ spin_lock(&(dp)->pde_unload_lock);
+ if (dp->proc_fops == NULL)
+ deleted = 1;
+ spin_unlock(&(dp)->pde_unload_lock);
+ if (deleted)
+ return -ENODEV;
+ return 0;
+}
#else /* !HAVE_PROCFS_DELETED*/
static inline
int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp)
return 0;
}
#endif /* HAVE_PROCFS_DELETED */
+#define LPROCFS_SRCH_ENTRY() \
+do { \
+ down_read(&_lprocfs_lock); \
+} while(0)
+
+#define LPROCFS_SRCH_EXIT() \
+do { \
+ up_read(&_lprocfs_lock); \
+} while(0)
#define LPROCFS_WRITE_ENTRY() \
do { \
cfs_down_write(&_lprocfs_lock); \
} while(0)
+
#define LPROCFS_WRITE_EXIT() \
do { \
cfs_up_write(&_lprocfs_lock); \
} while(0)
-
#else /* !LPROCFS */
typedef struct cfs_params_file {
])
])
+# 2.6.23 add code to wait other users to complete before removing procfs entry
+AC_DEFUN([LC_PROCFS_USERS],
+[AC_MSG_CHECKING([if kernel has pde_users member in procfs entry struct])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/proc_fs.h>
+],[
+ struct proc_dir_entry pde;
+
+ pde.pde_users = 0;
+],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_PROCFS_USERS, 1,
+ [kernel has pde_users member in procfs entry struct])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
# 2.6.24 has bio_endio with 2 args
AC_DEFUN([LC_BIO_ENDIO_2ARG],
[AC_MSG_CHECKING([if kernel has bio_endio with 2 args])
LC_HAVE_EXPORTFS_H
LC_VM_OP_FAULT
LC_REGISTER_SHRINKER
+ LC_PROCFS_USERS
# 2.6.24
LC_HAVE_MMTYPES_H
{
struct proc_dir_entry *temp;
- LPROCFS_ENTRY();
+ LPROCFS_SRCH_ENTRY();
temp = __lprocfs_srch(head, name);
- LPROCFS_EXIT();
+ LPROCFS_SRCH_EXIT();
return temp;
}
"0x%p %s/%s len %d\n", rm_entry, temp->name,
rm_entry->name, (int)strlen(rm_entry->name));
+#ifdef HAVE_PROCFS_USERS
+ /* if procfs uses user count to synchronize deletion of
+ * proc entry, there is no protection for rm_entry->data,
+ * then lprocfs_fops_read and lprocfs_fops_write maybe
+ * call proc_dir_entry->read_proc (or write_proc) with
+ * proc_dir_entry->data == NULL, then cause kernel Oops.
+ * see bug19706 for detailed information */
+
+ /* procfs won't free rm_entry->data if it isn't a LINK,
+ * and Lustre won't use rm_entry->data if it is a LINK */
+ if (S_ISLNK(rm_entry->mode))
+ rm_entry->data = NULL;
+#else
/* Now, the rm_entry->deleted flags is protected
* by _lprocfs_lock. */
rm_entry->data = NULL;
+#endif
remove_proc_entry(rm_entry->name, temp);
if (temp == parent)
break;