Commit e5307bf1 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_ppc64
parents 3dd5a454 22e962f9
VERSION = 2 VERSION = 2
PATCHLEVEL = 5 PATCHLEVEL = 5
SUBLEVEL = 8 SUBLEVEL = 8
EXTRAVERSION =-pre2 EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
...@@ -779,6 +779,8 @@ ENTRY(sys_call_table) ...@@ -779,6 +779,8 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_tkill) .long SYMBOL_NAME(sys_tkill)
.long SYMBOL_NAME(sys_sendfile64) .long SYMBOL_NAME(sys_sendfile64)
.long SYMBOL_NAME(sys_futex) /* 240 */ .long SYMBOL_NAME(sys_futex) /* 240 */
.long SYMBOL_NAME(sys_sched_setaffinity)
.long SYMBOL_NAME(sys_sched_getaffinity)
.rept NR_syscalls-(.-sys_call_table)/4 .rept NR_syscalls-(.-sys_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_ni_syscall)
......
...@@ -988,6 +988,80 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode) ...@@ -988,6 +988,80 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
return error; return error;
} }
int may_open(struct nameidata *nd, int acc_mode, int flag)
{
struct dentry *dentry = nd->dentry;
struct inode *inode = dentry->d_inode;
int error;
if (!inode)
return -ENOENT;
if (S_ISLNK(inode->i_mode))
return -ELOOP;
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR;
error = permission(inode, acc_mode);
if (error)
return error;
/*
* FIFO's, sockets and device files are special: they don't
* actually live on the filesystem itself, and as such you
* can write to them even if the filesystem is read-only.
*/
if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
flag &= ~O_TRUNC;
} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
if (nd->mnt->mnt_flags & MNT_NODEV)
return -EACCES;
flag &= ~O_TRUNC;
} else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
return -EROFS;
/*
* An append-only file must be opened in append mode for writing.
*/
if (IS_APPEND(inode)) {
if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
return -EPERM;
if (flag & O_TRUNC)
return -EPERM;
}
/*
* Ensure there are no outstanding leases on the file.
*/
error = get_lease(inode, flag);
if (error)
return error;
if (flag & O_TRUNC) {
error = get_write_access(inode);
if (error)
return error;
/*
* Refuse to truncate files with mandatory locks held on them.
*/
error = locks_verify_locked(inode);
if (!error) {
DQUOT_INIT(inode);
error = do_truncate(dentry, 0);
}
put_write_access(inode);
if (error)
return error;
} else
if (flag & FMODE_WRITE)
DQUOT_INIT(inode);
return 0;
}
/* /*
* open_namei() * open_namei()
* *
...@@ -1005,7 +1079,6 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode) ...@@ -1005,7 +1079,6 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
{ {
int acc_mode, error = 0; int acc_mode, error = 0;
struct inode *inode;
struct dentry *dentry; struct dentry *dentry;
struct dentry *dir; struct dentry *dir;
int count = 0; int count = 0;
...@@ -1092,80 +1165,9 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ...@@ -1092,80 +1165,9 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
goto exit; goto exit;
ok: ok:
error = -ENOENT; error = may_open(nd, acc_mode, flag);
inode = dentry->d_inode;
if (!inode)
goto exit;
error = -ELOOP;
if (S_ISLNK(inode->i_mode))
goto exit;
error = -EISDIR;
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
goto exit;
error = permission(inode,acc_mode);
if (error) if (error)
goto exit; goto exit;
/*
* FIFO's, sockets and device files are special: they don't
* actually live on the filesystem itself, and as such you
* can write to them even if the filesystem is read-only.
*/
if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
flag &= ~O_TRUNC;
} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
error = -EACCES;
if (nd->mnt->mnt_flags & MNT_NODEV)
goto exit;
flag &= ~O_TRUNC;
} else {
error = -EROFS;
if (IS_RDONLY(inode) && (flag & 2))
goto exit;
}
/*
* An append-only file must be opened in append mode for writing.
*/
error = -EPERM;
if (IS_APPEND(inode)) {
if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
goto exit;
if (flag & O_TRUNC)
goto exit;
}
/*
* Ensure there are no outstanding leases on the file.
*/
error = get_lease(inode, flag);
if (error)
goto exit;
if (flag & O_TRUNC) {
error = get_write_access(inode);
if (error)
goto exit;
/*
* Refuse to truncate files with mandatory locks held on them.
*/
error = locks_verify_locked(inode);
if (!error) {
DQUOT_INIT(inode);
error = do_truncate(dentry, 0);
}
put_write_access(inode);
if (error)
goto exit;
} else
if (flag & FMODE_WRITE)
DQUOT_INIT(inode);
return 0; return 0;
exit_dput: exit_dput:
......
...@@ -37,7 +37,16 @@ static struct file *do_open(char *name, int flags) ...@@ -37,7 +37,16 @@ static struct file *do_open(char *name, int flags)
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
return dentry_open(nd.dentry, nd.mnt, flags); if (flags == O_RDWR)
error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE);
else
error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
if (!error)
return dentry_open(nd.dentry, nd.mnt, flags);
path_release(&nd);
return ERR_PTR(error);
} }
static struct { static struct {
......
...@@ -245,6 +245,8 @@ ...@@ -245,6 +245,8 @@
#define __NR_tkill 238 #define __NR_tkill 238
#define __NR_sendfile64 239 #define __NR_sendfile64 239
#define __NR_futex 240 #define __NR_futex 240
#define __NR_sched_setaffinity 241
#define __NR_sched_getaffinity 242
/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */ /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
......
...@@ -1233,6 +1233,7 @@ static inline void allow_write_access(struct file *file) ...@@ -1233,6 +1233,7 @@ static inline void allow_write_access(struct file *file)
extern int do_pipe(int *); extern int do_pipe(int *);
extern int open_namei(const char *, int, int, struct nameidata *); extern int open_namei(const char *, int, int, struct nameidata *);
extern int may_open(struct nameidata *, int, int);
extern int kernel_read(struct file *, unsigned long, char *, unsigned long); extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
extern struct file * open_exec(const char *); extern struct file * open_exec(const char *);
......
...@@ -1234,6 +1234,96 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param) ...@@ -1234,6 +1234,96 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param)
return retval; return retval;
} }
/**
* sys_sched_setaffinity - set the cpu affinity of a process
* @pid: pid of the process
* @len: length of new_mask
* @new_mask: user-space pointer to the new cpu mask
*/
asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
unsigned long *new_mask_ptr)
{
unsigned long new_mask;
task_t *p;
int retval;
if (len < sizeof(new_mask))
return -EINVAL;
if (copy_from_user(&new_mask, new_mask_ptr, sizeof(new_mask)))
return -EFAULT;
new_mask &= cpu_online_map;
if (!new_mask)
return -EINVAL;
read_lock(&tasklist_lock);
p = find_process_by_pid(pid);
if (!p) {
read_unlock(&tasklist_lock);
return -ESRCH;
}
/*
* It is not safe to call set_cpus_allowed with the
* tasklist_lock held. We will bump the task_struct's
* usage count and then drop tasklist_lock.
*/
get_task_struct(p);
read_unlock(&tasklist_lock);
retval = -EPERM;
if ((current->euid != p->euid) && (current->euid != p->uid) &&
!capable(CAP_SYS_NICE))
goto out_unlock;
retval = 0;
set_cpus_allowed(p, new_mask);
out_unlock:
put_task_struct(p);
return retval;
}
/**
* sys_sched_getaffinity - get the cpu affinity of a process
* @pid: pid of the process
* @len: length of the new mask
* @user_mask_ptr: userspace pointer to the mask
*/
asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
unsigned long *user_mask_ptr)
{
unsigned long mask;
unsigned int real_len;
task_t *p;
int retval;
real_len = sizeof(mask);
if (len < real_len)
return -EINVAL;
read_lock(&tasklist_lock);
retval = -ESRCH;
p = find_process_by_pid(pid);
if (!p)
goto out_unlock;
retval = 0;
mask = p->cpus_allowed & cpu_online_map;
out_unlock:
read_unlock(&tasklist_lock);
if (retval)
return retval;
if (copy_to_user(user_mask_ptr, &mask, real_len))
return -EFAULT;
return real_len;
}
asmlinkage long sys_sched_yield(void) asmlinkage long sys_sched_yield(void)
{ {
runqueue_t *rq; runqueue_t *rq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment