patch-2.4.0-test6 linux/arch/sparc64/kernel/sys_sparc32.c

Next file: linux/arch/sparc64/kernel/sys_sunos32.c
Previous file: linux/arch/sparc64/kernel/sys_sparc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.156 2000/07/13 10:59:13 davem Exp $
+/* $Id: sys_sparc32.c,v 1.159 2000/08/08 02:47:50 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -253,45 +253,6 @@
 	return high2lowgid(current->egid);
 }
 
-/* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
- *
- * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
- */
-static inline int do_getname32(const char *filename, char *page)
-{
-	int retval;
-
-	/* 32bit pointer will be always far below TASK_SIZE :)) */
-	retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
-	if (retval > 0) {
-		if (retval < PAGE_SIZE)
-			return 0;
-		return -ENAMETOOLONG;
-	} else if (!retval)
-		retval = -ENOENT;
-	return retval;
-}
-
-char * getname32(const char *filename)
-{
-	char *tmp, *result;
-
-	result = ERR_PTR(-ENOMEM);
-	tmp = __getname();
-	if (tmp)  {
-		int retval = do_getname32(filename, tmp);
-
-		result = tmp;
-		if (retval < 0) {
-			putname(tmp);
-			result = ERR_PTR(retval);
-		}
-	}
-	return result;
-}
-
 /* 32-bit timeval and related flotsam.  */
 
 struct timeval32
@@ -799,7 +760,6 @@
 {
 	int version, err;
 
-	lock_kernel();
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
@@ -861,7 +821,6 @@
 	err = -EINVAL;
 
 out:
-	unlock_kernel();
 	return err;
 }
 
@@ -953,7 +912,7 @@
 		return sys_quotactl(cmd, special,
 				    id, (caddr_t)addr);
 	}
-	spec = getname32 (special);
+	spec = getname (special);
 	err = PTR_ERR(spec);
 	if (IS_ERR(spec)) return err;
 	old_fs = get_fs ();
@@ -998,7 +957,7 @@
 	mm_segment_t old_fs = get_fs();
 	char *pth;
 	
-	pth = getname32 (path);
+	pth = getname (path);
 	ret = PTR_ERR(pth);
 	if (!IS_ERR(pth)) {
 		set_fs (KERNEL_DS);
@@ -1064,7 +1023,7 @@
 	if (get_user (t.actime, &times->actime) ||
 	    __get_user (t.modtime, &times->modtime))
 		return -EFAULT;
-	filenam = getname32 (filename);
+	filenam = getname (filename);
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		old_fs = get_fs();
@@ -1078,7 +1037,8 @@
 
 struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
 
-typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
 			      const struct iovec32 *vector, u32 count)
@@ -1088,14 +1048,15 @@
 	struct iovec *iov=iovstack, *ivp;
 	struct inode *inode;
 	long retval, i;
-	IO_fn_t fn;
+	io_fn_t fn;
+	iov_fn_t fnv;
 
 	/* First get the "struct iovec" from user memory and
 	 * verify all the pointers
 	 */
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -1127,33 +1088,19 @@
 	retval = locks_verify_area((type == VERIFY_WRITE
 				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
 				   inode, file, file->f_pos, tot_len);
-	if (retval) {
-		if (iov != iovstack)
-			kfree(iov);
-		return retval;
-	}
+	if (retval)
+		goto out;
 
-	/* Then do the actual IO.  Note that sockets need to be handled
-	 * specially as they have atomicity guarantees and can handle
-	 * iovec's natively
-	 */
-	if (inode->i_sock) {
-		int err;
-		err = sock_readv_writev(type, inode, file, iov, count, tot_len);
-		if (iov != iovstack)
-			kfree(iov);
-		return err;
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
+	if (fnv) {
+		retval = fnv(file, iov, count, &file->f_pos);
+		goto out;
 	}
 
-	if (!file->f_op) {
-		if (iov != iovstack)
-			kfree(iov);
-		return -EINVAL;
-	}
-	/* VERIFY_WRITE actually means a read, as we write to user space */
-	fn = file->f_op->read;
-	if (type == VERIFY_READ)
-		fn = (IO_fn_t) file->f_op->write;		
+	fn = (type == VERIFY_WRITE ? file->f_op->read :
+	      (io_fn_t) file->f_op->write);
+
 	ivp = iov;
 	while (count > 0) {
 		void * base;
@@ -1165,17 +1112,18 @@
 		count--;
 		nr = fn(file, base, len, &file->f_pos);
 		if (nr < 0) {
-			if (retval)
-				break;
-			retval = nr;
+			if (!retval)
+				retval = nr;
 			break;
 		}
 		retval += nr;
 		if (nr != len)
 			break;
 	}
+out:
 	if (iov != iovstack)
 		kfree(iov);
+
 	return retval;
 }
 
@@ -1188,7 +1136,8 @@
 	if(!file)
 		goto bad_file;
 
-	if (file->f_op && file->f_op->read && (file->f_mode & FMODE_READ))
+	if (file->f_op && (file->f_mode & FMODE_READ) &&
+	    (file->f_op->readv || file->f_op->read))
 		ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
 	fput(file);
 
@@ -1204,7 +1153,8 @@
 	file = fget(fd);
 	if(!file)
 		goto bad_file;
-	if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE))
+	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+	    (file->f_op->writev || file->f_op->write))
 		ret = do_readv_writev32(VERIFY_READ, file, vector, count);
 	fput(file);
 
@@ -1572,6 +1522,16 @@
 	return err;
 }
 
+/* Perhaps this belongs in fs.h or similar. -DaveM */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+	struct inode * inode = dentry->d_inode;
+	if (inode->i_op && inode->i_op->revalidate)
+		return inode->i_op->revalidate(dentry);
+	return 0;
+}
+
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
 	struct nameidata nd;
@@ -1579,16 +1539,9 @@
 
 	error = user_path_walk(filename, &nd);
 	if (!error) {
-		struct inode *inode = nd.dentry->d_inode;
-
-		if (inode->i_op &&
-		    inode->i_op->revalidate)
-			error = inode->i_op->revalidate(nd.dentry);
-		else
-			error = 0;
+		error = do_revalidate(nd.dentry);
 		if (!error)
-			error = cp_new_stat32(inode, statbuf);
-
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
 		path_release(&nd);
 	}
 	return error;
@@ -1601,15 +1554,9 @@
 
 	error = user_path_walk_link(filename, &nd);
 	if (!error) {
-		struct inode *inode = nd.dentry->d_inode;
-
-		if (inode->i_op &&
-		    inode->i_op->revalidate)
-			error = inode->i_op->revalidate(nd.dentry);
-		else
-			error = 0;
+		error = do_revalidate(nd.dentry);
 		if (!error)
-			error = cp_new_stat32(inode, statbuf);
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
 
 		path_release(&nd);
 	}
@@ -1623,16 +1570,11 @@
 
 	f = fget(fd);
 	if (f) {
-		struct inode *inode = f->f_dentry->d_inode;
+		struct dentry * dentry = f->f_dentry;
 
-		if (inode->i_op &&
-		    inode->i_op->revalidate)
-			err = inode->i_op->revalidate(f->f_dentry);
-		else
-			err = 0;
+		err = do_revalidate(dentry);
 		if (!err)
-			err = cp_new_stat32(inode, statbuf);
-
+			err = cp_new_stat32(dentry->d_inode, statbuf);
 		fput(f);
 	}
 	return err;
@@ -1738,7 +1680,6 @@
 
 	is_smb = is_ncp = 0;
 
-	lock_kernel();
 	err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
 	if (err)
 		goto out;
@@ -1764,16 +1705,20 @@
 		goto dev_out;
 
 	if (!is_smb && !is_ncp) {
+		lock_kernel();
 		err = do_mount((char*)dev_page, (char*)dir_page,
 				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
 	} else {
 		if (is_ncp)
 			do_ncp_super_data_conv((void *)data_page);
 		else
 			do_smb_super_data_conv((void *)data_page);
 
+		lock_kernel();
 		err = do_mount((char*)dev_page, (char*)dir_page,
 				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
 	}
 	free_page(dir_page);
 
@@ -1787,7 +1732,6 @@
 	free_page(type_page);
 
 out:
-	unlock_kernel();
 	return err;
 }
 
@@ -2234,34 +2178,9 @@
 					   24 for IPv6,
 					   about 80 for AX.25 */
 
-/* XXX These as well... */
-extern __inline__ struct socket *socki_lookup(struct inode *inode)
-{
-	return &inode->u.socket_i;
-}
-
-extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
-{
-	struct file *file;
-	struct inode *inode;
-
-	if (!(file = fget(fd)))
-	{
-		*err = -EBADF;
-		return NULL;
-	}
-
-	inode = file->f_dentry->d_inode;
-	if (!inode || !inode->i_sock || !socki_lookup(inode))
-	{
-		*err = -ENOTSOCK;
-		fput(file);
-		return NULL;
-	}
-
-	return socki_lookup(inode);
-}
+extern struct socket *sockfd_lookup(int fd, int *err);
 
+/* XXX This as well... */
 extern __inline__ void sockfd_put(struct socket *sock)
 {
 	fput(sock->file);
@@ -2678,7 +2597,6 @@
 	}
 	kern_msg.msg_flags = user_flags;
 
-	lock_kernel();
 	sock = sockfd_lookup(fd, &err);
 	if (sock != NULL) {
 		if (sock->file->f_flags & O_NONBLOCK)
@@ -2686,7 +2604,6 @@
 		err = sock_sendmsg(sock, &kern_msg, total_len);
 		sockfd_put(sock);
 	}
-	unlock_kernel();
 
 	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
 	if(ctl_buf != ctl)
@@ -2725,7 +2642,6 @@
 	cmsg_ptr = (unsigned long) kern_msg.msg_control;
 	kern_msg.msg_flags = 0;
 
-	lock_kernel();
 	sock = sockfd_lookup(fd, &err);
 	if (sock != NULL) {
 		struct scm_cookie scm;
@@ -2762,7 +2678,6 @@
 		}
 		sockfd_put(sock);
 	}
-	unlock_kernel();
 
 	if(uaddr != NULL && err >= 0)
 		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
@@ -3084,7 +2999,7 @@
         if((u32)regs->u_regs[UREG_G1] == 0)
                 base = 1;
 
-        filename = getname32((char *)AA(regs->u_regs[base + UREG_I0]));
+        filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
 	error = PTR_ERR(filename);
         if(IS_ERR(filename))
                 goto out;
@@ -3926,7 +3841,7 @@
 	mm_segment_t old_fs;
 	int ret;
 
-	kfilename = getname32(filename);
+	kfilename = getname(filename);
 	ret = PTR_ERR(kfilename);
 	if (!IS_ERR(kfilename)) {
 		if (tvs) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)