patch-2.1.15 linux/fs/read_write.c
Next file: linux/fs/smbfs/sock.c
Previous file: linux/fs/proc/root.c
Back to the patch index
Back to the overall index
- Lines: 113
- Date:
Thu Dec 12 16:54:19 1996
- Orig file:
v2.1.14/linux/fs/read_write.c
- Orig date:
Tue Oct 29 19:58:44 1996
diff -u --recursive --new-file v2.1.14/linux/fs/read_write.c linux/fs/read_write.c
@@ -13,6 +13,7 @@
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/uio.h>
+#include <linux/malloc.h>
#include <asm/uaccess.h>
@@ -166,41 +167,14 @@
return error;
}
-static long sock_readv_writev(int type, struct inode * inode, struct file * file,
- const struct iovec * iov, long count, long size)
-{
- struct msghdr msg;
- struct socket *sock;
-
- sock = &inode->u.socket_i;
- if (!sock->ops)
- return -EOPNOTSUPP;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
- msg.msg_iov = (struct iovec *) iov;
- msg.msg_iovlen = count;
-
- /* read() does a VERIFY_WRITE */
- if (type == VERIFY_WRITE) {
- if (!sock->ops->recvmsg)
- return -EOPNOTSUPP;
- return sock->ops->recvmsg(sock, &msg, size,
- (file->f_flags & O_NONBLOCK), 0, NULL);
- }
- if (!sock->ops->sendmsg)
- return -EOPNOTSUPP;
- return sock->ops->sendmsg(sock, &msg, size,
- (file->f_flags & O_NONBLOCK), 0);
-}
-
typedef long (*IO_fn_t)(struct inode *, struct file *, char *, unsigned long);
static long do_readv_writev(int type, struct inode * inode, struct file * file,
const struct iovec * vector, unsigned long count)
{
unsigned long tot_len;
- struct iovec iov[UIO_MAXIOV];
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov=iovstack;
long retval, i;
IO_fn_t fn;
@@ -212,27 +186,46 @@
return 0;
if (count > UIO_MAXIOV)
return -EINVAL;
- if (copy_from_user(iov, vector, count*sizeof(*vector)))
+ if (count > UIO_FASTIOV) {
+ iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+ if (!iov)
+ return -ENOMEM;
+ }
+ if (copy_from_user(iov, vector, count*sizeof(*vector))) {
+ if (iov != iovstack)
+ kfree(iov);
return -EFAULT;
+ }
tot_len = 0;
for (i = 0 ; i < count ; i++)
tot_len += iov[i].iov_len;
retval = locks_verify_area(type == VERIFY_READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
inode, file, file->f_pos, tot_len);
- if (retval)
+ if (retval) {
+ if (iov != iovstack)
+ kfree(iov);
return retval;
+ }
/*
* 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)
- return sock_readv_writev(type, inode, file, iov, count, tot_len);
+ if (inode->i_sock) {
+ int err;
+ err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+ if (iov != iovstack)
+ kfree(iov);
+ return err;
+ }
- if (!file->f_op)
+ 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)
@@ -257,6 +250,8 @@
if (nr != len)
break;
}
+ if (iov != iovstack)
+ kfree(iov);
return retval;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov