]> Git Repo - linux.git/blobdiff - mm/filemap.c
__btrfs_direct_write(): switch to iov_iter
[linux.git] / mm / filemap.c
index 5020b280a771a4929bee7dbf0c5aee3fab1dea8b..a840890ed39f20f660dc0b98555bfa56241b6a67 100644 (file)
@@ -906,8 +906,8 @@ EXPORT_SYMBOL(page_cache_prev_hole);
  * Looks up the page cache slot at @mapping & @offset.  If there is a
  * page cache page, it is returned with an increased refcount.
  *
- * If the slot holds a shadow entry of a previously evicted page, it
- * is returned.
+ * If the slot holds a shadow entry of a previously evicted page, or a
+ * swap entry from shmem/tmpfs, it is returned.
  *
  * Otherwise, %NULL is returned.
  */
@@ -928,9 +928,9 @@ repeat:
                        if (radix_tree_deref_retry(page))
                                goto repeat;
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so return it without
-                        * attempting to raise page count.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Return
+                        * it without attempting to raise page count.
                         */
                        goto out;
                }
@@ -983,8 +983,8 @@ EXPORT_SYMBOL(find_get_page);
  * page cache page, it is returned locked and with an increased
  * refcount.
  *
- * If the slot holds a shadow entry of a previously evicted page, it
- * is returned.
+ * If the slot holds a shadow entry of a previously evicted page, or a
+ * swap entry from shmem/tmpfs, it is returned.
  *
  * Otherwise, %NULL is returned.
  *
@@ -1099,8 +1099,8 @@ EXPORT_SYMBOL(find_or_create_page);
  * with ascending indexes.  There may be holes in the indices due to
  * not-present pages.
  *
- * Any shadow entries of evicted pages are included in the returned
- * array.
+ * Any shadow entries of evicted pages, or swap entries from
+ * shmem/tmpfs, are included in the returned array.
  *
  * find_get_entries() returns the number of pages and shadow entries
  * which were found.
@@ -1128,9 +1128,9 @@ repeat:
                        if (radix_tree_deref_retry(page))
                                goto restart;
                        /*
-                        * Otherwise, we must be storing a swap entry
-                        * here as an exceptional entry: so return it
-                        * without attempting to raise page count.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Return
+                        * it without attempting to raise page count.
                         */
                        goto export;
                }
@@ -1198,9 +1198,9 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so skip over it -
-                        * we only reach this from invalidate_mapping_pages().
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Skip
+                        * over it.
                         */
                        continue;
                }
@@ -1265,9 +1265,9 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so stop looking for
-                        * contiguous pages.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Stop
+                        * looking for contiguous pages.
                         */
                        break;
                }
@@ -1341,10 +1341,17 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * This function is never used on a shmem/tmpfs
-                        * mapping, so a swap entry won't be found here.
+                        * A shadow entry of a recently evicted page.
+                        *
+                        * Those entries should never be tagged, but
+                        * this tree walk is lockless and the tags are
+                        * looked up in bulk, one radix tree node at a
+                        * time, so there is a sizable window for page
+                        * reclaim to evict a page we saw tagged.
+                        *
+                        * Skip over it.
                         */
-                       BUG();
+                       continue;
                }
 
                if (!page_cache_get_speculative(page))
@@ -2378,9 +2385,8 @@ int pagecache_write_end(struct file *file, struct address_space *mapping,
 EXPORT_SYMBOL(pagecache_write_end);
 
 ssize_t
-generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
-               unsigned long *nr_segs, loff_t pos,
-               size_t count, size_t ocount)
+generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
+               loff_t pos, size_t count, size_t ocount)
 {
        struct file     *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
@@ -2390,9 +2396,9 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
        pgoff_t         end;
 
        if (count != ocount)
-               *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
+               from->nr_segs = iov_shorten((struct iovec *)from->iov, from->nr_segs, count);
 
-       write_len = iov_length(iov, *nr_segs);
+       write_len = iov_length(from->iov, from->nr_segs);
        end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
 
        written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);
@@ -2419,7 +2425,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
                }
        }
 
-       written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+       written = mapping->a_ops->direct_IO(WRITE, iocb, from->iov, pos, from->nr_segs);
 
        /*
         * Finally, try again to invalidate clean pages which might have been
@@ -2436,6 +2442,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
 
        if (written > 0) {
                pos += written;
+               iov_iter_advance(from, written);
                if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
                        i_size_write(inode, pos);
                        mark_inode_dirty(inode);
@@ -2638,11 +2645,10 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (unlikely(file->f_flags & O_DIRECT)) {
                loff_t endbyte;
 
-               written = generic_file_direct_write(iocb, iov, &from.nr_segs, pos,
+               written = generic_file_direct_write(iocb, &from, pos,
                                                        count, ocount);
                if (written < 0 || written == count)
                        goto out;
-               iov_iter_advance(&from, written);
 
                /*
                 * direct-io write to a hole: fall through to buffered I/O
This page took 0.03995 seconds and 4 git commands to generate.