From: Oleg Drokin Date: Tue, 23 Jul 2013 06:00:09 +0000 (+0000) Subject: Revert "LU-2800 autoconf: remove LC_PROCFS_USERS test" X-Git-Tag: 2.4.53~40 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=bc71055256db623ba2062f8f299d8b603d89e0d9 Revert "LU-2800 autoconf: remove LC_PROCFS_USERS test" Unfortunately this now breaks build due to a new user of the function emerged. This reverts commit 663ef6abd788c3388cae8d5bc5421bad99979c8b Change-Id: If69fe87cea77c83ae815a1125f2cdbce0caaa1db Reviewed-on: http://review.whamcloud.com/7083 Reviewed-by: Oleg Drokin Tested-by: Oleg Drokin --- diff --git a/libcfs/include/libcfs/params_tree.h b/libcfs/include/libcfs/params_tree.h index 41413eb..1bf8d37 100644 --- a/libcfs/include/libcfs/params_tree.h +++ b/libcfs/include/libcfs/params_tree.h @@ -78,8 +78,46 @@ typedef struct poll_table_struct cfs_poll_table_t; /* in lprocfs_stat.c, to protect the private data for proc entries */ extern struct rw_semaphore _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 { \ + down_read(&_lprocfs_lock); \ +} while(0) + +#define LPROCFS_EXIT() \ +do { \ + up_read(&_lprocfs_lock); \ +} while(0) + +#else +#define LPROCFS_ENTRY() do{ }while(0) +#define LPROCFS_EXIT() do{ }while(0) +#endif + +#ifdef HAVE_PROCFS_DELETED + +static inline +int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp) +{ + LPROCFS_ENTRY(); + if ((dp)->deleted) { + LPROCFS_EXIT(); + return -ENODEV; + } + return 0; +} +#elif defined(HAVE_PROCFS_USERS) /* !HAVE_PROCFS_DELETED*/ static inline -int LPROCFS_ENTRY_CHECK(struct proc_dir_entry *dp) +int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp) { int deleted = 0; @@ -91,6 +129,14 @@ int LPROCFS_ENTRY_CHECK(struct proc_dir_entry *dp) return -ENODEV; return 0; } +#else /* !HAVE_PROCFS_DELETED*/ +static inline +int LPROCFS_ENTRY_AND_CHECK(struct proc_dir_entry *dp) +{ + LPROCFS_ENTRY(); + return 0; +} +#endif /* HAVE_PROCFS_DELETED */ #define LPROCFS_SRCH_ENTRY() \ do { \ down_read(&_lprocfs_lock); \ @@ -201,9 +247,12 @@ do { \ rc = 0; \ } while(0) +#define LPROCFS_ENTRY() do {} while(0) +#define LPROCFS_EXIT() do {} while(0) static inline -int LPROCFS_ENTRY_CHECK(cfs_param_dentry_t *dp) +int LPROCFS_ENTRY_AND_CHECK(cfs_param_dentry_t *dp) { + LPROCFS_ENTRY(); return 0; } #define LPROCFS_WRITE_ENTRY() do {} while(0) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index cd6fd43..ec50de0 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -461,6 +461,36 @@ LB_LINUX_TRY_COMPILE([ ]) ]) +# 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 +],[ + 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]) +],[ + LB_LINUX_TRY_COMPILE([ + #include "$LINUX/fs/proc/internal.h" + ],[ + struct proc_dir_entry_aux pde_aux; + + pde_aux.pde_users = 0; + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_PROCFS_USERS, 1, + [kernel has pde_users member in proc_dir_entry_aux]) + ],[ + AC_MSG_RESULT([no]) + ]) +]) +]) + # 2.6.24 # 2.6.24 has bio_endio with 2 args @@ -479,6 +509,24 @@ LB_LINUX_TRY_COMPILE([ ]) ]) +# 2.6.24 removes long aged procfs entry -> deleted member +AC_DEFUN([LC_PROCFS_DELETED], +[AC_MSG_CHECKING([if kernel has deleted member in procfs entry struct]) +LB_LINUX_TRY_COMPILE([ + #include +],[ + struct proc_dir_entry pde; + + pde.deleted = sizeof(pde); +], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_PROCFS_DELETED, 1, + [kernel has deleted member in procfs entry struct]) +],[ + AC_MSG_RESULT([no]) +]) +]) + # 2.6.26 # 2.6.26 isn't export set_fs_pwd and change paramter in fs struct @@ -1516,9 +1564,11 @@ AC_DEFUN([LC_PROG_LINUX], # 2.6.23 LC_UNREGISTER_BLKDEV_RETURN_INT + LC_PROCFS_USERS # 2.6.24 LC_BIO_ENDIO_2ARG + LC_PROCFS_DELETED # 2.6.26 LC_FS_STRUCT_USE_PATH diff --git a/lustre/fld/lproc_fld.c b/lustre/fld/lproc_fld.c index c3734c7..97bd3d5 100644 --- a/lustre/fld/lproc_fld.c +++ b/lustre/fld/lproc_fld.c @@ -282,7 +282,7 @@ static int fldb_seq_open(struct inode *inode, struct file *file) int env_init = 0; int rc; - LPROCFS_ENTRY_CHECK(dp); + LPROCFS_ENTRY_AND_CHECK(dp); rc = seq_open(file, &fldb_sops); if (rc) GOTO(out, rc); @@ -319,6 +319,7 @@ out: lu_env_fini(¶m->fsp_env); if (param != NULL) OBD_FREE_PTR(param); + LPROCFS_EXIT(); } return rc; } diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 9142ac9..ff60773 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -750,8 +750,14 @@ extern int lprocfs_seq_release(cfs_inode_t *, struct file *); #define __LPROC_SEQ_FOPS(name, custom_seq_write) \ static int name##_single_open(cfs_inode_t *inode, struct file *file) { \ struct proc_dir_entry *dp = PDE(inode); \ - LPROCFS_ENTRY_CHECK(dp); \ - return single_open(file, name##_seq_show, dp->data); \ + int rc; \ + LPROCFS_ENTRY_AND_CHECK(dp); \ + rc = single_open(file, name##_seq_show, dp->data); \ + if (rc) { \ + LPROCFS_EXIT(); \ + return rc; \ + } \ + return 0; \ } \ struct file_operations name##_fops = { \ .owner = THIS_MODULE, \ diff --git a/lustre/lod/lproc_lod.c b/lustre/lod/lproc_lod.c index e976063..6fe74e3 100644 --- a/lustre/lod/lproc_lod.c +++ b/lustre/lod/lproc_lod.c @@ -418,10 +418,12 @@ static int lod_osts_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc; - LPROCFS_ENTRY_CHECK(dp); + LPROCFS_ENTRY_AND_CHECK(dp); rc = seq_open(file, &lod_osts_sops); - if (rc) + if (rc) { + LPROCFS_EXIT(); return rc; + } seq = file->private_data; seq->private = dp->data; diff --git a/lustre/lov/lproc_lov.c b/lustre/lov/lproc_lov.c index 850bb39..1c5839c 100644 --- a/lustre/lov/lproc_lov.c +++ b/lustre/lov/lproc_lov.c @@ -252,10 +252,12 @@ static int lov_target_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc; - LPROCFS_ENTRY_CHECK(dp); + LPROCFS_ENTRY_AND_CHECK(dp); rc = seq_open(file, &lov_tgt_sops); - if (rc) + if (rc) { + LPROCFS_EXIT(); return rc; + } seq = file->private_data; seq->private = dp->data; diff --git a/lustre/mdt/mdt_hsm_cdt_actions.c b/lustre/mdt/mdt_hsm_cdt_actions.c index ea2187a..37a4da1 100644 --- a/lustre/mdt/mdt_hsm_cdt_actions.c +++ b/lustre/mdt/mdt_hsm_cdt_actions.c @@ -541,12 +541,14 @@ static int lprocfs_open_agent_actions(struct inode *inode, struct file *file) struct mdt_device *mdt; ENTRY; - if (LPROCFS_ENTRY_CHECK(PDE(inode))) + if (LPROCFS_ENTRY_AND_CHECK(PDE(inode))) RETURN(-ENOENT); rc = seq_open(file, &mdt_agent_actions_proc_ops); - if (rc) + if (rc) { + LPROCFS_EXIT(); RETURN(rc); + } OBD_ALLOC_PTR(aai); if (aai == NULL) diff --git a/lustre/obdclass/lprocfs_jobstats.c b/lustre/obdclass/lprocfs_jobstats.c index f67e426..dab281b 100644 --- a/lustre/obdclass/lprocfs_jobstats.c +++ b/lustre/obdclass/lprocfs_jobstats.c @@ -420,12 +420,14 @@ static int lprocfs_jobstats_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc; - if (LPROCFS_ENTRY_CHECK(dp)) + if (LPROCFS_ENTRY_AND_CHECK(dp)) return -ENOENT; rc = seq_open(file, &lprocfs_jobstats_seq_sops); - if (rc) + if (rc) { + LPROCFS_EXIT(); return rc; + } seq = file->private_data; seq->private = dp->data; return 0; diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 6544034..8b52d52 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -62,12 +62,14 @@ EXPORT_SYMBOL(_lprocfs_lock); int lprocfs_single_release(struct inode *inode, struct file *file) { + LPROCFS_EXIT(); return single_release(inode, file); } EXPORT_SYMBOL(lprocfs_single_release); int lprocfs_seq_release(struct inode *inode, struct file *file) { + LPROCFS_EXIT(); return seq_release(inode, file); } EXPORT_SYMBOL(lprocfs_seq_release); @@ -203,7 +205,7 @@ static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, if (page == NULL) return -ENOMEM; - if (LPROCFS_ENTRY_CHECK(dp)) { + if (LPROCFS_ENTRY_AND_CHECK(dp)) { rc = -ENOENT; goto out; } @@ -212,6 +214,7 @@ static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, if (dp->read_proc) rc = dp->read_proc(page, &start, *ppos, PAGE_CACHE_SIZE, &eof, dp->data); + LPROCFS_EXIT(); if (rc <= 0) goto out; @@ -247,10 +250,11 @@ 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; - if (LPROCFS_ENTRY_CHECK(dp)) + if (LPROCFS_ENTRY_AND_CHECK(dp)) return -ENOENT; if (dp->write_proc) rc = dp->write_proc(f, buf, size, dp->data); + LPROCFS_EXIT(); return rc; } @@ -1468,12 +1472,14 @@ static int lprocfs_stats_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc; - if (LPROCFS_ENTRY_CHECK(dp)) + if (LPROCFS_ENTRY_AND_CHECK(dp)) return -ENOENT; rc = seq_open(file, &lprocfs_stats_seq_sops); - if (rc) + if (rc) { + LPROCFS_EXIT(); return rc; + } seq = file->private_data; seq->private = dp->data; return 0; diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index e2ba1ee..47ed364 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -992,10 +992,12 @@ ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file) struct seq_file *seqf; int rc; - LPROCFS_ENTRY_CHECK(dp); + LPROCFS_ENTRY_AND_CHECK(dp); rc = seq_open(file, &sops); - if (rc) + if (rc) { + LPROCFS_EXIT(); return rc; + } seqf = file->private_data; seqf->private = dp->data; @@ -1240,6 +1242,14 @@ int lprocfs_wr_evict_client(struct file *file, const char *buffer, goto out; } tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count)); + /* Kludge code(deadlock situation): the lprocfs lock has been held + * since the client is evicted by writting client's + * uuid/nid to procfs "evict_client" entry. However, + * obd_export_evict_by_uuid() will call lprocfs_remove() to destroy + * the proc entries under the being destroyed export{}, so I have + * to drop the lock at first here. + * - jay, jxiong@clusterfs.com */ + LPROCFS_EXIT(); class_incref(obd, __FUNCTION__, cfs_current()); if (strncmp(tmpbuf, "nid:", 4) == 0) @@ -1250,6 +1260,7 @@ int lprocfs_wr_evict_client(struct file *file, const char *buffer, obd_export_evict_by_uuid(obd, tmpbuf); class_decref(obd, __FUNCTION__, cfs_current()); + LPROCFS_ENTRY(); out: OBD_FREE(kbuf, BUFLEN); diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index 791f47d..38f3bb2 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -280,19 +280,21 @@ static int lprocfs_quota_seq_open(struct inode *inode, struct file *file) goto out_lqp; } - if (LPROCFS_ENTRY_CHECK(dp)) { + if (LPROCFS_ENTRY_AND_CHECK(dp)) { rc = -ENOENT; goto out_env; } rc = seq_open(file, &lprocfs_quota_seq_sops); if (rc) - goto out_env; + goto out_lprocfs; seq = file->private_data; seq->private = lqp; return 0; +out_lprocfs: + LPROCFS_EXIT(); out_env: lu_env_fini(&lqp->lqp_env); out_lqp: @@ -305,6 +307,8 @@ static int lprocfs_quota_seq_release(struct inode *inode, struct file *file) struct seq_file *seq = file->private_data; struct lquota_procfs *lqp = seq->private; + LPROCFS_EXIT(); + LASSERT(lqp); lu_env_fini(&lqp->lqp_env); OBD_FREE_PTR(lqp);