infinibad: weird APIs switched to ->write_iter()
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 4 Apr 2015 04:11:32 +0000 (00:11 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Apr 2015 02:29:42 +0000 (22:29 -0400)
Things Not To Do When Writing A Driver, part 1001st:
have writev() and write() on the same file doing completely
different things.  As in, "interpret very different sets of
commands".

We _can_ handle that, but it's a bloody bad idea.
Don't do that in new drivers.  Ever.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/qib/qib_file_ops.c

index aed8afee56da16a6a3609a247c9bea2c54060c44..450d1596500512c7f41174dec8d078bb15edb79a 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
+#include <linux/uio.h>
 #include <asm/pgtable.h>
 
 #include "ipath_kernel.h"
@@ -52,15 +53,19 @@ static int ipath_open(struct inode *, struct file *);
 static int ipath_close(struct inode *, struct file *);
 static ssize_t ipath_write(struct file *, const char __user *, size_t,
                           loff_t *);
-static ssize_t ipath_writev(struct kiocb *, const struct iovec *,
-                           unsigned long , loff_t);
+static ssize_t ipath_write_iter(struct kiocb *, struct iov_iter *from);
 static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
 static int ipath_mmap(struct file *, struct vm_area_struct *);
 
+/*
+ * This is really, really weird shit - write() and writev() here
+ * have completely unrelated semantics.  Sucky userland ABI,
+ * film at 11.
+ */
 static const struct file_operations ipath_file_ops = {
        .owner = THIS_MODULE,
        .write = ipath_write,
-       .aio_write = ipath_writev,
+       .write_iter = ipath_write_iter,
        .open = ipath_open,
        .release = ipath_close,
        .poll = ipath_poll,
@@ -2413,18 +2418,17 @@ bail:
        return ret;
 }
 
-static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov,
-                           unsigned long dim, loff_t off)
+static ssize_t ipath_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *filp = iocb->ki_filp;
        struct ipath_filedata *fp = filp->private_data;
        struct ipath_portdata *pd = port_fp(filp);
        struct ipath_user_sdma_queue *pq = fp->pq;
 
-       if (!dim)
+       if (!iter_is_iovec(from) || !from->nr_segs)
                return -EINVAL;
 
-       return ipath_user_sdma_writev(pd->port_dd, pq, iov, dim);
+       return ipath_user_sdma_writev(pd->port_dd, pq, from->iov, from->nr_segs);
 }
 
 static struct class *ipath_class;
index 14046f5a37fa332cf5e5b25ba1a86a5fe7918188..9ea6c440a00ca7012f6422f1ffd7f525b8d80548 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/pgtable.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/uio.h>
 
 #include "qib.h"
 #include "qib_common.h"
 static int qib_open(struct inode *, struct file *);
 static int qib_close(struct inode *, struct file *);
 static ssize_t qib_write(struct file *, const char __user *, size_t, loff_t *);
-static ssize_t qib_aio_write(struct kiocb *, const struct iovec *,
-                            unsigned long, loff_t);
+static ssize_t qib_write_iter(struct kiocb *, struct iov_iter *);
 static unsigned int qib_poll(struct file *, struct poll_table_struct *);
 static int qib_mmapf(struct file *, struct vm_area_struct *);
 
+/*
+ * This is really, really weird shit - write() and writev() here
+ * have completely unrelated semantics.  Sucky userland ABI,
+ * film at 11.
+ */
 static const struct file_operations qib_file_ops = {
        .owner = THIS_MODULE,
        .write = qib_write,
-       .aio_write = qib_aio_write,
+       .write_iter = qib_write_iter,
        .open = qib_open,
        .release = qib_close,
        .poll = qib_poll,
@@ -2248,17 +2253,16 @@ bail:
        return ret;
 }
 
-static ssize_t qib_aio_write(struct kiocb *iocb, const struct iovec *iov,
-                            unsigned long dim, loff_t off)
+static ssize_t qib_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct qib_filedata *fp = iocb->ki_filp->private_data;
        struct qib_ctxtdata *rcd = ctxt_fp(iocb->ki_filp);
        struct qib_user_sdma_queue *pq = fp->pq;
 
-       if (!dim || !pq)
+       if (!iter_is_iovec(from) || !from->nr_segs || !pq)
                return -EINVAL;
-
-       return qib_user_sdma_writev(rcd, pq, iov, dim);
+                        
+       return qib_user_sdma_writev(rcd, pq, from->iov, from->nr_segs);
 }
 
 static struct class *qib_class;