Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / alpha / kernel / osf_sys.c
index 4761ed9..a693bd2 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/namei.h>
 #include <linux/uio.h>
 #include <linux/vfs.h>
+#include <linux/rcupdate.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/fpu.h>
 #include <asm/io.h>
@@ -91,8 +93,8 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
  * braindamage (it can't really handle filesystems where the directory
  * offset differences aren't the same as "d_reclen").
  */
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+3) & ~3)
+#define NAME_OFFSET    offsetof (struct osf_dirent, d_name)
+#define ROUND_UP(x)    (((x)+3) & ~3)
 
 struct osf_dirent {
        unsigned int d_ino;
@@ -114,7 +116,7 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
 {
        struct osf_dirent __user *dirent;
        struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
-       unsigned int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+       unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
 
        buf->error = -EINVAL;   /* only used if we fail */
        if (reclen > buf->count)
@@ -398,18 +400,20 @@ asmlinkage int
 osf_utsname(char __user *name)
 {
        int error;
+       struct new_utsname *ptr;
 
        down_read(&uts_sem);
+       ptr = vx_new_utsname();
        error = -EFAULT;
-       if (copy_to_user(name + 0, system_utsname.sysname, 32))
+       if (copy_to_user(name + 0, ptr->sysname, 32))
                goto out;
-       if (copy_to_user(name + 32, system_utsname.nodename, 32))
+       if (copy_to_user(name + 32, ptr->nodename, 32))
                goto out;
-       if (copy_to_user(name + 64, system_utsname.release, 32))
+       if (copy_to_user(name + 64, ptr->release, 32))
                goto out;
-       if (copy_to_user(name + 96, system_utsname.version, 32))
+       if (copy_to_user(name + 96, ptr->version, 32))
                goto out;
-       if (copy_to_user(name + 128, system_utsname.machine, 32))
+       if (copy_to_user(name + 128, ptr->machine, 32))
                goto out;
 
        error = 0;
@@ -437,43 +441,28 @@ asmlinkage int
 osf_getdomainname(char __user *name, int namelen)
 {
        unsigned len;
-       int i, error;
+       int i;
+       char *domainname;
 
-       error = verify_area(VERIFY_WRITE, name, namelen);
-       if (error)
-               goto out;
+       if (!access_ok(VERIFY_WRITE, name, namelen))
+               return -EFAULT;
 
        len = namelen;
        if (namelen > 32)
                len = 32;
 
        down_read(&uts_sem);
+       domainname = vx_new_uts(domainname);
        for (i = 0; i < len; ++i) {
-               __put_user(system_utsname.domainname[i], name + i);
-               if (system_utsname.domainname[i] == '\0')
+               __put_user(domainname[i], name + i);
+               if (domainname[i] == '\0')
                        break;
        }
        up_read(&uts_sem);
- out:
-       return error;
-}
-
-asmlinkage long
-osf_shmat(int shmid, void __user *shmaddr, int shmflg)
-{
-       unsigned long raddr;
-       long err;
-
-       err = do_shmat(shmid, shmaddr, shmflg, &raddr);
 
-       /*
-        * This works because all user-level addresses are
-        * non-negative longs!
-        */
-       return err ? err : (long)raddr;
+       return 0;
 }
 
-
 /*
  * The following stuff should move into a header file should it ever
  * be labeled "officially supported."  Right now, there is just enough
@@ -623,30 +612,30 @@ osf_sigstack(struct sigstack __user *uss, struct sigstack __user *uoss)
 asmlinkage long
 osf_sysinfo(int command, char __user *buf, long count)
 {
-       static char * sysinfo_table[] = {
-               system_utsname.sysname,
-               system_utsname.nodename,
-               system_utsname.release,
-               system_utsname.version,
-               system_utsname.machine,
-               "alpha",        /* instruction set architecture */
-               "dummy",        /* hardware serial number */
-               "dummy",        /* hardware manufacturer */
-               "dummy",        /* secure RPC domain */
-       };
        unsigned long offset;
        char *res;
        long len, err = -EINVAL;
 
        offset = command-1;
-       if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
+       if (offset >= 9) {
                /* Digital UNIX has a few unpublished interfaces here */
                printk("sysinfo(%d)", command);
                goto out;
        }
        
        down_read(&uts_sem);
-       res = sysinfo_table[offset];
+       switch (offset)
+       {
+       case 0: res = vx_new_uts(sysname);  break;
+       case 1: res = vx_new_uts(nodename); break;
+       case 2: res = vx_new_uts(release);  break;
+       case 3: res = vx_new_uts(version);  break;
+       case 4: res = vx_new_uts(machine);  break;
+       case 5: res = "alpha";              break;
+       default:
+               res = "dummy";
+               break;
+       }
        len = strlen(res)+1;
        if (len > count)
                len = count;
@@ -723,7 +712,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
 {
        switch (op) {
        case SSI_IEEE_FP_CONTROL: {
-               unsigned long swcr, fpcr, fex;
+               unsigned long swcr, fpcr;
+               unsigned int *state;
 
                /* 
                 * Alpha Architecture Handbook 4.7.7.3:
@@ -732,22 +722,42 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
                 * set in the trap shadow of a software-complete insn.
                 */
 
-               /* Update softare trap enable bits.  */
                if (get_user(swcr, (unsigned long __user *)buffer))
                        return -EFAULT;
-               current_thread_info()->ieee_state
-                 = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
-                    | (swcr & IEEE_SW_MASK));
+               state = &current_thread_info()->ieee_state;
+
+               /* Update softare trap enable bits.  */
+               *state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
+
+               /* Update the real fpcr.  */
+               fpcr = rdfpcr() & FPCR_DYN_MASK;
+               fpcr |= ieee_swcr_to_fpcr(swcr);
+               wrfpcr(fpcr);
+
+               return 0;
+       }
+
+       case SSI_IEEE_RAISE_EXCEPTION: {
+               unsigned long exc, swcr, fpcr, fex;
+               unsigned int *state;
+
+               if (get_user(exc, (unsigned long __user *)buffer))
+                       return -EFAULT;
+               state = &current_thread_info()->ieee_state;
+               exc &= IEEE_STATUS_MASK;
+
+               /* Update softare trap enable bits.  */
+               swcr = (*state & IEEE_SW_MASK) | exc;
+               *state |= exc;
 
                /* Update the real fpcr.  */
                fpcr = rdfpcr();
-               fpcr &= FPCR_DYN_MASK;
                fpcr |= ieee_swcr_to_fpcr(swcr);
                wrfpcr(fpcr);
 
-               /* If any exceptions are now unmasked, send a signal.  */
-               fex = ((swcr & IEEE_STATUS_MASK)
-                      >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
+               /* If any exceptions set by this call, and are unmasked,
+                  send a signal.  Old exceptions are not signaled.  */
+               fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
                if (fex) {
                        siginfo_t info;
                        int si_code = 0;
@@ -765,7 +775,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
                        info.si_addr = NULL;  /* FIXME */
                        send_sig_info(SIGFPE, &info, current);
                }
-
                return 0;
        }
 
@@ -817,7 +826,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
    affects all sorts of things, like timeval and itimerval.  */
 
 extern struct timezone sys_tz;
-extern int do_adjtimex(struct timex *);
 
 struct timeval32
 {
@@ -956,7 +964,7 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs)
                        return -EFAULT;
        }
 
-       return do_utimes(filename, tvs ? ktvs : NULL);
+       return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL);
 }
 
 #define MAX_SELECT_SECONDS \
@@ -969,19 +977,22 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
        fd_set_bits fds;
        char *bits;
        size_t size;
-       unsigned long timeout;
-       int ret;
+       long timeout;
+       int ret = -EINVAL;
+       struct fdtable *fdt;
+       int max_fdset;
 
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) {
                time_t sec, usec;
 
-               if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
-                   || (ret = __get_user(sec, &tvp->tv_sec))
-                   || (ret = __get_user(usec, &tvp->tv_usec)))
+               if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
+                   || __get_user(sec, &tvp->tv_sec)
+                   || __get_user(usec, &tvp->tv_usec)) {
+                       ret = -EFAULT;
                        goto out_nofds;
+               }
 
-               ret = -EINVAL;
                if (sec < 0 || usec < 0)
                        goto out_nofds;
 
@@ -991,8 +1002,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
                }
        }
 
-       ret = -EINVAL;
-       if (n < 0 || n > current->files->max_fdset)
+       rcu_read_lock();
+       fdt = files_fdtable(current->files);
+       max_fdset = fdt->max_fdset;
+       rcu_read_unlock();
+       if (n < 0 || n > max_fdset)
                goto out_nofds;
 
        /*
@@ -1033,9 +1047,10 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
                ret = 0;
        }
 
-       set_fd_set(n, inp->fds_bits, fds.res_in);
-       set_fd_set(n, outp->fds_bits, fds.res_out);
-       set_fd_set(n, exp->fds_bits, fds.res_ex);
+       if (set_fd_set(n, inp->fds_bits, fds.res_in) ||
+           set_fd_set(n, outp->fds_bits, fds.res_out) ||
+           set_fd_set(n, exp->fds_bits, fds.res_ex))
+               ret = -EFAULT;
 
  out:
        kfree(bits);
@@ -1079,64 +1094,57 @@ osf_getrusage(int who, struct rusage32 __user *ru)
                r.ru_majflt = current->maj_flt;
                break;
        case RUSAGE_CHILDREN:
-               jiffies_to_timeval32(current->cutime, &r.ru_utime);
-               jiffies_to_timeval32(current->cstime, &r.ru_stime);
-               r.ru_minflt = current->cmin_flt;
-               r.ru_majflt = current->cmaj_flt;
-               break;
-       default:
-               jiffies_to_timeval32(current->utime + current->cutime,
-                                  &r.ru_utime);
-               jiffies_to_timeval32(current->stime + current->cstime,
-                                  &r.ru_stime);
-               r.ru_minflt = current->min_flt + current->cmin_flt;
-               r.ru_majflt = current->maj_flt + current->cmaj_flt;
+               jiffies_to_timeval32(current->signal->cutime, &r.ru_utime);
+               jiffies_to_timeval32(current->signal->cstime, &r.ru_stime);
+               r.ru_minflt = current->signal->cmin_flt;
+               r.ru_majflt = current->signal->cmaj_flt;
                break;
        }
 
        return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
-asmlinkage int
-osf_wait4(pid_t pid, int __user *ustatus, int options, struct rusage32 __user *ur)
+asmlinkage long
+osf_wait4(pid_t pid, int __user *ustatus, int options,
+         struct rusage32 __user *ur)
 {
-       if (!ur) {
+       struct rusage r;
+       long ret, err;
+       mm_segment_t old_fs;
+
+       if (!ur)
                return sys_wait4(pid, ustatus, options, NULL);
-       } else {
-               struct rusage r;
-               int ret, status;
-               mm_segment_t old_fs = get_fs();
+
+       old_fs = get_fs();
                
-               set_fs (KERNEL_DS);
-               ret = sys_wait4(pid, &status, options, &r);
-               set_fs (old_fs);
+       set_fs (KERNEL_DS);
+       ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+       set_fs (old_fs);
 
-               if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
-                       return -EFAULT;
-               __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
-               __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
-               __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
-               __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
-               __put_user(r.ru_maxrss, &ur->ru_maxrss);
-               __put_user(r.ru_ixrss, &ur->ru_ixrss);
-               __put_user(r.ru_idrss, &ur->ru_idrss);
-               __put_user(r.ru_isrss, &ur->ru_isrss);
-               __put_user(r.ru_minflt, &ur->ru_minflt);
-               __put_user(r.ru_majflt, &ur->ru_majflt);
-               __put_user(r.ru_nswap, &ur->ru_nswap);
-               __put_user(r.ru_inblock, &ur->ru_inblock);
-               __put_user(r.ru_oublock, &ur->ru_oublock);
-               __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
-               __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
-               __put_user(r.ru_nsignals, &ur->ru_nsignals);
-               __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
-               if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw))
-                       return -EFAULT;
+       if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
+               return -EFAULT;
 
-               if (ustatus && put_user(status, ustatus))
-                       return -EFAULT;
-               return ret;
-       }
+       err = 0;
+       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);
+       err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
+       err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
+       err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
+       err |= __put_user(r.ru_idrss, &ur->ru_idrss);
+       err |= __put_user(r.ru_isrss, &ur->ru_isrss);
+       err |= __put_user(r.ru_minflt, &ur->ru_minflt);
+       err |= __put_user(r.ru_majflt, &ur->ru_majflt);
+       err |= __put_user(r.ru_nswap, &ur->ru_nswap);
+       err |= __put_user(r.ru_inblock, &ur->ru_inblock);
+       err |= __put_user(r.ru_oublock, &ur->ru_oublock);
+       err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
+       err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
+       err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
+       err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
+       err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
+
+       return err ? err : ret;
 }
 
 /*
@@ -1153,16 +1161,12 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
        if (get_tv32(&tmp, sleep))
                goto fault;
 
-       ticks = tmp.tv_usec;
-       ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
-       ticks += tmp.tv_sec * HZ;
+       ticks = timeval_to_jiffies(&tmp);
 
-       current->state = TASK_INTERRUPTIBLE;
-       ticks = schedule_timeout(ticks);
+       ticks = schedule_timeout_interruptible(ticks);
 
        if (remain) {
-               tmp.tv_sec = ticks / HZ;
-               tmp.tv_usec = ticks % HZ;
+               jiffies_to_timeval(ticks, &tmp);
                if (put_tv32(remain, &tmp))
                        goto fault;
        }