From: Nate Diller <nate.diller@gmail.com>
To: Andrew Morton <akpm@osdl.org>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christoph Hellwig <hch@infradead.org>,
Roman Zippel <zippel@linux-m68k.org>,
Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>,
David Woodhouse <dwmw2@infradead.org>,
Dave Kleikamp <shaggy@austin.ibm.com>,
Anton Altaparmakov <aia21@cantab.net>,
Evgeniy Dushistov <dushistov@mail.ru>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
reiserfs-dev@namesys.com
Subject: [PATCH 2/17] fs: introduce new read_cache_page interface
Date: Wed, 11 Apr 2007 19:49:38 -0700 [thread overview]
Message-ID: <20070412024938.27380.66967.patchbomb.py@localhost> (raw)
In-Reply-To: <20070412024938.27380.54538.patchbomb.py@localhost>
Export a single version of read_cache_page, which returns with a locked,
Uptodate page or a synchronous error, and use inline helper functions to
replicate the old behavior. Also, introduce new helper functions for the
most common file system uses, which include kmapping the page, as well as
needing to keep the page locked. These changes collectively eliminate a
substantial amount of private fs logic in favor of generic code.
It also simplifies filemap.c significantly, by assuming that callers want
synchronous behavior, which is true for all callers anyway except one.
Signed-off-by: Nate Diller <nate.diller@gmail.com>
---
diff -urpN -X dontdiff linux-2.6.21-rc6-mm1/include/linux/pagemap.h linux-2.6.21-rc6-mm1-test/include/linux/pagemap.h
--- linux-2.6.21-rc6-mm1/include/linux/pagemap.h 2007-04-11 14:22:19.000000000 -0700
+++ linux-2.6.21-rc6-mm1-test/include/linux/pagemap.h 2007-04-11 14:29:31.000000000 -0700
@@ -108,21 +108,30 @@ static inline struct page *grab_cache_pa
extern struct page * grab_cache_page_nowait(struct address_space *mapping,
unsigned long index);
-extern struct page * read_cache_page_async(struct address_space *mapping,
- unsigned long index, filler_t *filler,
- void *data);
-extern struct page * read_cache_page(struct address_space *mapping,
+extern struct page *__read_cache_page(struct address_space *mapping,
unsigned long index, filler_t *filler,
void *data);
extern int read_cache_pages(struct address_space *mapping,
struct list_head *pages, filler_t *filler, void *data);
-static inline struct page *read_mapping_page_async(
- struct address_space *mapping,
+void fastcall unlock_page(struct page *page);
+static inline struct page *read_cache_page(struct address_space *mapping,
+ unsigned long index, filler_t *filler,
+ void *data)
+{
+ struct page *page;
+
+ page = __read_cache_page(mapping, index, filler, data);
+ if (!IS_ERR(page))
+ unlock_page(page);
+ return page;
+}
+
+static inline struct page *__read_mapping_page(struct address_space *mapping,
unsigned long index, void *data)
{
filler_t *filler = (filler_t *)mapping->a_ops->readpage;
- return read_cache_page_async(mapping, index, filler, data);
+ return __read_cache_page(mapping, index, filler, data);
}
static inline struct page *read_mapping_page(struct address_space *mapping,
@@ -132,6 +141,36 @@ static inline struct page *read_mapping_
return read_cache_page(mapping, index, filler, data);
}
+static inline struct page *__read_kmap_page(struct address_space *mapping,
+ unsigned long index)
+{
+ struct page *page = __read_mapping_page(mapping, index, NULL);
+ if (!IS_ERR(page))
+ kmap(page);
+ return page;
+}
+
+static inline struct page *read_kmap_page(struct address_space *mapping,
+ unsigned long index)
+{
+ struct page *page = read_mapping_page(mapping, index, NULL);
+ if (!IS_ERR(page))
+ kmap(page);
+ return page;
+}
+
+static inline void put_kmapped_page(struct page *page)
+{
+ kunmap(page);
+ page_cache_release(page);
+}
+
+static inline void put_locked_page(struct page *page)
+{
+ unlock_page(page);
+ put_kmapped_page(page);
+}
+
int add_to_page_cache(struct page *page, struct address_space *mapping,
unsigned long index, gfp_t gfp_mask);
int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
diff -urpN -X dontdiff linux-2.6.21-rc6-mm1/mm/filemap.c linux-2.6.21-rc6-mm1-test/mm/filemap.c
--- linux-2.6.21-rc6-mm1/mm/filemap.c 2007-04-11 14:26:42.000000000 -0700
+++ linux-2.6.21-rc6-mm1-test/mm/filemap.c 2007-04-10 21:46:03.000000000 -0700
@@ -1600,115 +1600,53 @@ int generic_file_readonly_mmap(struct fi
EXPORT_SYMBOL(generic_file_mmap);
EXPORT_SYMBOL(generic_file_readonly_mmap);
-static struct page *__read_cache_page(struct address_space *mapping,
- unsigned long index,
- int (*filler)(void *,struct page*),
- void *data)
-{
- struct page *page, *cached_page = NULL;
- int err;
-repeat:
- page = find_get_page(mapping, index);
- if (!page) {
- if (!cached_page) {
- cached_page = page_cache_alloc_cold(mapping);
- if (!cached_page)
- return ERR_PTR(-ENOMEM);
- }
- err = add_to_page_cache_lru(cached_page, mapping,
- index, GFP_KERNEL);
- if (err == -EEXIST)
- goto repeat;
- if (err < 0) {
- /* Presumably ENOMEM for radix tree node */
- page_cache_release(cached_page);
- return ERR_PTR(err);
- }
- page = cached_page;
- cached_page = NULL;
- err = filler(data, page);
- if (err < 0) {
- page_cache_release(page);
- page = ERR_PTR(err);
- }
- }
- if (cached_page)
- page_cache_release(cached_page);
- return page;
-}
-
-/*
- * Same as read_cache_page, but don't wait for page to become unlocked
- * after submitting it to the filler.
+/**
+ * __read_cache_page - read into page cache, fill it if needed
+ * @mapping: the page's address_space
+ * @index: the page index
+ * @filler: function to perform the read
+ * @data: destination for read data
+ *
+ * Read into the page cache. If a page already exists, and PageUptodate() is
+ * not set, try to fill the page then wait for I/O.
+ *
+ * Returns a locked, uptodate page, or an error.
*/
-struct page *read_cache_page_async(struct address_space *mapping,
+struct page *__read_cache_page(struct address_space *mapping,
unsigned long index,
int (*filler)(void *,struct page*),
void *data)
{
struct page *page;
+ int gfp_mask = mapping_gfp_mask(mapping)|__GFP_COLD;
int err;
-
-retry:
- page = __read_cache_page(mapping, index, filler, data);
- if (IS_ERR(page))
- goto out;
+repeat:
+ page = find_or_create_page(mapping, index, gfp_mask);
mark_page_accessed(page);
if (PageUptodate(page))
- goto out;
+ return page;
- lock_page(page);
- if (!page->mapping) {
- unlock_page(page);
- page_cache_release(page);
- goto retry;
- }
- if (PageUptodate(page)) {
- unlock_page(page);
- goto out;
- }
err = filler(data, page);
if (err < 0) {
page_cache_release(page);
- page = ERR_PTR(err);
+ return ERR_PTR(err);
}
- out:
- mark_page_accessed(page);
- return page;
-}
-EXPORT_SYMBOL(read_cache_page_async);
-/**
- * read_cache_page - read into page cache, fill it if needed
- * @mapping: the page's address_space
- * @index: the page index
- * @filler: function to perform the read
- * @data: destination for read data
- *
- * Read into the page cache. If a page already exists, and PageUptodate() is
- * not set, try to fill the page then wait for it to become unlocked.
- *
- * If the page does not get brought uptodate, return -EIO.
- */
-struct page *read_cache_page(struct address_space *mapping,
- unsigned long index,
- int (*filler)(void *,struct page*),
- void *data)
-{
- struct page *page;
+ lock_page(page);
+ if (PageUptodate(page))
+ return page;
- page = read_cache_page_async(mapping, index, filler, data);
- if (IS_ERR(page))
- goto out;
- wait_on_page_locked(page);
- if (!PageUptodate(page)) {
+ if (!page->mapping) {
+ unlock_page(page);
page_cache_release(page);
- page = ERR_PTR(-EIO);
+ goto repeat;
}
- out:
- return page;
+
+ unlock_page(page);
+ page_cache_release(page);
+ return ERR_PTR(-EIO);
}
-EXPORT_SYMBOL(read_cache_page);
+EXPORT_SYMBOL(__read_cache_page);
/*
* If the page was newly created, increment its refcount and add it to the
next prev parent reply other threads:[~2007-04-12 2:51 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-12 2:49 [PATCH 0/17] fs: cleanup single page synchronous read interface Nate Diller
2007-04-12 2:49 ` [PATCH 14/17] reiserfs: convert reiserfs_get_page to read_kmap_page Nate Diller
2007-04-12 2:49 ` [PATCH 16/17] ufs: convert ufs_get_page " Nate Diller
2007-04-12 2:49 ` [PATCH 10/17] mtd: convert page_read " Nate Diller
2007-04-12 2:49 ` [PATCH 8/17] jfs: use locking read_mapping_page Nate Diller
2007-04-12 2:49 ` [PATCH 11/17] ntfs: convert ntfs_map_page to read_kmap_page Nate Diller
2007-04-12 2:49 ` [PATCH 13/17] reiser4: remove redundant read_mapping_page error checks Nate Diller
2007-04-12 2:49 ` [PATCH 1/17] cramfs: use read_mapping_page Nate Diller
2007-04-12 9:54 ` Christoph Hellwig
2007-04-12 11:26 ` Roman Zippel
2007-04-12 18:36 ` Nate Diller
2007-04-12 2:49 ` [PATCH 15/17] sysv: convert dir_get_page to read_kmap_page Nate Diller
2007-04-12 2:49 ` [PATCH 5/17] hfsplus: remove redundant read_mapping_page error check Nate Diller
2007-04-12 2:49 ` [PATCH 17/17] vxfs: convert vxfs_get_page to read_kmap_page Nate Diller
2007-04-12 2:49 ` [PATCH 6/17] hfs: remove redundant read_mapping_page error check Nate Diller
2007-04-12 2:49 ` [PATCH 4/17] ext2: convert ext2_get_page to read_kmap_page Nate Diller
2007-04-12 2:49 ` [PATCH 3/17] afs: convert afs_dir_get_page " Nate Diller
2007-04-12 10:58 ` David Howells
2007-04-12 18:23 ` Nate Diller
2007-04-12 18:57 ` David Howells
2007-04-12 19:21 ` Andrew Morton
2007-04-12 19:29 ` David Howells
2007-07-16 6:05 ` Drop patch update-isdn-tree-to-use-pci_get_device.patch from -mm tree Surya Prabhakar N
2007-04-12 19:27 ` [PATCH 3/17] afs: convert afs_dir_get_page to read_kmap_page Nate Diller
2007-04-12 19:43 ` David Howells
2007-04-12 2:49 ` [PATCH 9/17] minix: convert dir_get_page " Nate Diller
2007-04-12 2:49 ` Nate Diller [this message]
2007-04-12 2:49 ` [PATCH 12/17] partition: remove redundant read_mapping_page error checks Nate Diller
2007-04-12 2:49 ` [PATCH 7/17] jffs2: convert jffs2_gc_fetch_page to read_cache_page Nate Diller
2007-04-12 11:40 ` Phillip Lougher
2007-04-12 18:29 ` Nate Diller
2007-04-12 18:53 ` Phillip Lougher
2007-04-15 10:52 ` David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070412024938.27380.66967.patchbomb.py@localhost \
--to=nate.diller@gmail.com \
--cc=aia21@cantab.net \
--cc=akpm@osdl.org \
--cc=dushistov@mail.ru \
--cc=dwmw2@infradead.org \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mikulas@artax.karlin.mff.cuni.cz \
--cc=reiserfs-dev@namesys.com \
--cc=shaggy@austin.ibm.com \
--cc=viro@zeniv.linux.org.uk \
--cc=zippel@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox