lkml.org 
[lkml]   [2009]   [Jul]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[RFC][PATCH] fcntl: F_[SG]ETOWN_TID
    From
    Date
    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:



    \
     
     \ /
      Last update: 2009-07-31 10:35    [W:0.032 / U:28.992 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site