patch-2.2.14 linux/arch/sparc64/kernel/sys_sparc32.c
Next file: linux/arch/sparc64/kernel/time.c
Previous file: linux/arch/sparc64/kernel/smp.c
Back to the patch index
Back to the overall index
- Lines: 321
- Date:
Tue Jan 4 10:12:13 2000
- Orig file:
v2.2.13/linux/arch/sparc64/kernel/sys_sparc32.c
- Orig date:
Wed Jun 2 09:55:38 1999
diff -u --recursive --new-file v2.2.13/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107.2.1 1999/05/16 10:48:44 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.5 1999/11/12 11:17:47 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -44,6 +44,7 @@
#include <linux/personality.h>
#include <linux/stat.h>
#include <linux/timex.h>
+#include <linux/filter.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -1136,8 +1137,10 @@
}
ret = -EINVAL;
- if (n < 0 || n > KFDS_NR)
+ if (n < 0)
goto out_nofds;
+ if (n > current->files->max_fdset)
+ n = current->files->max_fdset;
/*
* We need 6 bitmaps (in/out/ex for both incoming and outgoing),
@@ -1197,84 +1200,157 @@
return ret;
}
-static inline int putstat(struct stat32 *ubuf, struct stat *kbuf)
+static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
{
+ unsigned long ino, blksize, blocks;
+ kdev_t dev, rdev;
+ umode_t mode;
+ nlink_t nlink;
+ uid_t uid;
+ gid_t gid;
+ off_t size;
+ time_t atime, mtime, ctime;
int err;
-
- err = put_user (kbuf->st_dev, &ubuf->st_dev);
- err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
- err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
- err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
- err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
- err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
- err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
- err |= __put_user (kbuf->st_size, &ubuf->st_size);
- err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
- err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
- err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
- err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
- err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+
+ /* Stream the loads of inode data into the load buffer,
+ * then we push it all into the store buffer below. This
+ * should give optimal cache performance.
+ */
+ ino = inode->i_ino;
+ dev = inode->i_dev;
+ mode = inode->i_mode;
+ nlink = inode->i_nlink;
+ uid = inode->i_uid;
+ gid = inode->i_gid;
+ rdev = inode->i_rdev;
+ size = inode->i_size;
+ atime = inode->i_atime;
+ mtime = inode->i_mtime;
+ ctime = inode->i_ctime;
+ blksize = inode->i_blksize;
+ blocks = inode->i_blocks;
+
+ err = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
+ err |= put_user(ino, &statbuf->st_ino);
+ err |= put_user(mode, &statbuf->st_mode);
+ err |= put_user(nlink, &statbuf->st_nlink);
+ err |= put_user(uid, &statbuf->st_uid);
+ err |= put_user(gid, &statbuf->st_gid);
+ err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
+ err |= put_user(size, &statbuf->st_size);
+ err |= put_user(atime, &statbuf->st_atime);
+ err |= put_user(0, &statbuf->__unused1);
+ err |= put_user(mtime, &statbuf->st_mtime);
+ err |= put_user(0, &statbuf->__unused2);
+ err |= put_user(ctime, &statbuf->st_ctime);
+ err |= put_user(0, &statbuf->__unused3);
+ if (blksize) {
+ err |= put_user(blksize, &statbuf->st_blksize);
+ err |= put_user(blocks, &statbuf->st_blocks);
+ } else {
+ unsigned int tmp_blocks;
+
+#define D_B 7
+#define I_B (BLOCK_SIZE / sizeof(unsigned short))
+ tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ if (tmp_blocks > D_B) {
+ unsigned int indirect;
+
+ indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
+ tmp_blocks += indirect;
+ if (indirect > 1) {
+ indirect = (indirect - 1 + I_B - 1) / I_B;
+ tmp_blocks += indirect;
+ if (indirect > 1)
+ tmp_blocks++;
+ }
+ }
+ err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
+ err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
+#undef D_B
+#undef I_B
+ }
+ err |= put_user(0, &statbuf->__unused4[0]);
+ err |= put_user(0, &statbuf->__unused4[1]);
+
return err;
}
-extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
-
asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
{
- int ret;
- struct stat s;
- char *filenam;
- mm_segment_t old_fs = get_fs();
-
- filenam = getname32 (filename);
- ret = PTR_ERR(filenam);
- if (!IS_ERR(filenam)) {
- set_fs (KERNEL_DS);
- ret = sys_newstat(filenam, &s);
- set_fs (old_fs);
- putname (filenam);
- if (putstat (statbuf, &s))
- return -EFAULT;
+ struct dentry *dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode *inode = dentry->d_inode;
+
+ if (inode->i_op &&
+ inode->i_op->revalidate)
+ error = inode->i_op->revalidate(dentry);
+ else
+ error = 0;
+ if (!error)
+ error = cp_new_stat32(inode, statbuf);
+
+ dput(dentry);
}
- return ret;
+ unlock_kernel();
+ return error;
}
-extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
-
asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
{
- int ret;
- struct stat s;
- char *filenam;
- mm_segment_t old_fs = get_fs();
-
- filenam = getname32 (filename);
- ret = PTR_ERR(filenam);
- if (!IS_ERR(filenam)) {
- set_fs (KERNEL_DS);
- ret = sys_newlstat(filenam, &s);
- set_fs (old_fs);
- putname (filenam);
- if (putstat (statbuf, &s))
- return -EFAULT;
+ struct dentry *dentry;
+ int error;
+
+ lock_kernel();
+ dentry = lnamei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode *inode = dentry->d_inode;
+
+ if (inode->i_op &&
+ inode->i_op->revalidate)
+ error = inode->i_op->revalidate(dentry);
+ else
+ error = 0;
+ if (!error)
+ error = cp_new_stat32(inode, statbuf);
+
+ dput(dentry);
}
- return ret;
+ unlock_kernel();
+ return error;
}
-extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
-
asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
{
- int ret;
- struct stat s;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_newfstat(fd, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
- return -EFAULT;
- return ret;
+ struct file *f;
+ int err = -EBADF;
+
+ lock_kernel();
+ f = fget(fd);
+ if (f) {
+ struct dentry *dentry = f->f_dentry;
+ struct inode *inode = dentry->d_inode;
+
+ if (inode->i_op &&
+ inode->i_op->revalidate)
+ err = inode->i_op->revalidate(dentry);
+ else
+ err = 0;
+ if (!err)
+ err = cp_new_stat32(inode, statbuf);
+
+ fput(f);
+ }
+ unlock_kernel();
+ return err;
}
extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
@@ -1677,7 +1753,7 @@
siginfo_t32 *
siginfo64to32(siginfo_t32 *d, siginfo_t *s)
{
- memset (&d, 0, sizeof(siginfo_t32));
+ memset (d, 0, sizeof(siginfo_t32));
d->si_signo = s->si_signo;
d->si_errno = s->si_errno;
d->si_code = s->si_code;
@@ -2581,6 +2657,48 @@
return len;
}
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen);
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen)
+{
+ if (optname == SO_ATTACH_FILTER) {
+ struct sock_fprog32 {
+ __u16 len;
+ __u32 filter;
+ } *fprog32 = (struct sock_fprog32 *)optval;
+ struct sock_fprog kfprog;
+ struct sock_filter *kfilter;
+ unsigned int fsize;
+ mm_segment_t old_fs;
+ __u32 uptr;
+ int ret;
+
+ if (get_user(kfprog.len, &fprog32->len) ||
+ __get_user(uptr, &fprog32->filter))
+ return -EFAULT;
+ kfprog.filter = (struct sock_filter *)A(uptr);
+ fsize = kfprog.len * sizeof(struct sock_filter);
+ kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+ if (kfilter == NULL)
+ return -ENOMEM;
+ if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+ kfree(kfilter);
+ return -EFAULT;
+ }
+ kfprog.filter = kfilter;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_setsockopt(fd, level, optname,
+ (char *)&kfprog, sizeof(kfprog));
+ set_fs(old_fs);
+ kfree(kfilter);
+ return ret;
+ }
+ return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
@@ -2599,8 +2717,6 @@
extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
- char *optval, int optlen);
extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
u32 optval, u32 optlen);
@@ -2651,7 +2767,7 @@
case SYS_SHUTDOWN:
return sys_shutdown(a0,a1);
case SYS_SETSOCKOPT:
- return sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]);
+ return sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]);
case SYS_GETSOCKOPT:
return sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
case SYS_SENDMSG:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)