Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165688
b: refs/heads/master
c: ba0a6c9
h: refs/heads/master
v: v3
  • Loading branch information
Peter Zijlstra authored and Linus Torvalds committed Sep 24, 2009
1 parent 72d0aa9 commit 9a1f358
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 06f1631a1671bce2d59d58cb1debdf23e1803ebf
refs/heads/master: ba0a6c9f6fceed11c6a99e8326f0477fe383e6b5
2 changes: 2 additions & 0 deletions trunk/arch/alpha/include/asm/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#define F_GETOWN 6 /* for sockets. */
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
#define F_SETOWN_EX 12
#define F_GETOWN_EX 13

/* for posix fcntl() and lockf() */
#define F_RDLCK 1
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/parisc/include/asm/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_EX 15
#define F_SETOWN_EX 16

/* for posix fcntl() and lockf() */
#define F_RDLCK 01
Expand Down
108 changes: 100 additions & 8 deletions trunk/fs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,79 @@ pid_t f_getown(struct file *filp)
return pid;
}

static int f_setown_ex(struct file *filp, unsigned long arg)
{
struct f_owner_ex * __user owner_p = (void * __user)arg;
struct f_owner_ex owner;
struct pid *pid;
int type;
int ret;

ret = copy_from_user(&owner, owner_p, sizeof(owner));
if (ret)
return ret;

switch (owner.type) {
case F_OWNER_TID:
type = PIDTYPE_MAX;
break;

case F_OWNER_PID:
type = PIDTYPE_PID;
break;

case F_OWNER_GID:
type = PIDTYPE_PGID;
break;

default:
return -EINVAL;
}

rcu_read_lock();
pid = find_vpid(owner.pid);
if (owner.pid && !pid)
ret = -ESRCH;
else
ret = __f_setown(filp, pid, type, 1);
rcu_read_unlock();

return ret;
}

static int f_getown_ex(struct file *filp, unsigned long arg)
{
struct f_owner_ex * __user owner_p = (void * __user)arg;
struct f_owner_ex owner;
int ret = 0;

read_lock(&filp->f_owner.lock);
owner.pid = pid_vnr(filp->f_owner.pid);
switch (filp->f_owner.pid_type) {
case PIDTYPE_MAX:
owner.type = F_OWNER_TID;
break;

case PIDTYPE_PID:
owner.type = F_OWNER_PID;
break;

case PIDTYPE_PGID:
owner.type = F_OWNER_GID;
break;

default:
WARN_ON(1);
ret = -EINVAL;
break;
}
read_unlock(&filp->f_owner.lock);

if (!ret)
ret = copy_to_user(owner_p, &owner, sizeof(owner));
return ret;
}

static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
struct file *filp)
{
Expand Down Expand Up @@ -313,6 +386,12 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
case F_SETOWN:
err = f_setown(filp, arg, 1);
break;
case F_GETOWN_EX:
err = f_getown_ex(filp, arg);
break;
case F_SETOWN_EX:
err = f_setown_ex(filp, arg);
break;
case F_GETSIG:
err = filp->f_owner.signum;
break;
Expand Down Expand Up @@ -428,8 +507,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 fd, int reason, int group)
{
/*
* F_SETSIG can change ->signum lockless in parallel, make
Expand Down Expand Up @@ -461,11 +539,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 (!do_send_sig_info(signum, &si, p, true))
if (!do_send_sig_info(signum, &si, p, group))
break;
/* fall-through: fall back on the old plain SIGIO signal */
case 0:
do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, true);
do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, group);
}
}

Expand All @@ -474,38 +552,52 @@ 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);
send_sigio_to_task(p, fown, fd, band, group);
} 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)
struct fown_struct *fown, int group)
{
if (sigio_perm(p, fown, SIGURG))
group_send_sig_info(SIGURG, SEND_SIG_PRIV, p);
do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, group);
}

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;
Expand All @@ -514,7 +606,7 @@ int send_sigurg(struct fown_struct *fown)

read_lock(&tasklist_lock);
do_each_pid_task(pid, type, p) {
send_sigurg_to_task(p, fown);
send_sigurg_to_task(p, fown, group);
} while_each_pid_task(pid, type, p);
read_unlock(&tasklist_lock);
out_unlock_fown:
Expand Down
13 changes: 13 additions & 0 deletions trunk/include/asm-generic/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
#endif
#ifndef F_SETOWN_EX
#define F_SETOWN_EX 12
#define F_GETOWN_EX 13
#endif

#define F_OWNER_TID 0
#define F_OWNER_PID 1
#define F_OWNER_GID 2

struct f_owner_ex {
int type;
pid_t pid;
};

/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
Expand Down

0 comments on commit 9a1f358

Please sign in to comment.