aboutsummaryrefslogtreecommitdiff
path: root/arch/alpha/kernel/osf_sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/osf_sys.c')
-rw-r--r--arch/alpha/kernel/osf_sys.c357
1 files changed, 273 insertions, 84 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 547e8b84b2f..1402fcc11c2 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -40,8 +40,8 @@
#include <asm/fpu.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <asm/sysinfo.h>
+#include <asm/thread_info.h>
#include <asm/hwrpb.h>
#include <asm/processor.h>
@@ -96,6 +96,7 @@ struct osf_dirent {
};
struct osf_dirent_callback {
+ struct dir_context ctx;
struct osf_dirent __user *dirent;
long __user *basep;
unsigned int count;
@@ -145,27 +146,24 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
long __user *, basep)
{
int error;
- struct file *file;
- struct osf_dirent_callback buf;
-
- error = -EBADF;
- file = fget(fd);
- if (!file)
- goto out;
+ struct fd arg = fdget(fd);
+ struct osf_dirent_callback buf = {
+ .ctx.actor = osf_filldir,
+ .dirent = dirent,
+ .basep = basep,
+ .count = count
+ };
- buf.dirent = dirent;
- buf.basep = basep;
- buf.count = count;
- buf.error = 0;
+ if (!arg.file)
+ return -EBADF;
- error = vfs_readdir(file, osf_filldir, &buf);
+ error = iterate_dir(arg.file, &buf.ctx);
if (error >= 0)
error = buf.error;
if (count != buf.count)
error = count - buf.count;
- fput(file);
- out:
+ fdput(arg);
return error;
}
@@ -191,6 +189,39 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len,
return ret;
}
+struct osf_stat {
+ int st_dev;
+ int st_pad1;
+ unsigned st_mode;
+ unsigned short st_nlink;
+ short st_nlink_reserved;
+ unsigned st_uid;
+ unsigned st_gid;
+ int st_rdev;
+ int st_ldev;
+ long st_size;
+ int st_pad2;
+ int st_uatime;
+ int st_pad3;
+ int st_umtime;
+ int st_pad4;
+ int st_uctime;
+ int st_pad5;
+ int st_pad6;
+ unsigned st_flags;
+ unsigned st_gen;
+ long st_spare[4];
+ unsigned st_ino;
+ int st_ino_reserved;
+ int st_atime;
+ int st_atime_reserved;
+ int st_mtime;
+ int st_mtime_reserved;
+ int st_ctime;
+ int st_ctime_reserved;
+ long st_blksize;
+ long st_blocks;
+};
/*
* The OSF/1 statfs structure is much larger, but this should
@@ -209,6 +240,60 @@ struct osf_statfs {
__kernel_fsid_t f_fsid;
};
+struct osf_statfs64 {
+ short f_type;
+ short f_flags;
+ int f_pad1;
+ int f_pad2;
+ int f_pad3;
+ int f_pad4;
+ int f_pad5;
+ int f_pad6;
+ int f_pad7;
+ __kernel_fsid_t f_fsid;
+ u_short f_namemax;
+ short f_reserved1;
+ int f_spare[8];
+ char f_pad8[90];
+ char f_pad9[90];
+ long mount_info[10];
+ u_long f_flags2;
+ long f_spare2[14];
+ long f_fsize;
+ long f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+};
+
+static int
+linux_to_osf_stat(struct kstat *lstat, struct osf_stat __user *osf_stat)
+{
+ struct osf_stat tmp = { 0 };
+
+ tmp.st_dev = lstat->dev;
+ tmp.st_mode = lstat->mode;
+ tmp.st_nlink = lstat->nlink;
+ tmp.st_uid = from_kuid_munged(current_user_ns(), lstat->uid);
+ tmp.st_gid = from_kgid_munged(current_user_ns(), lstat->gid);
+ tmp.st_rdev = lstat->rdev;
+ tmp.st_ldev = lstat->rdev;
+ tmp.st_size = lstat->size;
+ tmp.st_uatime = lstat->atime.tv_nsec / 1000;
+ tmp.st_umtime = lstat->mtime.tv_nsec / 1000;
+ tmp.st_uctime = lstat->ctime.tv_nsec / 1000;
+ tmp.st_ino = lstat->ino;
+ tmp.st_atime = lstat->atime.tv_sec;
+ tmp.st_mtime = lstat->mtime.tv_sec;
+ tmp.st_ctime = lstat->ctime.tv_sec;
+ tmp.st_blksize = lstat->blksize;
+ tmp.st_blocks = lstat->blocks;
+
+ return copy_to_user(osf_stat, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+}
+
static int
linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_stat,
unsigned long bufsiz)
@@ -231,43 +316,99 @@ linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_st
}
static int
-do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
- unsigned long bufsiz)
+linux_to_osf_statfs64(struct kstatfs *linux_stat, struct osf_statfs64 __user *osf_stat,
+ unsigned long bufsiz)
+{
+ struct osf_statfs64 tmp_stat = { 0 };
+
+ tmp_stat.f_type = linux_stat->f_type;
+ tmp_stat.f_fsize = linux_stat->f_frsize;
+ tmp_stat.f_bsize = linux_stat->f_bsize;
+ tmp_stat.f_blocks = linux_stat->f_blocks;
+ tmp_stat.f_bfree = linux_stat->f_bfree;
+ tmp_stat.f_bavail = linux_stat->f_bavail;
+ tmp_stat.f_files = linux_stat->f_files;
+ tmp_stat.f_ffree = linux_stat->f_ffree;
+ tmp_stat.f_fsid = linux_stat->f_fsid;
+ if (bufsiz > sizeof(tmp_stat))
+ bufsiz = sizeof(tmp_stat);
+ return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
+}
+
+SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
+ struct osf_statfs __user *, buffer, unsigned long, bufsiz)
{
struct kstatfs linux_stat;
- int error = vfs_statfs(path, &linux_stat);
+ int error = user_statfs(pathname, &linux_stat);
if (!error)
error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
return error;
}
-SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
- struct osf_statfs __user *, buffer, unsigned long, bufsiz)
+SYSCALL_DEFINE2(osf_stat, char __user *, name, struct osf_stat __user *, buf)
{
- struct path path;
- int retval;
+ struct kstat stat;
+ int error;
- retval = user_path(pathname, &path);
- if (!retval) {
- retval = do_osf_statfs(&path, buffer, bufsiz);
- path_put(&path);
- }
- return retval;
+ error = vfs_stat(name, &stat);
+ if (error)
+ return error;
+
+ return linux_to_osf_stat(&stat, buf);
+}
+
+SYSCALL_DEFINE2(osf_lstat, char __user *, name, struct osf_stat __user *, buf)
+{
+ struct kstat stat;
+ int error;
+
+ error = vfs_lstat(name, &stat);
+ if (error)
+ return error;
+
+ return linux_to_osf_stat(&stat, buf);
+}
+
+SYSCALL_DEFINE2(osf_fstat, int, fd, struct osf_stat __user *, buf)
+{
+ struct kstat stat;
+ int error;
+
+ error = vfs_fstat(fd, &stat);
+ if (error)
+ return error;
+
+ return linux_to_osf_stat(&stat, buf);
}
SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
struct osf_statfs __user *, buffer, unsigned long, bufsiz)
{
- struct file *file;
- int retval;
+ struct kstatfs linux_stat;
+ int error = fd_statfs(fd, &linux_stat);
+ if (!error)
+ error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
+ return error;
+}
- retval = -EBADF;
- file = fget(fd);
- if (file) {
- retval = do_osf_statfs(&file->f_path, buffer, bufsiz);
- fput(file);
- }
- return retval;
+SYSCALL_DEFINE3(osf_statfs64, char __user *, pathname,
+ struct osf_statfs64 __user *, buffer, unsigned long, bufsiz)
+{
+ struct kstatfs linux_stat;
+ int error = user_statfs(pathname, &linux_stat);
+ if (!error)
+ error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz);
+ return error;
+}
+
+SYSCALL_DEFINE3(osf_fstatfs64, unsigned long, fd,
+ struct osf_statfs64 __user *, buffer, unsigned long, bufsiz)
+{
+ struct kstatfs linux_stat;
+ int error = fd_statfs(fd, &linux_stat);
+ if (!error)
+ error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz);
+ return error;
}
/*
@@ -305,11 +446,11 @@ struct procfs_args {
* unhappy with OSF UFS. [CHECKME]
*/
static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
- char *devname;
+ struct filename *devname;
retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -318,18 +459,18 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
retval = PTR_ERR(devname);
if (IS_ERR(devname))
goto out;
- retval = do_mount(devname, dirname, "ext2", flags, NULL);
+ retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
putname(devname);
out:
return retval;
}
static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
- char *devname;
+ struct filename *devname;
retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -338,14 +479,14 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
retval = PTR_ERR(devname);
if (IS_ERR(devname))
goto out;
- retval = do_mount(devname, dirname, "iso9660", flags, NULL);
+ retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
putname(devname);
out:
return retval;
}
static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
{
struct procfs_args tmp;
@@ -359,7 +500,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
int, flag, void __user *, data)
{
int retval;
- char *name;
+ struct filename *name;
name = getname(path);
retval = PTR_ERR(name);
@@ -367,13 +508,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
goto out;
switch (typenr) {
case 1:
- retval = osf_ufs_mount(name, data, flag);
+ retval = osf_ufs_mount(name->name, data, flag);
break;
case 6:
- retval = osf_cdfs_mount(name, data, flag);
+ retval = osf_cdfs_mount(name->name, data, flag);
break;
case 9:
- retval = osf_procfs_mount(name, data, flag);
+ retval = osf_procfs_mount(name->name, data, flag);
break;
default:
retval = -EINVAL;
@@ -429,7 +570,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
return -EFAULT;
len = namelen;
- if (namelen > 32)
+ if (len > 32)
len = 32;
down_read(&uts_sem);
@@ -614,7 +755,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
down_read(&uts_sem);
res = sysinfo_table[offset];
len = strlen(res)+1;
- if (len > count)
+ if ((unsigned long)len > (unsigned long)count)
len = count;
if (copy_to_user(buf, res, len))
err = -EFAULT;
@@ -653,9 +794,9 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
case GSI_UACPROC:
if (nbytes < sizeof(unsigned int))
return -EINVAL;
- w = (current_thread_info()->flags >> UAC_SHIFT) & UAC_BITMASK;
- if (put_user(w, (unsigned int __user *)buffer))
- return -EFAULT;
+ w = current_thread_info()->status & UAC_BITMASK;
+ if (put_user(w, (unsigned int __user *)buffer))
+ return -EFAULT;
return 1;
case GSI_PROC_TYPE:
@@ -669,7 +810,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
return 1;
case GSI_GET_HWRPB:
- if (nbytes < sizeof(*hwrpb))
+ if (nbytes > sizeof(*hwrpb))
return -EINVAL;
if (copy_to_user(buffer, hwrpb, nbytes) != 0)
return -EFAULT;
@@ -763,24 +904,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
break;
case SSI_NVPAIRS: {
- unsigned long v, w, i;
- unsigned int old, new;
+ unsigned __user *p = buffer;
+ unsigned i;
- for (i = 0; i < nbytes; ++i) {
+ for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+ unsigned v, w, status;
- if (get_user(v, 2*i + (unsigned int __user *)buffer))
- return -EFAULT;
- if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+ if (get_user(v, p) || get_user(w, p + 1))
return -EFAULT;
switch (v) {
case SSIN_UACPROC:
- again:
- old = current_thread_info()->flags;
- new = old & ~(UAC_BITMASK << UAC_SHIFT);
- new = new | (w & UAC_BITMASK) << UAC_SHIFT;
- if (cmpxchg(&current_thread_info()->flags,
- old, new) != old)
- goto again;
+ w &= UAC_BITMASK;
+ status = current_thread_info()->status;
+ status = (status & ~UAC_BITMASK) | w;
+ current_thread_info()->status = status;
break;
default:
@@ -790,6 +927,9 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
return 0;
}
+ case SSI_LMF:
+ return 0;
+
default:
break;
}
@@ -951,9 +1091,6 @@ SYSCALL_DEFINE2(osf_utimes, const char __user *, filename,
return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
}
-#define MAX_SELECT_SECONDS \
- ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
SYSCALL_DEFINE5(osf_select, int, n, fd_set __user *, inp, fd_set __user *, outp,
fd_set __user *, exp, struct timeval32 __user *, tvp)
{
@@ -1003,6 +1140,7 @@ struct rusage32 {
SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
{
struct rusage32 r;
+ cputime_t utime, stime;
if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
return -EINVAL;
@@ -1010,8 +1148,9 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
memset(&r, 0, sizeof(r));
switch (who) {
case RUSAGE_SELF:
- jiffies_to_timeval32(current->utime, &r.ru_utime);
- jiffies_to_timeval32(current->stime, &r.ru_stime);
+ task_cputime(current, &utime, &stime);
+ jiffies_to_timeval32(utime, &r.ru_utime);
+ jiffies_to_timeval32(stime, &r.ru_stime);
r.ru_minflt = current->min_flt;
r.ru_majflt = current->maj_flt;
break;
@@ -1031,6 +1170,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
{
struct rusage r;
long ret, err;
+ unsigned int status = 0;
mm_segment_t old_fs;
if (!ur)
@@ -1039,13 +1179,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
old_fs = get_fs();
set_fs (KERNEL_DS);
- ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+ ret = sys_wait4(pid, (unsigned int __user *) &status, options,
+ (struct rusage __user *) &r);
set_fs (old_fs);
if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
return -EFAULT;
err = 0;
+ err |= put_user(status, ustatus);
err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
@@ -1159,17 +1301,15 @@ static unsigned long
arch_get_unmapped_area_1(unsigned long addr, unsigned long len,
unsigned long limit)
{
- struct vm_area_struct *vma = find_vma(current->mm, addr);
-
- while (1) {
- /* At this point: (!vma || addr < vma->vm_end). */
- if (limit - len < addr)
- return -ENOMEM;
- if (!vma || addr + len <= vma->vm_start)
- return addr;
- addr = vma->vm_end;
- vma = vma->vm_next;
- }
+ struct vm_unmapped_area_info info;
+
+ info.flags = 0;
+ info.length = len;
+ info.low_limit = addr;
+ info.high_limit = limit;
+ info.align_mask = 0;
+ info.align_offset = 0;
+ return vm_unmapped_area(&info);
}
unsigned long
@@ -1257,3 +1397,52 @@ SYSCALL_DEFINE3(osf_writev, unsigned long, fd,
}
#endif
+
+SYSCALL_DEFINE2(osf_getpriority, int, which, int, who)
+{
+ int prio = sys_getpriority(which, who);
+ if (prio >= 0) {
+ /* Return value is the unbiased priority, i.e. 20 - prio.
+ This does result in negative return values, so signal
+ no error */
+ force_successful_syscall_return();
+ prio = 20 - prio;
+ }
+ return prio;
+}
+
+SYSCALL_DEFINE0(getxuid)
+{
+ current_pt_regs()->r20 = sys_geteuid();
+ return sys_getuid();
+}
+
+SYSCALL_DEFINE0(getxgid)
+{
+ current_pt_regs()->r20 = sys_getegid();
+ return sys_getgid();
+}
+
+SYSCALL_DEFINE0(getxpid)
+{
+ current_pt_regs()->r20 = sys_getppid();
+ return sys_getpid();
+}
+
+SYSCALL_DEFINE0(alpha_pipe)
+{
+ int fd[2];
+ int res = do_pipe_flags(fd, 0);
+ if (!res) {
+ /* The return values are in $0 and $20. */
+ current_pt_regs()->r20 = fd[1];
+ res = fd[0];
+ }
+ return res;
+}
+
+SYSCALL_DEFINE1(sethae, unsigned long, val)
+{
+ current_pt_regs()->hae = val;
+ return 0;
+}