diff options
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 74 |
1 files changed, 39 insertions, 35 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index 12273b6ea56d..4137d96534a6 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -116,7 +116,7 @@ int f_setown(struct file *filp, unsigned long arg, int force) struct pid *pid = NULL; int who = arg, ret = 0; - type = PIDTYPE_PID; + type = PIDTYPE_TGID; if (who < 0) { /* avoid overflow below */ if (who == INT_MIN) @@ -143,7 +143,7 @@ EXPORT_SYMBOL(f_setown); void f_delown(struct file *filp) { - f_modown(filp, NULL, PIDTYPE_PID, 1); + f_modown(filp, NULL, PIDTYPE_TGID, 1); } pid_t f_getown(struct file *filp) @@ -171,11 +171,11 @@ static int f_setown_ex(struct file *filp, unsigned long arg) switch (owner.type) { case F_OWNER_TID: - type = PIDTYPE_MAX; + type = PIDTYPE_PID; break; case F_OWNER_PID: - type = PIDTYPE_PID; + type = PIDTYPE_TGID; break; case F_OWNER_PGRP: @@ -206,11 +206,11 @@ static int f_getown_ex(struct file *filp, unsigned long arg) read_lock(&filp->f_owner.lock); owner.pid = pid_vnr(filp->f_owner.pid); switch (filp->f_owner.pid_type) { - case PIDTYPE_MAX: + case PIDTYPE_PID: owner.type = F_OWNER_TID; break; - case PIDTYPE_PID: + case PIDTYPE_TGID: owner.type = F_OWNER_PID; break; @@ -723,7 +723,7 @@ static inline int sigio_perm(struct task_struct *p, static void send_sigio_to_task(struct task_struct *p, struct fown_struct *fown, - int fd, int reason, int group) + int fd, int reason, enum pid_type type) { /* * F_SETSIG can change ->signum lockless in parallel, make @@ -767,11 +767,11 @@ static void send_sigio_to_task(struct task_struct *p, else si.si_band = mangle_poll(band_table[reason - POLL_IN]); si.si_fd = fd; - if (!do_send_sig_info(signum, &si, p, group)) + if (!do_send_sig_info(signum, &si, p, type)) break; /* fall-through: fall back on the old plain SIGIO signal */ case 0: - do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, group); + do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type); } } @@ -780,34 +780,36 @@ void send_sigio(struct fown_struct *fown, int fd, int band) struct task_struct *p; enum pid_type type; struct pid *pid; - int group = 1; read_lock(&fown->lock); type = fown->pid_type; - if (type == PIDTYPE_MAX) { - group = 0; - type = PIDTYPE_PID; - } - pid = fown->pid; if (!pid) goto out_unlock_fown; - - read_lock(&tasklist_lock); - do_each_pid_task(pid, type, p) { - send_sigio_to_task(p, fown, fd, band, group); - } while_each_pid_task(pid, type, p); - read_unlock(&tasklist_lock); + + if (type <= PIDTYPE_TGID) { + rcu_read_lock(); + p = pid_task(pid, PIDTYPE_PID); + if (p) + send_sigio_to_task(p, fown, fd, band, type); + rcu_read_unlock(); + } else { + read_lock(&tasklist_lock); + do_each_pid_task(pid, type, p) { + send_sigio_to_task(p, fown, fd, band, type); + } while_each_pid_task(pid, type, p); + read_unlock(&tasklist_lock); + } out_unlock_fown: read_unlock(&fown->lock); } static void send_sigurg_to_task(struct task_struct *p, - struct fown_struct *fown, int group) + struct fown_struct *fown, enum pid_type type) { if (sigio_perm(p, fown, SIGURG)) - do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, group); + do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type); } int send_sigurg(struct fown_struct *fown) @@ -815,28 +817,30 @@ int send_sigurg(struct fown_struct *fown) struct task_struct *p; enum pid_type type; struct pid *pid; - int group = 1; int ret = 0; read_lock(&fown->lock); type = fown->pid_type; - if (type == PIDTYPE_MAX) { - group = 0; - type = PIDTYPE_PID; - } - pid = fown->pid; if (!pid) goto out_unlock_fown; ret = 1; - - read_lock(&tasklist_lock); - do_each_pid_task(pid, type, p) { - send_sigurg_to_task(p, fown, group); - } while_each_pid_task(pid, type, p); - read_unlock(&tasklist_lock); + + if (type <= PIDTYPE_TGID) { + rcu_read_lock(); + p = pid_task(pid, PIDTYPE_PID); + if (p) + send_sigurg_to_task(p, fown, type); + rcu_read_unlock(); + } else { + read_lock(&tasklist_lock); + do_each_pid_task(pid, type, p) { + send_sigurg_to_task(p, fown, type); + } while_each_pid_task(pid, type, p); + read_unlock(&tasklist_lock); + } out_unlock_fown: read_unlock(&fown->lock); return ret; |