]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/read_write.c
Merge branch 'omap-clock-fixes' of git://git.pwsan.com/linux-2.6
[linux-2.6-omap-h63xx.git] / fs / read_write.c
index 400fe81c973e90cccdb94c814325bc3ce4e39d19..9d1e76bb9ee147b8236630ba953a53873b1847d4 100644 (file)
@@ -731,6 +731,62 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
        return ret;
 }
 
+static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
+{
+#define HALF_LONG_BITS (BITS_PER_LONG / 2)
+       return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
+}
+
+SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
+               unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
+{
+       loff_t pos = pos_from_hilo(pos_h, pos_l);
+       struct file *file;
+       ssize_t ret = -EBADF;
+       int fput_needed;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       file = fget_light(fd, &fput_needed);
+       if (file) {
+               ret = -ESPIPE;
+               if (file->f_mode & FMODE_PREAD)
+                       ret = vfs_readv(file, vec, vlen, &pos);
+               fput_light(file, fput_needed);
+       }
+
+       if (ret > 0)
+               add_rchar(current, ret);
+       inc_syscr(current);
+       return ret;
+}
+
+SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec,
+               unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
+{
+       loff_t pos = pos_from_hilo(pos_h, pos_l);
+       struct file *file;
+       ssize_t ret = -EBADF;
+       int fput_needed;
+
+       if (pos < 0)
+               return -EINVAL;
+
+       file = fget_light(fd, &fput_needed);
+       if (file) {
+               ret = -ESPIPE;
+               if (file->f_mode & FMODE_PWRITE)
+                       ret = vfs_writev(file, vec, vlen, &pos);
+               fput_light(file, fput_needed);
+       }
+
+       if (ret > 0)
+               add_wchar(current, ret);
+       inc_syscw(current);
+       return ret;
+}
+
 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
                           size_t count, loff_t max)
 {