]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
nfs: simplify swap
authorDave Kleikamp <dave.kleikamp@oracle.com>
Tue, 15 Oct 2013 18:44:39 +0000 (13:44 -0500)
committerDave Kleikamp <dave.kleikamp@oracle.com>
Fri, 18 Oct 2013 15:56:50 +0000 (10:56 -0500)
swap_writepage can now call nfs's write_iter f_op, eliminating the need to
implement for the special-case direct_IO a_op. There is no longer a need to
pass the uio flag through the direct write path.

Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
Acked-by: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: linux-nfs@vger.kernel.org
fs/nfs/direct.c
fs/nfs/file.c
include/linux/blk_types.h
include/linux/fs.h
include/linux/nfs_fs.h
mm/page_io.c

index 7f5377b94e9214e63215830fe3f87e1958b8150f..239c2fe05ea5f2a5a16ccc10b3426e77a842e4d6 100644 (file)
@@ -118,28 +118,18 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
  * @nr_segs: size of iovec array
  *
  * The presence of this routine in the address space ops vector means
- * the NFS client supports direct I/O. However, for most direct IO, we
- * shunt off direct read and write requests before the VFS gets them,
- * so this method is only ever called for swap.
+ * the NFS client supports direct I/O. However, we shunt off direct
+ * read and write requests before the VFS gets them, so this method
+ * should never be called.
  */
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
                      loff_t pos)
 {
-#ifndef CONFIG_NFS_SWAP
        dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
                        iocb->ki_filp->f_path.dentry->d_name.name,
                        (long long) pos, iter->nr_segs);
 
        return -EINVAL;
-#else
-       VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE);
-
-       if (rw == READ || rw == KERNEL_READ)
-               return nfs_file_direct_read(iocb, iter, pos,
-                               rw == READ ? true : false);
-       return nfs_file_direct_write(iocb, iter, pos,
-                               rw == WRITE ? true : false);
-#endif /* CONFIG_NFS_SWAP */
 }
 
 static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
@@ -311,7 +301,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_read_completion_ops = {
  */
 static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *desc,
                                                const struct iovec *iov,
-                                               loff_t pos, bool uio)
+                                               loff_t pos)
 {
        struct nfs_direct_req *dreq = desc->pg_dreq;
        struct nfs_open_context *ctx = dreq->ctx;
@@ -339,20 +329,12 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de
                                          GFP_KERNEL);
                if (!pagevec)
                        break;
-               if (uio) {
-                       down_read(&current->mm->mmap_sem);
-                       result = get_user_pages(current, current->mm, user_addr,
+               down_read(&current->mm->mmap_sem);
+               result = get_user_pages(current, current->mm, user_addr,
                                        npages, 1, 0, pagevec, NULL);
-                       up_read(&current->mm->mmap_sem);
-                       if (result < 0)
-                               break;
-               } else {
-                       WARN_ON(npages != 1);
-                       result = get_kernel_page(user_addr, 1, pagevec);
-                       if (WARN_ON(result != 1))
-                               break;
-               }
-
+               up_read(&current->mm->mmap_sem);
+               if (result < 0)
+                       break;
                if ((unsigned)result < npages) {
                        bytes = result * PAGE_SIZE;
                        if (bytes <= pgbase) {
@@ -402,7 +384,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de
 
 static ssize_t nfs_direct_do_schedule_read_iovec(
                struct nfs_pageio_descriptor *desc, const struct iovec *iov,
-               unsigned long nr_segs, loff_t pos, bool uio)
+               unsigned long nr_segs, loff_t pos)
 {
        ssize_t result = -EINVAL;
        size_t requested_bytes = 0;
@@ -410,7 +392,7 @@ static ssize_t nfs_direct_do_schedule_read_iovec(
 
        for (seg = 0; seg < nr_segs; seg++) {
                const struct iovec *vec = &iov[seg];
-               result = nfs_direct_read_schedule_segment(desc, vec, pos, uio);
+               result = nfs_direct_read_schedule_segment(desc, vec, pos);
                if (result < 0)
                        break;
                requested_bytes += result;
@@ -467,8 +449,7 @@ static ssize_t nfs_direct_do_schedule_read_bvec(
 #endif /* CONFIG_BLOCK */
 
 static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq,
-                                       struct iov_iter *iter, loff_t pos,
-                                       bool uio)
+                                       struct iov_iter *iter, loff_t pos)
 {
        struct nfs_pageio_descriptor desc;
        ssize_t result;
@@ -479,10 +460,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq,
        desc.pg_dreq = dreq;
 
        if (iov_iter_has_iovec(iter)) {
-               if (uio)
-                       dreq->flags = NFS_ODIRECT_MARK_DIRTY;
                result = nfs_direct_do_schedule_read_iovec(&desc,
-                               iov_iter_iovec(iter), iter->nr_segs, pos, uio);
+                               iov_iter_iovec(iter), iter->nr_segs, pos);
 #ifdef CONFIG_BLOCK
        } else if (iov_iter_has_bvec(iter)) {
                result = nfs_direct_do_schedule_read_bvec(&desc,
@@ -508,7 +487,7 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq,
 }
 
 static ssize_t nfs_direct_read(struct kiocb *iocb, struct iov_iter *iter,
-                              loff_t pos, bool uio)
+                              loff_t pos)
 {
        ssize_t result = -ENOMEM;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -532,7 +511,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, struct iov_iter *iter,
                dreq->iocb = iocb;
 
        NFS_I(inode)->read_io += iov_iter_count(iter);
-       result = nfs_direct_read_schedule(dreq, iter, pos, uio);
+       result = nfs_direct_read_schedule(dreq, iter, pos);
        if (!result)
                result = nfs_direct_wait(dreq);
 out_release:
@@ -697,7 +676,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
  */
 static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *desc,
                                                 const struct iovec *iov,
-                                                loff_t pos, bool uio)
+                                                loff_t pos)
 {
        struct nfs_direct_req *dreq = desc->pg_dreq;
        struct nfs_open_context *ctx = dreq->ctx;
@@ -725,19 +704,12 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d
                if (!pagevec)
                        break;
 
-               if (uio) {
-                       down_read(&current->mm->mmap_sem);
-                       result = get_user_pages(current, current->mm, user_addr,
-                                               npages, 0, 0, pagevec, NULL);
-                       up_read(&current->mm->mmap_sem);
-                       if (result < 0)
-                               break;
-               } else {
-                       WARN_ON(npages != 1);
-                       result = get_kernel_page(user_addr, 0, pagevec);
-                       if (WARN_ON(result != 1))
-                               break;
-               }
+               down_read(&current->mm->mmap_sem);
+               result = get_user_pages(current, current->mm, user_addr,
+                                       npages, 0, 0, pagevec, NULL);
+               up_read(&current->mm->mmap_sem);
+               if (result < 0)
+                       break;
 
                if ((unsigned)result < npages) {
                        bytes = result * PAGE_SIZE;
@@ -868,7 +840,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
 
 static ssize_t nfs_direct_do_schedule_write_iovec(
                struct nfs_pageio_descriptor *desc, const struct iovec *iov,
-               unsigned long nr_segs, loff_t pos, bool uio)
+               unsigned long nr_segs, loff_t pos)
 {
        ssize_t result = -EINVAL;
        size_t requested_bytes = 0;
@@ -877,7 +849,7 @@ static ssize_t nfs_direct_do_schedule_write_iovec(
        for (seg = 0; seg < nr_segs; seg++) {
                const struct iovec *vec = &iov[seg];
                result = nfs_direct_write_schedule_segment(desc, vec,
-                                                          pos, uio);
+                                                          pos);
                if (result < 0)
                        break;
                requested_bytes += result;
@@ -935,8 +907,7 @@ static ssize_t nfs_direct_do_schedule_write_bvec(
 #endif /* CONFIG_BLOCK */
 
 static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq,
-                                        struct iov_iter *iter, loff_t pos,
-                                        bool uio)
+                                        struct iov_iter *iter, loff_t pos)
 {
        struct nfs_pageio_descriptor desc;
        struct inode *inode = dreq->inode;
@@ -952,7 +923,7 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq,
 
        if (iov_iter_has_iovec(iter)) {
                result = nfs_direct_do_schedule_write_iovec(&desc,
-                               iov_iter_iovec(iter), iter->nr_segs, pos, uio);
+                               iov_iter_iovec(iter), iter->nr_segs, pos);
 #ifdef CONFIG_BLOCK
        } else if (iov_iter_has_bvec(iter)) {
                result = nfs_direct_do_schedule_write_bvec(&desc,
@@ -979,7 +950,7 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq,
 }
 
 static ssize_t nfs_direct_write(struct kiocb *iocb, struct iov_iter *iter,
-                               loff_t pos, bool uio)
+                               loff_t pos)
 {
        ssize_t result = -ENOMEM;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -1002,7 +973,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, struct iov_iter *iter,
        if (!is_sync_kiocb(iocb))
                dreq->iocb = iocb;
 
-       result = nfs_direct_write_schedule(dreq, iter, pos, uio);
+       result = nfs_direct_write_schedule(dreq, iter, pos);
        if (!result)
                result = nfs_direct_wait(dreq);
 out_release:
@@ -1032,7 +1003,7 @@ out:
  * cache.
  */
 ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
-                            loff_t pos, bool uio)
+                            loff_t pos)
 {
        ssize_t retval = -EINVAL;
        struct file *file = iocb->ki_filp;
@@ -1057,7 +1028,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
 
        task_io_account_read(count);
 
-       retval = nfs_direct_read(iocb, iter, pos, uio);
+       retval = nfs_direct_read(iocb, iter, pos);
        if (retval > 0)
                iocb->ki_pos = pos + retval;
 
@@ -1087,7 +1058,7 @@ out:
  * is no atomic O_APPEND write facility in the NFS protocol.
  */
 ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
-                             loff_t pos, bool uio)
+                             loff_t pos)
 {
        ssize_t retval = -EINVAL;
        struct file *file = iocb->ki_filp;
@@ -1119,7 +1090,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
 
        task_io_account_write(count);
 
-       retval = nfs_direct_write(iocb, iter, pos, uio);
+       retval = nfs_direct_write(iocb, iter, pos);
        if (retval > 0) {
                struct inode *inode = mapping->host;
 
index af9025b4639222e995d409981320b1cf21b30f2e..19ac4fd4054460136a0164b848015b80594a8025 100644 (file)
@@ -181,7 +181,7 @@ nfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
        ssize_t result;
 
        if (iocb->ki_filp->f_flags & O_DIRECT)
-               return nfs_file_direct_read(iocb, iter, pos, true);
+               return nfs_file_direct_read(iocb, iter, pos);
 
        dprintk("NFS: read_iter(%s/%s, %lu@%lu)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -669,7 +669,7 @@ ssize_t nfs_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
                return result;
 
        if (iocb->ki_filp->f_flags & O_DIRECT)
-               return nfs_file_direct_write(iocb, iter, pos, true);
+               return nfs_file_direct_write(iocb, iter, pos);
 
        dprintk("NFS: write_iter(%s/%s, %lu@%lld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
index fa1abeb45b7602a4f0c1a4098f05f63d7a075281..1bea25f14796f8fabed2b310adde5316fe893af1 100644 (file)
@@ -176,7 +176,6 @@ enum rq_flag_bits {
        __REQ_FLUSH_SEQ,        /* request for flush sequence */
        __REQ_IO_STAT,          /* account I/O stat */
        __REQ_MIXED_MERGE,      /* merge of different types, fail separately */
-       __REQ_KERNEL,           /* direct IO to kernel pages */
        __REQ_PM,               /* runtime pm request */
        __REQ_NR_BITS,          /* stops here */
 };
@@ -227,7 +226,6 @@ enum rq_flag_bits {
 #define REQ_IO_STAT            (1 << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE                (1 << __REQ_MIXED_MERGE)
 #define REQ_SECURE             (1 << __REQ_SECURE)
-#define REQ_KERNEL             (1 << __REQ_KERNEL)
 #define REQ_PM                 (1 << __REQ_PM)
 
 #endif /* __LINUX_BLK_TYPES_H */
index 747755e3ee031d50437a74476126cc6934d3e5e8..3f29da3340ba1dd990e639de990abb517f40caf5 100644 (file)
@@ -182,8 +182,6 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define READ                   0
 #define WRITE                  RW_MASK
 #define READA                  RWA_MASK
-#define KERNEL_READ            (READ|REQ_KERNEL)
-#define KERNEL_WRITE           (WRITE|REQ_KERNEL)
 
 #define READ_SYNC              (READ | REQ_SYNC)
 #define WRITE_SYNC             (WRITE | REQ_SYNC | REQ_NOIDLE)
index a2f5b570f3dd5abc3bffe0dd0c741ea1c5a3c197..ad17f6e018785425b2c34a2b8b8ba377c574eff1 100644 (file)
@@ -459,9 +459,9 @@ extern int nfs3_removexattr (struct dentry *, const char *name);
  */
 extern ssize_t nfs_direct_IO(int, struct kiocb *, struct iov_iter *, loff_t);
 extern ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
-                       loff_t pos, bool uio);
+                       loff_t pos);
 extern ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
-                       loff_t pos, bool uio);
+                       loff_t pos);
 
 /*
  * linux/fs/nfs/dir.c
index 4f7e59909f20bab51b122bbbb9ec8c4fb6a6ff38..e4e6a4f57b09f2c304683e026a8dab05f98a500d 100644 (file)
@@ -258,14 +258,14 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
        if (sis->flags & SWP_FILE) {
                struct kiocb kiocb;
                struct file *swap_file = sis->swap_file;
-               struct address_space *mapping = swap_file->f_mapping;
-               struct iovec iov = {
-                       .iov_base = kmap(page),
-                       .iov_len  = PAGE_SIZE,
+               struct bio_vec bvec = {
+                       .bv_page = kmap(page),
+                       .bv_len = PAGE_SIZE,
+                       .bv_offset = 0,
                };
                struct iov_iter iter;
 
-               iov_iter_init(&iter, &iov, 1, PAGE_SIZE, 0);
+               iov_iter_init_bvec(&iter, &bvec, 1, PAGE_SIZE, 0);
 
                init_sync_kiocb(&kiocb, swap_file);
                kiocb.ki_pos = page_file_offset(page);
@@ -273,8 +273,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
 
                set_page_writeback(page);
                unlock_page(page);
-               ret = mapping->a_ops->direct_IO(KERNEL_WRITE, &kiocb, &iter,
-                                               kiocb.ki_pos);
+               ret = swap_file->f_op->write_iter(&kiocb, &iter, kiocb.ki_pos);
                kunmap(page);
                if (ret == PAGE_SIZE) {
                        count_vm_event(PSWPOUT);