diff options
author | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | 2009-10-19 13:44:21 +0530 |
---|---|---|
committer | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | 2009-10-19 13:44:21 +0530 |
commit | 720bbfc68d9e7dfd8c37587c6a61da75d6aab4fa (patch) | |
tree | a3114dc7319d78202b40f3458bac4516aedbe4cf /runtime/uprobes | |
parent | 3c2341daf979fc38fc534ae91e00594a525962e0 (diff) | |
download | systemtap-steved-720bbfc68d9e7dfd8c37587c6a61da75d6aab4fa.tar.gz systemtap-steved-720bbfc68d9e7dfd8c37587c6a61da75d6aab4fa.tar.xz systemtap-steved-720bbfc68d9e7dfd8c37587c6a61da75d6aab4fa.zip |
Avoid lockdep warnings.
uprobe_fork_uproc() runs with parent_uproc->rwsem locked.
However uprobe_mk_process() that gets called within uprobe_fork_uproc()
also locks child_uproc->rwsem after initializing it.
Lockdep report confuses this to acquiring a lock that already has been
acquired and suggests using sub-classes.
The alternatives we have are:
1. use classes level to distinguish different uproc structures.
2. unlock parent_uproc->rwsem before we call uprobe_fork_uproc().
3. dont try locking child_uproc->rwsem; since we are protected by
uproc_mutex as well as parent_uproc->rwsem;
We use the last approach.
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
---
Diffstat (limited to 'runtime/uprobes')
-rw-r--r-- | runtime/uprobes/uprobes.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index 27e923b8..60c84509 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -652,8 +652,18 @@ dont_add: return NULL; } -/* Runs with uproc_mutex held; returns with uproc->rwsem write-locked. */ -static struct uprobe_process *uprobe_mk_process(struct task_struct *p) +/* + * Create a per process uproc struct. + * at_fork: indicates uprobe_mk_process is called from + * a fork context of a probe process. refer uprobe_fork_uproc + * for more details. + * + * Runs with uproc_mutex held; + * Returns with uproc->rwsem write-locked when not called + * from fork context. + */ +static struct uprobe_process *uprobe_mk_process(struct task_struct *p, + bool at_fork) { struct uprobe_process *uproc; struct uprobe_task *utask; @@ -668,7 +678,9 @@ static struct uprobe_process *uprobe_mk_process(struct task_struct *p) /* Initialize fields */ atomic_set(&uproc->refcount, 1); init_rwsem(&uproc->rwsem); - down_write(&uproc->rwsem); + if (!at_fork) + /* not called from fork context. */ + down_write(&uproc->rwsem); init_waitqueue_head(&uproc->waitq); for (i = 0; i < UPROBE_TABLE_SIZE; i++) INIT_HLIST_HEAD(&uproc->uprobe_table[i]); @@ -923,7 +935,7 @@ int register_uprobe(struct uprobe *u) unlock_uproc_table(); goto fail_tsk; } - uproc = uprobe_mk_process(p); + uproc = uprobe_mk_process(p, 0); if (IS_ERR(uproc)) { ret = (int) PTR_ERR(uproc); unlock_uproc_table(); @@ -2206,13 +2218,12 @@ static int uprobe_fork_uproc(struct uprobe_process *parent_uproc, if (!try_module_get(THIS_MODULE)) return -ENOSYS; - child_uproc = uprobe_mk_process(child_tsk); + child_uproc = uprobe_mk_process(child_tsk, 1); if (IS_ERR(child_uproc)) { ret = (int) PTR_ERR(child_uproc); module_put(THIS_MODULE); return ret; } - /* child_uproc is write-locked and ref-counted at this point. */ mutex_lock(&child_uproc->ssol_area.setup_mutex); uprobe_init_ssol(child_uproc, child_tsk, @@ -2228,7 +2239,6 @@ static int uprobe_fork_uproc(struct uprobe_process *parent_uproc, &uproc_table[hash_long(child_uproc->tgid, UPROBE_HASH_BITS)]); - up_write(&child_uproc->rwsem); uprobe_decref_process(child_uproc); return ret; } |