From: Boaz Harrosh <bharrosh@panasas.com>
To: Andrew Morton <akpm@linux-foundation.org>,
"Rafael J. Wysocki" <rjw@sisk.pl>, <keyrings@linux-nfs.org>,
<linux-security-module@vger.kernel.org>
Cc: linux-fsdevel <linux-fsdevel@vger.kernel.org>,
linux-kernel <linux-kernel@vger.kernel.org>,
NFS list <linux-nfs@vger.kernel.org>,
Trond Myklebust <Trond.Myklebust@netapp.com>,
"Bhamare, Sachin" <sbhamare@panasas.com>,
David Howells <dhowells@redhat.com>,
Eric Paris <eparis@redhat.com>,
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
Kay Sievers <kay.sievers@vrfy.org>,
James Morris <jmorris@namei.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
Greg Kroah-Hartman <gregkh@suse.de>
Subject: [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout() API
Date: Tue, 20 Mar 2012 16:32:19 -0700 [thread overview]
Message-ID: <4F691383.5040506@panasas.com> (raw)
In-Reply-To: <4F691059.30405@panasas.com>
In the blasphemous occasions that a the Kernel must call a user-mode program
half of the times it is more robust to not wait forever but limit the wait
for a specified timeout.
So add a new call_usermodehelper_timeout() that implements that.
(Users of this new API will be added once this API is in mainline)
call_usermodehelper_fns() is added an extra timeout parameter which
is then implemented in call_usermodehelper_exec. The few users of
call_usermodehelper_fns() are also changed in this patch.
Since now the executing threads might come back after the waiting
thread has returned, do to a timeout. I used a simple kref pattern
to govern the life time of the subprocess_info struct.
Should some wait-forever callers today, be converted to this new
schema?
CC: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
fs/exec.c | 2 +-
include/linux/kmod.h | 15 +++++++++++++--
kernel/kmod.c | 29 +++++++++++++++++++++--------
kernel/sys.c | 2 +-
security/keys/request_key.c | 2 +-
5 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index 92ce83a..e696081 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2197,7 +2197,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
}
retval = call_usermodehelper_fns(helper_argv[0], helper_argv,
- NULL, UMH_WAIT_EXEC, umh_pipe_setup,
+ NULL, UMH_WAIT_EXEC, 0, umh_pipe_setup,
NULL, &cprm);
argv_free(helper_argv);
if (retval) {
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 5a89c00..eccc3f5 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -25,6 +25,7 @@
#include <linux/compiler.h>
#include <linux/workqueue.h>
#include <linux/sysctl.h>
+#include <linux/kref.h>
#define KMOD_PATH_LEN 256
@@ -55,12 +56,14 @@ enum umh_wait {
};
struct subprocess_info {
+ struct kref kref;
struct work_struct work;
struct completion *complete;
char *path;
char **argv;
char **envp;
enum umh_wait wait;
+ unsigned long wait_timeout;
int retval;
int (*init)(struct subprocess_info *info, struct cred *new);
void (*cleanup)(struct subprocess_info *info);
@@ -69,14 +72,22 @@ struct subprocess_info {
extern int
call_usermodehelper_fns(char *path, char **argv, char **envp,
- enum umh_wait wait,
+ enum umh_wait wait, unsigned long timeout,
int (*init)(struct subprocess_info *info, struct cred *new),
void (*cleanup)(struct subprocess_info *), void *data);
static inline int
call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
{
- return call_usermodehelper_fns(path, argv, envp, wait,
+ return call_usermodehelper_fns(path, argv, envp, wait, 0,
+ NULL, NULL, NULL);
+}
+
+static inline int
+call_usermodehelper_timeout(char *path, char **argv, char **envp,
+ enum umh_wait wait, unsigned long timeout)
+{
+ return call_usermodehelper_fns(path, argv, envp, wait, timeout,
NULL, NULL, NULL);
}
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 3cb7457..a72eefa 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -129,7 +129,7 @@ int __request_module(bool wait, const char *fmt, ...)
trace_module_request(module_name, wait, _RET_IP_);
ret = call_usermodehelper_fns(modprobe_path, argv, envp,
- wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC,
+ wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC, 0,
NULL, NULL, NULL);
atomic_dec(&kmod_concurrent);
@@ -191,8 +191,11 @@ fail:
do_exit(0);
}
-static void call_usermodehelper_freeinfo(struct subprocess_info *info)
+static void call_usermodehelper_freeinfo(struct kref *kref)
{
+ struct subprocess_info *info =
+ container_of(kref, struct subprocess_info, kref);
+
if (info->cleanup)
(*info->cleanup)(info);
kfree(info);
@@ -235,6 +238,7 @@ static int wait_for_helper(void *data)
}
complete(sub_info->complete);
+ kref_put(&sub_info->kref, call_usermodehelper_freeinfo);
return 0;
}
@@ -258,7 +262,8 @@ static void __call_usermodehelper(struct work_struct *work)
switch (wait) {
case UMH_NO_WAIT:
- call_usermodehelper_freeinfo(sub_info);
+ kref_put(&sub_info->kref, call_usermodehelper_freeinfo);
+ kref_put(&sub_info->kref, call_usermodehelper_freeinfo);
break;
case UMH_WAIT_PROC:
@@ -269,6 +274,7 @@ static void __call_usermodehelper(struct work_struct *work)
if (pid < 0)
sub_info->retval = pid;
complete(sub_info->complete);
+ kref_put(&sub_info->kref, call_usermodehelper_freeinfo);
}
}
@@ -387,6 +393,7 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
if (!sub_info)
goto out;
+ kref_init(&sub_info->kref);
INIT_WORK(&sub_info->work, __call_usermodehelper);
sub_info->path = path;
sub_info->argv = argv;
@@ -452,22 +459,27 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
sub_info->complete = &done;
sub_info->wait = wait;
+ if (!sub_info->wait_timeout)
+ sub_info->wait_timeout = MAX_SCHEDULE_TIMEOUT;
+ /* Balanced in __call_usermodehelper or wait_for_helper */
+ kref_get(&sub_info->kref);
queue_work(khelper_wq, &sub_info->work);
if (wait == UMH_NO_WAIT) /* task has freed sub_info */
goto unlock;
- wait_for_completion(&done);
- retval = sub_info->retval;
-
+ if (likely(wait_for_completion_timeout(&done, sub_info->wait_timeout)))
+ retval = sub_info->retval;
+ else
+ retval = -ETIMEDOUT;
out:
- call_usermodehelper_freeinfo(sub_info);
+ kref_put(&sub_info->kref, call_usermodehelper_freeinfo);
unlock:
helper_unlock();
return retval;
}
int call_usermodehelper_fns(char *path, char **argv, char **envp,
- enum umh_wait wait,
+ enum umh_wait wait, unsigned long timeout,
int (*init)(struct subprocess_info *info, struct cred *new),
void (*cleanup)(struct subprocess_info *), void *data)
{
@@ -480,6 +492,7 @@ int call_usermodehelper_fns(char *path, char **argv, char **envp,
return -ENOMEM;
call_usermodehelper_setfns(info, init, cleanup, data);
+ info->wait_timeout = timeout;
return call_usermodehelper_exec(info, wait);
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 9947fb0..a9079d1 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2013,7 +2013,7 @@ int orderly_poweroff(bool force)
goto out;
}
- ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT,
+ ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, 0,
NULL, argv_cleanup, NULL);
out:
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index b8cc38c..28050ea 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -93,7 +93,7 @@ static void umh_keys_cleanup(struct subprocess_info *info)
static int call_usermodehelper_keys(char *path, char **argv, char **envp,
struct key *session_keyring, enum umh_wait wait)
{
- return call_usermodehelper_fns(path, argv, envp, wait,
+ return call_usermodehelper_fns(path, argv, envp, wait, 0,
umh_keys_init, umh_keys_cleanup,
key_get(session_keyring));
}
--
1.7.6.2
next prev parent reply other threads:[~2012-03-20 23:32 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-20 23:18 [PATCHSET 0/4] kmod: Optional timeout on the wait in call_usermodehelper_exec Boaz Harrosh
2012-03-20 23:18 ` Boaz Harrosh
2012-03-20 23:23 ` [PATCH 1/4] kmod: Un-export call_usermodehelper_freeinfo() Boaz Harrosh
2012-03-20 23:23 ` Boaz Harrosh
2012-03-20 23:26 ` [PATCH 2/4] kmod: Convert two call sites to call_usermodehelper_fns() Boaz Harrosh
2012-03-20 23:26 ` Boaz Harrosh
2012-03-22 3:00 ` James Morris
2012-03-22 3:00 ` James Morris
2012-03-20 23:28 ` [PATCH 3/4] kmod: Move call_usermodehelper_fns() to .c file and unexport it's helpers Boaz Harrosh
2012-03-20 23:32 ` Boaz Harrosh [this message]
2012-03-22 2:44 ` [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout() API Boaz Harrosh
2012-03-22 2:48 ` Boaz Harrosh
2012-03-22 2:52 ` Boaz Harrosh
[not found] ` <201203241028.IGJ09825.MtOVFHFJQSLOFO@I-love.SAKURA.ne.jp>
[not found] ` <4F6D35F0.2020808@panasas.com>
[not found] ` <20120323200028.fadf49f8.akpm@linux-foundation.org>
[not found] ` <20120324145308.GA10023@redhat.com>
[not found] ` <201205191121.BIF57837.FHFOtMOLJQSOFV@I-love.SAKURA.ne.jp>
[not found] ` <4FB7170F.7070807@panasas.com>
2012-05-21 17:01 ` call_usermodehelper && check_hung_uninterruptible_tasks Oleg Nesterov
2012-05-21 18:24 ` Oleg Nesterov
[not found] ` <87fwau4aag.fsf@rustcorp.com.au>
2012-05-21 17:34 ` UMH_WAIT_EXEC->UMH_WAIT_PROC deadlock Oleg Nesterov
2012-05-21 18:12 ` Oleg Nesterov
2012-03-22 11:48 ` [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout()API Tetsuo Handa
2012-03-22 14:27 ` [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout() API Oleg Nesterov
2012-03-22 14:27 ` Oleg Nesterov
2012-03-22 14:42 ` Oleg Nesterov
2012-03-22 14:42 ` Oleg Nesterov
2012-03-22 19:08 ` Boaz Harrosh
2012-03-22 22:16 ` [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout()API Tetsuo Handa
2012-03-23 4:48 ` Boaz Harrosh
2012-03-23 5:23 ` Tetsuo Handa
2012-03-23 5:23 ` Tetsuo Handa
2012-03-23 16:30 ` Oleg Nesterov
2012-03-23 13:34 ` [RFC 4/4] {RFC} kmod.c: Add new call_usermodehelper_timeout() API Oleg Nesterov
2012-03-23 13:34 ` Oleg Nesterov
2012-03-21 15:35 ` [PATCHSET 0/4] kmod: Optional timeout on the wait in call_usermodehelper_exec Greg KH
2012-03-22 0:18 ` Boaz Harrosh
2012-03-22 0:31 ` Myklebust, Trond
2012-03-22 0:31 ` Myklebust, Trond
2012-03-22 0:31 ` Myklebust, Trond
2012-03-22 1:18 ` Boaz Harrosh
2012-03-27 1:57 ` [PATCHSET 0/6 version 2] " Boaz Harrosh
2012-03-27 2:00 ` [PATCH 1/6] kmod: Unexport call_usermodehelper_freeinfo() Boaz Harrosh
2012-03-27 2:00 ` Boaz Harrosh
2012-03-27 2:02 ` [PATCH 2/6] kmod: Convert two call sites to call_usermodehelper_fns() Boaz Harrosh
2012-03-27 2:04 ` [PATCH 3/6] kmod: Move call_usermodehelper_fns() to .c file and unexport all it's helpers Boaz Harrosh
2012-03-27 2:06 ` [PATCH 4/6 OPTION-A] completion: Add new wait_for_completion_timeout_state Boaz Harrosh
2012-03-27 2:06 ` Boaz Harrosh
2012-03-27 2:33 ` [PATCH 4/6 OPTION-A version 3] " Boaz Harrosh
2012-03-27 8:11 ` Peter Zijlstra
2012-03-27 8:11 ` Peter Zijlstra
2012-03-28 18:19 ` Boaz Harrosh
2012-03-28 18:19 ` Boaz Harrosh
2012-03-28 18:25 ` Peter Zijlstra
2012-03-28 18:25 ` Peter Zijlstra
2012-03-28 17:38 ` Oleg Nesterov
2012-03-27 2:09 ` [PATCH 4/6 option-B] kmod: add new wait_for_completion_timeout_state() helper Boaz Harrosh
2012-03-27 2:13 ` [PATCH 5/6] kmod: Add new call_usermodehelper_timeout() API Boaz Harrosh
2012-03-27 15:43 ` Oleg Nesterov
2012-03-27 15:43 ` Oleg Nesterov
2012-03-28 17:04 ` Oleg Nesterov
2012-03-27 2:15 ` [PATCH 6/6] kmod: optional: Convert the use of xchg to a kref Boaz Harrosh
2012-03-28 16:35 ` Oleg Nesterov
2012-03-27 21:07 ` [PATCHSET 0/6 version 2] kmod: Optional timeout on the wait in call_usermodehelper_exec Andrew Morton
2012-03-27 21:07 ` Andrew Morton
2012-03-28 20:19 ` Oleg Nesterov
2012-03-28 21:42 ` Boaz Harrosh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F691383.5040506@panasas.com \
--to=bharrosh@panasas.com \
--cc=Trond.Myklebust@netapp.com \
--cc=akpm@linux-foundation.org \
--cc=dhowells@redhat.com \
--cc=ebiederm@xmission.com \
--cc=eparis@redhat.com \
--cc=gregkh@suse.de \
--cc=jmorris@namei.org \
--cc=kay.sievers@vrfy.org \
--cc=keyrings@linux-nfs.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=sbhamare@panasas.com \
--cc=srivatsa.bhat@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.