From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: Oleg Nesterov <oleg@redhat.com>
Cc: eranian@gmail.com, Ingo Molnar <mingo@elte.hu>,
LKML <linux-kernel@vger.kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Robert Richter <robert.richter@amd.com>,
Paul Mackerras <paulus@samba.org>,
Andi Kleen <andi@firstfloor.org>,
Maynard Johnson <mpjohn@us.ibm.com>, Carl Love <cel@us.ibm.com>,
Corey J Ashford <cjashfor@us.ibm.com>,
Philip Mucci <mucci@eecs.utk.edu>,
Dan Terpstra <terpstra@eecs.utk.edu>,
perfmon2-devel <perfmon2-devel@lists.sourceforge.net>,
Michael Kerrisk <mtk.manpages@googlemail.com>,
roland <roland@redhat.com>
Subject: [RFC][PATCH] fcntl: F_[SG]ETOWN_TID
Date: Fri, 31 Jul 2009 10:35:20 +0200 [thread overview]
Message-ID: <1249029320.6391.72.camel@twins> (raw)
In-Reply-To: <20090730202804.GA13675@redhat.com>
In order to direct the SIGIO signal to a particular thread of a
multi-threaded application we cannot, like suggested by the manpage, put
a TID into the regular fcntl(F_SETOWN) call. It will still be send to
the whole process of which that thread is part.
Since people do want to properly direct SIGIO we introduce F_SETOWN_TID,
which functions similarly to F_SETOWN, except positive arguments are
interpreted as TIDs and negative arguments are interpreted as PIDs.
This extension is fully bug compatible with the old F_GETOWN
implementation in that F_GETOWN_TID will be troubled by the negative
return value for PIDs similarly to F_GETOWN's trouble with process
groups.
[ compile tested only so far ]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
arch/parisc/include/asm/fcntl.h | 2 +
fs/fcntl.c | 64 +++++++++++++++++++++++++++++++++-----
include/asm-generic/fcntl.h | 4 ++
include/linux/fs.h | 11 +++++-
net/socket.c | 2 +-
5 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/asm/fcntl.h
index 1e1c824..5d5235a 100644
--- a/arch/parisc/include/asm/fcntl.h
+++ b/arch/parisc/include/asm/fcntl.h
@@ -28,6 +28,8 @@
#define F_SETOWN 12 /* for sockets. */
#define F_SETSIG 13 /* for sockets. */
#define F_GETSIG 14 /* for sockets. */
+#define F_GETOWN_TID 15
+#define F_SETOWN_TID 16
/* for posix fcntl() and lockf() */
#define F_RDLCK 01
diff --git a/fs/fcntl.c b/fs/fcntl.c
index ae41308..8d0b7f9 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -197,13 +197,15 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
}
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
- int force)
+ int flags)
{
write_lock_irq(&filp->f_owner.lock);
- if (force || !filp->f_owner.pid) {
+ if ((flags & FF_SETOWN_FORCE) || !filp->f_owner.pid) {
put_pid(filp->f_owner.pid);
filp->f_owner.pid = get_pid(pid);
filp->f_owner.pid_type = type;
+ filp->f_owner.task_only =
+ (type == PIDTYPE_PID && (flags & FF_SETOWN_TID));
if (pid) {
const struct cred *cred = current_cred();
@@ -215,7 +217,7 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
}
int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
- int force)
+ int flags)
{
int err;
@@ -223,12 +225,12 @@ int __f_setown(struct file *filp, struct pid *pid, enum pid_type type,
if (err)
return err;
- f_modown(filp, pid, type, force);
+ f_modown(filp, pid, type, flags);
return 0;
}
EXPORT_SYMBOL(__f_setown);
-int f_setown(struct file *filp, unsigned long arg, int force)
+int f_setown(struct file *filp, unsigned long arg, int flags)
{
enum pid_type type;
struct pid *pid;
@@ -241,7 +243,7 @@ int f_setown(struct file *filp, unsigned long arg, int force)
}
rcu_read_lock();
pid = find_vpid(who);
- result = __f_setown(filp, pid, type, force);
+ result = __f_setown(filp, pid, type, flags);
rcu_read_unlock();
return result;
}
@@ -263,6 +265,40 @@ pid_t f_getown(struct file *filp)
return pid;
}
+static int f_setown_tid(struct file *filp, unsigned long arg)
+{
+ int flags = FF_SETOWN_FORCE;
+ struct pid *pid;
+ int who = arg;
+ int ret = 0;
+
+ if (who < 0)
+ who = -who;
+ else
+ flags |= FF_SETOWN_TID;
+
+ rcu_read_lock();
+ pid = find_vpid(who);
+ ret = __f_setown(filp, pid, PIDTYPE_PID, flags);
+ rcu_read_unlock();
+
+ return ret;
+}
+
+static pid_t f_getown_tid(struct file *filp)
+{
+ pid_t tid;
+
+ read_lock(&filp->f_owner.lock);
+ tid = pid_vnr(filp->f_owner.pid);
+ if (filp->f_owner.pid_type == PIDTYPE_PGID)
+ tid = 0;
+ if (!filp->f_owner.task_only)
+ tid = -tid;
+ read_unlock(&filp->f_owner.lock);
+ return tid;
+}
+
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
struct file *filp)
{
@@ -311,7 +347,14 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
force_successful_syscall_return();
break;
case F_SETOWN:
- err = f_setown(filp, arg, 1);
+ err = f_setown(filp, arg, FF_SETOWN_FORCE);
+ break;
+ case F_GETOWN_TID:
+ err = f_getown_tid(filp);
+ force_successful_syscall_return();
+ break;
+ case F_SETOWN_TID:
+ err = f_setown_tid(filp, arg);
break;
case F_GETSIG:
err = filp->f_owner.signum;
@@ -431,6 +474,7 @@ static void send_sigio_to_task(struct task_struct *p,
int fd,
int reason)
{
+ int (*send_sig)(int, struct siginfo *, struct task_struct *);
/*
* F_SETSIG can change ->signum lockless in parallel, make
* sure we read it once and use the same value throughout.
@@ -440,6 +484,8 @@ static void send_sigio_to_task(struct task_struct *p,
if (!sigio_perm(p, fown, signum))
return;
+ send_sig = fown->task_only ? send_sig_info : group_send_sig_info;
+
switch (signum) {
siginfo_t si;
default:
@@ -461,11 +507,11 @@ static void send_sigio_to_task(struct task_struct *p,
else
si.si_band = band_table[reason - POLL_IN];
si.si_fd = fd;
- if (!group_send_sig_info(signum, &si, p))
+ if (!send_sig(signum, &si, p))
break;
/* fall-through: fall back on the old plain SIGIO signal */
case 0:
- group_send_sig_info(SIGIO, SEND_SIG_PRIV, p);
+ send_sig(SIGIO, SEND_SIG_PRIV, p);
}
}
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 4d3e483..d7906b8 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -73,6 +73,10 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
#endif
+#ifndef F_SETOWN_TID
+#define F_SETOWN_TID 12
+#define F_GETOWN_TID 13
+#endif
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0872372..42697e7 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -872,6 +872,7 @@ struct fown_struct {
rwlock_t lock; /* protects pid, uid, euid fields */
struct pid *pid; /* pid or -pgrp where SIGIO should be sent */
enum pid_type pid_type; /* Kind of process group SIGIO should be sent to */
+ bool task_only; /* task or group signal */
uid_t uid, euid; /* uid/euid of process setting the owner */
int signum; /* posix.1b rt signal to be delivered on IO */
};
@@ -1291,8 +1292,14 @@ extern void kill_fasync(struct fasync_struct **, int, int);
/* only for net: no internal synchronization */
extern void __kill_fasync(struct fasync_struct *, int, int);
-extern int __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
-extern int f_setown(struct file *filp, unsigned long arg, int force);
+/*
+ * setown flags
+ */
+#define FF_SETOWN_FORCE 1
+#define FF_SETOWN_TID 2
+
+extern int __f_setown(struct file *filp, struct pid *, enum pid_type, int flags);
+extern int f_setown(struct file *filp, unsigned long arg, int flags);
extern void f_delown(struct file *filp);
extern pid_t f_getown(struct file *filp);
extern int send_sigurg(struct fown_struct *fown);
diff --git a/net/socket.c b/net/socket.c
index 791d71a..ac57f8e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -916,7 +916,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = -EFAULT;
if (get_user(pid, (int __user *)argp))
break;
- err = f_setown(sock->file, pid, 1);
+ err = f_setown(sock->file, pid, FF_SETOWN_FORCE);
break;
case FIOGETOWN:
case SIOCGPGRP:
next prev parent reply other threads:[~2009-07-31 8:32 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-27 16:51 perf_counters issue with self-sampling threads stephane eranian
2009-07-27 16:56 ` Peter Zijlstra
2009-07-27 21:25 ` Andi Kleen
[not found] ` <7c86c4470907272213w2ee57080re50dd22a4d73a7e0@mail.gmail.com>
2009-07-28 8:51 ` stephane eranian
2009-07-28 8:56 ` Andi Kleen
2009-07-28 9:13 ` stephane eranian
2009-08-04 16:09 ` stephane eranian
2009-07-29 12:19 ` Peter Zijlstra
2009-07-29 12:37 ` stephane eranian
2009-07-29 12:46 ` Peter Zijlstra
2009-07-29 22:17 ` Oleg Nesterov
2009-07-30 11:31 ` Peter Zijlstra
2009-07-30 19:20 ` Oleg Nesterov
2009-07-30 20:00 ` Peter Zijlstra
2009-07-30 20:28 ` Oleg Nesterov
2009-07-30 21:09 ` stephane eranian
2009-07-31 8:35 ` Peter Zijlstra [this message]
2009-07-31 14:01 ` [RFC][PATCH] fcntl: F_[SG]ETOWN_TID stephane eranian
2009-07-31 20:52 ` Oleg Nesterov
2009-07-31 21:11 ` Andrew Morton
2009-08-01 1:27 ` [PATCH 0/2] send_sigio/do_send_sig_info (Was: [RFC][PATCH] fcntl: F_[SG]ETOWN_TID) Oleg Nesterov
2009-08-03 15:48 ` [PATCH 3/2] fcntl: F_[SG]ETOWN_TID Peter Zijlstra
2009-08-03 17:16 ` Oleg Nesterov
2009-08-03 17:47 ` Peter Zijlstra
2009-08-03 18:06 ` Oleg Nesterov
2009-08-03 18:36 ` Peter Zijlstra
2009-08-03 19:02 ` Oleg Nesterov
2009-08-04 11:39 ` [PATCH 3/2 -v3] fcntl: F_[SG]ETOWN_EX Peter Zijlstra
2009-08-04 16:20 ` Oleg Nesterov
2009-08-04 16:52 ` Peter Zijlstra
2009-08-04 17:19 ` Oleg Nesterov
2009-08-06 13:14 ` [PATCH 3/2 -v4] " Peter Zijlstra
2009-08-06 19:05 ` Oleg Nesterov
2009-08-07 12:10 ` stephane eranian
2009-08-01 1:28 ` [PATCH 1/2] signals: introduce do_send_sig_info() helper Oleg Nesterov
2009-08-01 1:28 ` [PATCH 2/2] signals: send_sigio: use do_send_sig_info() to avoid check_kill_permission() Oleg Nesterov
2009-08-03 12:53 ` [RFC][PATCH] fcntl: F_[SG]ETOWN_TID stephane eranian
2009-08-09 5:46 ` F_SETOWN_TID: F_SETOWN was thread-specific for a while Jamie Lokier
2009-08-10 12:22 ` stephane eranian
2009-08-10 17:03 ` Oleg Nesterov
2009-08-10 21:01 ` stephane eranian
2009-08-17 17:16 ` Oleg Nesterov
2009-08-17 17:40 ` Oleg Nesterov
2009-08-17 22:26 ` stephane eranian
2009-08-18 11:45 ` Oleg Nesterov
2009-08-20 10:00 ` stephane eranian
2009-08-11 13:10 ` Jamie Lokier
2009-08-17 17:05 ` Oleg Nesterov
2009-08-03 15:21 ` [RFC][PATCH] fcntl: F_[SG]ETOWN_TID Peter Zijlstra
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=1249029320.6391.72.camel@twins \
--to=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=andi@firstfloor.org \
--cc=cel@us.ibm.com \
--cc=cjashfor@us.ibm.com \
--cc=eranian@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mpjohn@us.ibm.com \
--cc=mtk.manpages@googlemail.com \
--cc=mucci@eecs.utk.edu \
--cc=oleg@redhat.com \
--cc=paulus@samba.org \
--cc=perfmon2-devel@lists.sourceforge.net \
--cc=robert.richter@amd.com \
--cc=roland@redhat.com \
--cc=terpstra@eecs.utk.edu \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox