mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'folio-5.19' of git://git.infradead.org/users/willy/pagecache
Pull page cache updates from Matthew Wilcox:
- Appoint myself page cache maintainer
- Fix how scsicam uses the page cache
- Use the memalloc_nofs_save() API to replace AOP_FLAG_NOFS
- Remove the AOP flags entirely
- Remove pagecache_write_begin() and pagecache_write_end()
- Documentation updates
- Convert several address_space operations to use folios:
- is_dirty_writeback
- readpage becomes read_folio
- releasepage becomes release_folio
- freepage becomes free_folio
- Change filler_t to require a struct file pointer be the first
argument like ->read_folio
* tag 'folio-5.19' of git://git.infradead.org/users/willy/pagecache: (107 commits)
nilfs2: Fix some kernel-doc comments
Appoint myself page cache maintainer
fs: Remove aops->freepage
secretmem: Convert to free_folio
nfs: Convert to free_folio
orangefs: Convert to free_folio
fs: Add free_folio address space operation
fs: Convert drop_buffers() to use a folio
fs: Change try_to_free_buffers() to take a folio
jbd2: Convert release_buffer_page() to use a folio
jbd2: Convert jbd2_journal_try_to_free_buffers to take a folio
reiserfs: Convert release_buffer_page() to use a folio
fs: Remove last vestiges of releasepage
ubifs: Convert to release_folio
reiserfs: Convert to release_folio
orangefs: Convert to release_folio
ocfs2: Convert to release_folio
nilfs2: Remove comment about releasepage
nfs: Convert to release_folio
jfs: Convert to release_folio
...
This commit is contained in:
@@ -433,11 +433,11 @@ has done a write and then the page it wrote from has been released by the VM,
|
||||
after which it *has* to look in the cache.
|
||||
|
||||
To inform fscache that a page might now be in the cache, the following function
|
||||
should be called from the ``releasepage`` address space op::
|
||||
should be called from the ``release_folio`` address space op::
|
||||
|
||||
void fscache_note_page_release(struct fscache_cookie *cookie);
|
||||
|
||||
if the page has been released (ie. releasepage returned true).
|
||||
if the page has been released (ie. release_folio returned true).
|
||||
|
||||
Page release and page invalidation should also wait for any mark left on the
|
||||
page to say that a DIO write is underway from that page::
|
||||
|
||||
@@ -1256,7 +1256,7 @@ inline encryption hardware will encrypt/decrypt the file contents.
|
||||
When inline encryption isn't used, filesystems must encrypt/decrypt
|
||||
the file contents themselves, as described below:
|
||||
|
||||
For the read path (->readpage()) of regular files, filesystems can
|
||||
For the read path (->read_folio()) of regular files, filesystems can
|
||||
read the ciphertext into the page cache and decrypt it in-place. The
|
||||
page lock must be held until decryption has finished, to prevent the
|
||||
page from becoming visible to userspace prematurely.
|
||||
|
||||
@@ -559,7 +559,7 @@ already verified). Below, we describe how filesystems implement this.
|
||||
Pagecache
|
||||
~~~~~~~~~
|
||||
|
||||
For filesystems using Linux's pagecache, the ``->readpage()`` and
|
||||
For filesystems using Linux's pagecache, the ``->read_folio()`` and
|
||||
``->readahead()`` methods must be modified to verify pages before they
|
||||
are marked Uptodate. Merely hooking ``->read_iter()`` would be
|
||||
insufficient, since ``->read_iter()`` is not used for memory maps.
|
||||
|
||||
@@ -237,20 +237,20 @@ address_space_operations
|
||||
prototypes::
|
||||
|
||||
int (*writepage)(struct page *page, struct writeback_control *wbc);
|
||||
int (*readpage)(struct file *, struct page *);
|
||||
int (*read_folio)(struct file *, struct folio *);
|
||||
int (*writepages)(struct address_space *, struct writeback_control *);
|
||||
bool (*dirty_folio)(struct address_space *, struct folio *folio);
|
||||
void (*readahead)(struct readahead_control *);
|
||||
int (*write_begin)(struct file *, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata);
|
||||
int (*write_end)(struct file *, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned copied,
|
||||
struct page *page, void *fsdata);
|
||||
sector_t (*bmap)(struct address_space *, sector_t);
|
||||
void (*invalidate_folio) (struct folio *, size_t start, size_t len);
|
||||
int (*releasepage) (struct page *, int);
|
||||
void (*freepage)(struct page *);
|
||||
bool (*release_folio)(struct folio *, gfp_t);
|
||||
void (*free_folio)(struct folio *);
|
||||
int (*direct_IO)(struct kiocb *, struct iov_iter *iter);
|
||||
bool (*isolate_page) (struct page *, isolate_mode_t);
|
||||
int (*migratepage)(struct address_space *, struct page *, struct page *);
|
||||
@@ -262,22 +262,22 @@ prototypes::
|
||||
int (*swap_deactivate)(struct file *);
|
||||
|
||||
locking rules:
|
||||
All except dirty_folio and freepage may block
|
||||
All except dirty_folio and free_folio may block
|
||||
|
||||
====================== ======================== ========= ===============
|
||||
ops PageLocked(page) i_rwsem invalidate_lock
|
||||
ops folio locked i_rwsem invalidate_lock
|
||||
====================== ======================== ========= ===============
|
||||
writepage: yes, unlocks (see below)
|
||||
readpage: yes, unlocks shared
|
||||
read_folio: yes, unlocks shared
|
||||
writepages:
|
||||
dirty_folio maybe
|
||||
dirty_folio: maybe
|
||||
readahead: yes, unlocks shared
|
||||
write_begin: locks the page exclusive
|
||||
write_end: yes, unlocks exclusive
|
||||
bmap:
|
||||
invalidate_folio: yes exclusive
|
||||
releasepage: yes
|
||||
freepage: yes
|
||||
release_folio: yes
|
||||
free_folio: yes
|
||||
direct_IO:
|
||||
isolate_page: yes
|
||||
migratepage: yes (both)
|
||||
@@ -289,13 +289,13 @@ swap_activate: no
|
||||
swap_deactivate: no
|
||||
====================== ======================== ========= ===============
|
||||
|
||||
->write_begin(), ->write_end() and ->readpage() may be called from
|
||||
->write_begin(), ->write_end() and ->read_folio() may be called from
|
||||
the request handler (/dev/loop).
|
||||
|
||||
->readpage() unlocks the page, either synchronously or via I/O
|
||||
->read_folio() unlocks the folio, either synchronously or via I/O
|
||||
completion.
|
||||
|
||||
->readahead() unlocks the pages that I/O is attempted on like ->readpage().
|
||||
->readahead() unlocks the folios that I/O is attempted on like ->read_folio().
|
||||
|
||||
->writepage() is used for two purposes: for "memory cleansing" and for
|
||||
"sync". These are quite different operations and the behaviour may differ
|
||||
@@ -372,12 +372,12 @@ invalidate_lock before invalidating page cache in truncate / hole punch
|
||||
path (and thus calling into ->invalidate_folio) to block races between page
|
||||
cache invalidation and page cache filling functions (fault, read, ...).
|
||||
|
||||
->releasepage() is called when the kernel is about to try to drop the
|
||||
buffers from the page in preparation for freeing it. It returns zero to
|
||||
indicate that the buffers are (or may be) freeable. If ->releasepage is zero,
|
||||
the kernel assumes that the fs has no private interest in the buffers.
|
||||
->release_folio() is called when the kernel is about to try to drop the
|
||||
buffers from the folio in preparation for freeing it. It returns false to
|
||||
indicate that the buffers are (or may be) freeable. If ->release_folio is
|
||||
NULL, the kernel assumes that the fs has no private interest in the buffers.
|
||||
|
||||
->freepage() is called when the kernel is done dropping the page
|
||||
->free_folio() is called when the kernel has dropped the folio
|
||||
from the page cache.
|
||||
|
||||
->launder_folio() may be called prior to releasing a folio if
|
||||
|
||||
@@ -96,7 +96,7 @@ attached to an inode (or NULL if fscache is disabled)::
|
||||
Buffered Read Helpers
|
||||
=====================
|
||||
|
||||
The library provides a set of read helpers that handle the ->readpage(),
|
||||
The library provides a set of read helpers that handle the ->read_folio(),
|
||||
->readahead() and much of the ->write_begin() VM operations and translate them
|
||||
into a common call framework.
|
||||
|
||||
@@ -136,20 +136,19 @@ Read Helper Functions
|
||||
Three read helpers are provided::
|
||||
|
||||
void netfs_readahead(struct readahead_control *ractl);
|
||||
int netfs_readpage(struct file *file,
|
||||
struct page *page);
|
||||
int netfs_read_folio(struct file *file,
|
||||
struct folio *folio);
|
||||
int netfs_write_begin(struct file *file,
|
||||
struct address_space *mapping,
|
||||
loff_t pos,
|
||||
unsigned int len,
|
||||
unsigned int flags,
|
||||
struct folio **_folio,
|
||||
void **_fsdata);
|
||||
|
||||
Each corresponds to a VM address space operation. These operations use the
|
||||
state in the per-inode context.
|
||||
|
||||
For ->readahead() and ->readpage(), the network filesystem just point directly
|
||||
For ->readahead() and ->read_folio(), the network filesystem just point directly
|
||||
at the corresponding read helper; whereas for ->write_begin(), it may be a
|
||||
little more complicated as the network filesystem might want to flush
|
||||
conflicting writes or track dirty data and needs to put the acquired folio if
|
||||
|
||||
@@ -624,7 +624,7 @@ any symlink that might use page_follow_link_light/page_put_link() must
|
||||
have inode_nohighmem(inode) called before anything might start playing with
|
||||
its pagecache. No highmem pages should end up in the pagecache of such
|
||||
symlinks. That includes any preseeding that might be done during symlink
|
||||
creation. __page_symlink() will honour the mapping gfp flags, so once
|
||||
creation. page_symlink() will honour the mapping gfp flags, so once
|
||||
you've done inode_nohighmem() it's safe to use, but if you allocate and
|
||||
insert the page manually, make sure to use the right gfp flags.
|
||||
|
||||
|
||||
@@ -620,9 +620,9 @@ Writeback.
|
||||
The first can be used independently to the others. The VM can try to
|
||||
either write dirty pages in order to clean them, or release clean pages
|
||||
in order to reuse them. To do this it can call the ->writepage method
|
||||
on dirty pages, and ->releasepage on clean pages with PagePrivate set.
|
||||
Clean pages without PagePrivate and with no external references will be
|
||||
released without notice being given to the address_space.
|
||||
on dirty pages, and ->release_folio on clean folios with the private
|
||||
flag set. Clean pages without PagePrivate and with no external references
|
||||
will be released without notice being given to the address_space.
|
||||
|
||||
To achieve this functionality, pages need to be placed on an LRU with
|
||||
lru_cache_add and mark_page_active needs to be called whenever the page
|
||||
@@ -656,7 +656,7 @@ by memory-mapping the page. Data is written into the address space by
|
||||
the application, and then written-back to storage typically in whole
|
||||
pages, however the address_space has finer control of write sizes.
|
||||
|
||||
The read process essentially only requires 'readpage'. The write
|
||||
The read process essentially only requires 'read_folio'. The write
|
||||
process is more complicated and uses write_begin/write_end or
|
||||
dirty_folio to write data into the address_space, and writepage and
|
||||
writepages to writeback data to storage.
|
||||
@@ -722,20 +722,20 @@ cache in your filesystem. The following members are defined:
|
||||
|
||||
struct address_space_operations {
|
||||
int (*writepage)(struct page *page, struct writeback_control *wbc);
|
||||
int (*readpage)(struct file *, struct page *);
|
||||
int (*read_folio)(struct file *, struct folio *);
|
||||
int (*writepages)(struct address_space *, struct writeback_control *);
|
||||
bool (*dirty_folio)(struct address_space *, struct folio *);
|
||||
void (*readahead)(struct readahead_control *);
|
||||
int (*write_begin)(struct file *, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata);
|
||||
int (*write_end)(struct file *, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned copied,
|
||||
struct page *page, void *fsdata);
|
||||
sector_t (*bmap)(struct address_space *, sector_t);
|
||||
void (*invalidate_folio) (struct folio *, size_t start, size_t len);
|
||||
int (*releasepage) (struct page *, int);
|
||||
void (*freepage)(struct page *);
|
||||
bool (*release_folio)(struct folio *, gfp_t);
|
||||
void (*free_folio)(struct folio *);
|
||||
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
|
||||
/* isolate a page for migration */
|
||||
bool (*isolate_page) (struct page *, isolate_mode_t);
|
||||
@@ -747,7 +747,7 @@ cache in your filesystem. The following members are defined:
|
||||
|
||||
bool (*is_partially_uptodate) (struct folio *, size_t from,
|
||||
size_t count);
|
||||
void (*is_dirty_writeback) (struct page *, bool *, bool *);
|
||||
void (*is_dirty_writeback)(struct folio *, bool *, bool *);
|
||||
int (*error_remove_page) (struct mapping *mapping, struct page *page);
|
||||
int (*swap_activate)(struct file *);
|
||||
int (*swap_deactivate)(struct file *);
|
||||
@@ -772,14 +772,14 @@ cache in your filesystem. The following members are defined:
|
||||
|
||||
See the file "Locking" for more details.
|
||||
|
||||
``readpage``
|
||||
called by the VM to read a page from backing store. The page
|
||||
will be Locked when readpage is called, and should be unlocked
|
||||
and marked uptodate once the read completes. If ->readpage
|
||||
discovers that it needs to unlock the page for some reason, it
|
||||
can do so, and then return AOP_TRUNCATED_PAGE. In this case,
|
||||
the page will be relocated, relocked and if that all succeeds,
|
||||
->readpage will be called again.
|
||||
``read_folio``
|
||||
called by the VM to read a folio from backing store. The folio
|
||||
will be locked when read_folio is called, and should be unlocked
|
||||
and marked uptodate once the read completes. If ->read_folio
|
||||
discovers that it cannot perform the I/O at this time, it can
|
||||
unlock the folio and return AOP_TRUNCATED_PAGE. In this case,
|
||||
the folio will be looked up again, relocked and if that all succeeds,
|
||||
->read_folio will be called again.
|
||||
|
||||
``writepages``
|
||||
called by the VM to write out pages associated with the
|
||||
@@ -832,9 +832,6 @@ cache in your filesystem. The following members are defined:
|
||||
passed to write_begin is greater than the number of bytes copied
|
||||
into the page).
|
||||
|
||||
flags is a field for AOP_FLAG_xxx flags, described in
|
||||
include/linux/fs.h.
|
||||
|
||||
A void * may be returned in fsdata, which then gets passed into
|
||||
write_end.
|
||||
|
||||
@@ -867,36 +864,35 @@ cache in your filesystem. The following members are defined:
|
||||
address space. This generally corresponds to either a
|
||||
truncation, punch hole or a complete invalidation of the address
|
||||
space (in the latter case 'offset' will always be 0 and 'length'
|
||||
will be folio_size()). Any private data associated with the page
|
||||
will be folio_size()). Any private data associated with the folio
|
||||
should be updated to reflect this truncation. If offset is 0
|
||||
and length is folio_size(), then the private data should be
|
||||
released, because the page must be able to be completely
|
||||
discarded. This may be done by calling the ->releasepage
|
||||
released, because the folio must be able to be completely
|
||||
discarded. This may be done by calling the ->release_folio
|
||||
function, but in this case the release MUST succeed.
|
||||
|
||||
``releasepage``
|
||||
releasepage is called on PagePrivate pages to indicate that the
|
||||
page should be freed if possible. ->releasepage should remove
|
||||
any private data from the page and clear the PagePrivate flag.
|
||||
If releasepage() fails for some reason, it must indicate failure
|
||||
with a 0 return value. releasepage() is used in two distinct
|
||||
though related cases. The first is when the VM finds a clean
|
||||
page with no active users and wants to make it a free page. If
|
||||
->releasepage succeeds, the page will be removed from the
|
||||
address_space and become free.
|
||||
``release_folio``
|
||||
release_folio is called on folios with private data to tell the
|
||||
filesystem that the folio is about to be freed. ->release_folio
|
||||
should remove any private data from the folio and clear the
|
||||
private flag. If release_folio() fails, it should return false.
|
||||
release_folio() is used in two distinct though related cases.
|
||||
The first is when the VM wants to free a clean folio with no
|
||||
active users. If ->release_folio succeeds, the folio will be
|
||||
removed from the address_space and be freed.
|
||||
|
||||
The second case is when a request has been made to invalidate
|
||||
some or all pages in an address_space. This can happen through
|
||||
the fadvise(POSIX_FADV_DONTNEED) system call or by the
|
||||
filesystem explicitly requesting it as nfs and 9fs do (when they
|
||||
some or all folios in an address_space. This can happen
|
||||
through the fadvise(POSIX_FADV_DONTNEED) system call or by the
|
||||
filesystem explicitly requesting it as nfs and 9p do (when they
|
||||
believe the cache may be out of date with storage) by calling
|
||||
invalidate_inode_pages2(). If the filesystem makes such a call,
|
||||
and needs to be certain that all pages are invalidated, then its
|
||||
releasepage will need to ensure this. Possibly it can clear the
|
||||
PageUptodate bit if it cannot free private data yet.
|
||||
and needs to be certain that all folios are invalidated, then
|
||||
its release_folio will need to ensure this. Possibly it can
|
||||
clear the uptodate flag if it cannot free private data yet.
|
||||
|
||||
``freepage``
|
||||
freepage is called once the page is no longer visible in the
|
||||
``free_folio``
|
||||
free_folio is called once the folio is no longer visible in the
|
||||
page cache in order to allow the cleanup of any private data.
|
||||
Since it may be called by the memory reclaimer, it should not
|
||||
assume that the original address_space mapping still exists, and
|
||||
@@ -935,14 +931,14 @@ cache in your filesystem. The following members are defined:
|
||||
without needing I/O to bring the whole page up to date.
|
||||
|
||||
``is_dirty_writeback``
|
||||
Called by the VM when attempting to reclaim a page. The VM uses
|
||||
Called by the VM when attempting to reclaim a folio. The VM uses
|
||||
dirty and writeback information to determine if it needs to
|
||||
stall to allow flushers a chance to complete some IO.
|
||||
Ordinarily it can use PageDirty and PageWriteback but some
|
||||
filesystems have more complex state (unstable pages in NFS
|
||||
Ordinarily it can use folio_test_dirty and folio_test_writeback but
|
||||
some filesystems have more complex state (unstable folios in NFS
|
||||
prevent reclaim) or do not set those flags due to locking
|
||||
problems. This callback allows a filesystem to indicate to the
|
||||
VM if a page should be treated as dirty or writeback for the
|
||||
VM if a folio should be treated as dirty or writeback for the
|
||||
purposes of stalling.
|
||||
|
||||
``error_remove_page``
|
||||
|
||||
13
MAINTAINERS
13
MAINTAINERS
@@ -14878,6 +14878,19 @@ F: Documentation/core-api/padata.rst
|
||||
F: include/linux/padata.h
|
||||
F: kernel/padata.c
|
||||
|
||||
PAGE CACHE
|
||||
M: Matthew Wilcox (Oracle) <willy@infradead.org>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.infradead.org/users/willy/pagecache.git
|
||||
F: Documentation/filesystems/locking.rst
|
||||
F: Documentation/filesystems/vfs.rst
|
||||
F: include/linux/pagemap.h
|
||||
F: mm/filemap.c
|
||||
F: mm/page-writeback.c
|
||||
F: mm/readahead.c
|
||||
F: mm/truncate.c
|
||||
|
||||
PAGE POOL
|
||||
M: Jesper Dangaard Brouer <hawk@kernel.org>
|
||||
M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
|
||||
|
||||
12
block/fops.c
12
block/fops.c
@@ -372,9 +372,9 @@ static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
|
||||
return block_write_full_page(page, blkdev_get_block, wbc);
|
||||
}
|
||||
|
||||
static int blkdev_readpage(struct file * file, struct page * page)
|
||||
static int blkdev_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
return block_read_full_page(page, blkdev_get_block);
|
||||
return block_read_full_folio(folio, blkdev_get_block);
|
||||
}
|
||||
|
||||
static void blkdev_readahead(struct readahead_control *rac)
|
||||
@@ -383,11 +383,9 @@ static void blkdev_readahead(struct readahead_control *rac)
|
||||
}
|
||||
|
||||
static int blkdev_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags, struct page **pagep,
|
||||
void **fsdata)
|
||||
loff_t pos, unsigned len, struct page **pagep, void **fsdata)
|
||||
{
|
||||
return block_write_begin(mapping, pos, len, flags, pagep,
|
||||
blkdev_get_block);
|
||||
return block_write_begin(mapping, pos, len, pagep, blkdev_get_block);
|
||||
}
|
||||
|
||||
static int blkdev_write_end(struct file *file, struct address_space *mapping,
|
||||
@@ -412,7 +410,7 @@ static int blkdev_writepages(struct address_space *mapping,
|
||||
const struct address_space_operations def_blk_aops = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.readpage = blkdev_readpage,
|
||||
.read_folio = blkdev_read_folio,
|
||||
.readahead = blkdev_readahead,
|
||||
.writepage = blkdev_writepage,
|
||||
.write_begin = blkdev_write_begin,
|
||||
|
||||
@@ -408,6 +408,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
|
||||
const struct drm_i915_gem_pwrite *arg)
|
||||
{
|
||||
struct address_space *mapping = obj->base.filp->f_mapping;
|
||||
const struct address_space_operations *aops = mapping->a_ops;
|
||||
char __user *user_data = u64_to_user_ptr(arg->data_ptr);
|
||||
u64 remain, offset;
|
||||
unsigned int pg;
|
||||
@@ -465,9 +466,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pagecache_write_begin(obj->base.filp, mapping,
|
||||
offset, len, 0,
|
||||
&page, &data);
|
||||
err = aops->write_begin(obj->base.filp, mapping, offset, len,
|
||||
&page, &data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -477,9 +477,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
|
||||
len);
|
||||
kunmap_atomic(vaddr);
|
||||
|
||||
err = pagecache_write_end(obj->base.filp, mapping,
|
||||
offset, len, len - unwritten,
|
||||
page, data);
|
||||
err = aops->write_end(obj->base.filp, mapping, offset, len,
|
||||
len - unwritten, page, data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -622,6 +621,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct file *file;
|
||||
const struct address_space_operations *aops;
|
||||
resource_size_t offset;
|
||||
int err;
|
||||
|
||||
@@ -633,15 +633,15 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
|
||||
GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU);
|
||||
|
||||
file = obj->base.filp;
|
||||
aops = file->f_mapping->a_ops;
|
||||
offset = 0;
|
||||
do {
|
||||
unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
|
||||
struct page *page;
|
||||
void *pgdata, *vaddr;
|
||||
|
||||
err = pagecache_write_begin(file, file->f_mapping,
|
||||
offset, len, 0,
|
||||
&page, &pgdata);
|
||||
err = aops->write_begin(file, file->f_mapping, offset, len,
|
||||
&page, &pgdata);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -649,9 +649,8 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
|
||||
memcpy(vaddr, data, len);
|
||||
kunmap(page);
|
||||
|
||||
err = pagecache_write_end(file, file->f_mapping,
|
||||
offset, len, len,
|
||||
page, pgdata);
|
||||
err = aops->write_end(file, file->f_mapping, offset, len, len,
|
||||
page, pgdata);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
|
||||
@@ -34,15 +34,14 @@ unsigned char *scsi_bios_ptable(struct block_device *dev)
|
||||
{
|
||||
struct address_space *mapping = bdev_whole(dev)->bd_inode->i_mapping;
|
||||
unsigned char *res = NULL;
|
||||
struct page *page;
|
||||
struct folio *folio;
|
||||
|
||||
page = read_mapping_page(mapping, 0, NULL);
|
||||
if (IS_ERR(page))
|
||||
folio = read_mapping_folio(mapping, 0, NULL);
|
||||
if (IS_ERR(folio))
|
||||
return NULL;
|
||||
|
||||
if (!PageError(page))
|
||||
res = kmemdup(page_address(page) + 0x1be, 66, GFP_KERNEL);
|
||||
put_page(page);
|
||||
res = kmemdup(folio_address(folio) + 0x1be, 66, GFP_KERNEL);
|
||||
folio_put(folio);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_bios_ptable);
|
||||
|
||||
@@ -100,29 +100,28 @@ const struct netfs_request_ops v9fs_req_ops = {
|
||||
};
|
||||
|
||||
/**
|
||||
* v9fs_release_page - release the private state associated with a page
|
||||
* @page: The page to be released
|
||||
* v9fs_release_folio - release the private state associated with a folio
|
||||
* @folio: The folio to be released
|
||||
* @gfp: The caller's allocation restrictions
|
||||
*
|
||||
* Returns 1 if the page can be released, false otherwise.
|
||||
* Returns true if the page can be released, false otherwise.
|
||||
*/
|
||||
|
||||
static int v9fs_release_page(struct page *page, gfp_t gfp)
|
||||
static bool v9fs_release_folio(struct folio *folio, gfp_t gfp)
|
||||
{
|
||||
struct folio *folio = page_folio(page);
|
||||
struct inode *inode = folio_inode(folio);
|
||||
|
||||
if (folio_test_private(folio))
|
||||
return 0;
|
||||
return false;
|
||||
#ifdef CONFIG_9P_FSCACHE
|
||||
if (folio_test_fscache(folio)) {
|
||||
if (current_is_kswapd() || !(gfp & __GFP_FS))
|
||||
return 0;
|
||||
return false;
|
||||
folio_wait_fscache(folio);
|
||||
}
|
||||
#endif
|
||||
fscache_note_page_release(v9fs_inode_cookie(V9FS_I(inode)));
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void v9fs_invalidate_folio(struct folio *folio, size_t offset,
|
||||
@@ -260,7 +259,7 @@ v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
}
|
||||
|
||||
static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int flags,
|
||||
loff_t pos, unsigned int len,
|
||||
struct page **subpagep, void **fsdata)
|
||||
{
|
||||
int retval;
|
||||
@@ -275,7 +274,7 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
|
||||
* file. We need to do this before we get a lock on the page in case
|
||||
* there's more than one writer competing for the same cache block.
|
||||
*/
|
||||
retval = netfs_write_begin(filp, mapping, pos, len, flags, &folio, fsdata);
|
||||
retval = netfs_write_begin(filp, mapping, pos, len, &folio, fsdata);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -336,13 +335,13 @@ static bool v9fs_dirty_folio(struct address_space *mapping, struct folio *folio)
|
||||
#endif
|
||||
|
||||
const struct address_space_operations v9fs_addr_operations = {
|
||||
.readpage = netfs_readpage,
|
||||
.read_folio = netfs_read_folio,
|
||||
.readahead = netfs_readahead,
|
||||
.dirty_folio = v9fs_dirty_folio,
|
||||
.writepage = v9fs_vfs_writepage,
|
||||
.write_begin = v9fs_write_begin,
|
||||
.write_end = v9fs_write_end,
|
||||
.releasepage = v9fs_release_page,
|
||||
.release_folio = v9fs_release_folio,
|
||||
.invalidate_folio = v9fs_invalidate_folio,
|
||||
.launder_folio = v9fs_launder_folio,
|
||||
.direct_IO = v9fs_direct_IO,
|
||||
|
||||
@@ -38,9 +38,9 @@ static int adfs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
return block_write_full_page(page, adfs_get_block, wbc);
|
||||
}
|
||||
|
||||
static int adfs_readpage(struct file *file, struct page *page)
|
||||
static int adfs_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
return block_read_full_page(page, adfs_get_block);
|
||||
return block_read_full_folio(folio, adfs_get_block);
|
||||
}
|
||||
|
||||
static void adfs_write_failed(struct address_space *mapping, loff_t to)
|
||||
@@ -52,13 +52,13 @@ static void adfs_write_failed(struct address_space *mapping, loff_t to)
|
||||
}
|
||||
|
||||
static int adfs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*pagep = NULL;
|
||||
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
|
||||
adfs_get_block,
|
||||
&ADFS_I(mapping->host)->mmu_private);
|
||||
if (unlikely(ret))
|
||||
@@ -75,7 +75,7 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
|
||||
static const struct address_space_operations adfs_aops = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.readpage = adfs_readpage,
|
||||
.read_folio = adfs_read_folio,
|
||||
.writepage = adfs_writepage,
|
||||
.write_begin = adfs_write_begin,
|
||||
.write_end = generic_write_end,
|
||||
|
||||
@@ -375,9 +375,9 @@ static int affs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
return block_write_full_page(page, affs_get_block, wbc);
|
||||
}
|
||||
|
||||
static int affs_readpage(struct file *file, struct page *page)
|
||||
static int affs_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
return block_read_full_page(page, affs_get_block);
|
||||
return block_read_full_folio(folio, affs_get_block);
|
||||
}
|
||||
|
||||
static void affs_write_failed(struct address_space *mapping, loff_t to)
|
||||
@@ -414,13 +414,13 @@ affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
}
|
||||
|
||||
static int affs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*pagep = NULL;
|
||||
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
|
||||
affs_get_block,
|
||||
&AFFS_I(mapping->host)->mmu_private);
|
||||
if (unlikely(ret))
|
||||
@@ -455,7 +455,7 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
|
||||
const struct address_space_operations affs_aops = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.readpage = affs_readpage,
|
||||
.read_folio = affs_read_folio,
|
||||
.writepage = affs_writepage,
|
||||
.write_begin = affs_write_begin,
|
||||
.write_end = affs_write_end,
|
||||
@@ -629,8 +629,9 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
affs_readpage_ofs(struct file *file, struct page *page)
|
||||
affs_read_folio_ofs(struct file *file, struct folio *folio)
|
||||
{
|
||||
struct page *page = &folio->page;
|
||||
struct inode *inode = page->mapping->host;
|
||||
u32 to;
|
||||
int err;
|
||||
@@ -650,7 +651,7 @@ affs_readpage_ofs(struct file *file, struct page *page)
|
||||
}
|
||||
|
||||
static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
@@ -670,7 +671,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
|
||||
}
|
||||
|
||||
index = pos >> PAGE_SHIFT;
|
||||
page = grab_cache_page_write_begin(mapping, index, flags);
|
||||
page = grab_cache_page_write_begin(mapping, index);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
*pagep = page;
|
||||
@@ -837,7 +838,7 @@ err_bh:
|
||||
const struct address_space_operations affs_aops_ofs = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.readpage = affs_readpage_ofs,
|
||||
.read_folio = affs_read_folio_ofs,
|
||||
//.writepage = affs_writepage_ofs,
|
||||
.write_begin = affs_write_begin_ofs,
|
||||
.write_end = affs_write_end_ofs
|
||||
@@ -887,7 +888,7 @@ affs_truncate(struct inode *inode)
|
||||
loff_t isize = inode->i_size;
|
||||
int res;
|
||||
|
||||
res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, 0, &page, &fsdata);
|
||||
res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &page, &fsdata);
|
||||
if (!res)
|
||||
res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
|
||||
else
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
|
||||
#include "affs.h"
|
||||
|
||||
static int affs_symlink_readpage(struct file *file, struct page *page)
|
||||
static int affs_symlink_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
struct page *page = &folio->page;
|
||||
struct buffer_head *bh;
|
||||
struct inode *inode = page->mapping->host;
|
||||
char *link = page_address(page);
|
||||
@@ -67,7 +68,7 @@ fail:
|
||||
}
|
||||
|
||||
const struct address_space_operations affs_symlink_aops = {
|
||||
.readpage = affs_symlink_readpage,
|
||||
.read_folio = affs_symlink_read_folio,
|
||||
};
|
||||
|
||||
const struct inode_operations affs_symlink_inode_operations = {
|
||||
|
||||
@@ -41,7 +41,7 @@ static int afs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
static int afs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags);
|
||||
static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags);
|
||||
static bool afs_dir_release_folio(struct folio *folio, gfp_t gfp_flags);
|
||||
static void afs_dir_invalidate_folio(struct folio *folio, size_t offset,
|
||||
size_t length);
|
||||
|
||||
@@ -75,7 +75,7 @@ const struct inode_operations afs_dir_inode_operations = {
|
||||
|
||||
const struct address_space_operations afs_dir_aops = {
|
||||
.dirty_folio = afs_dir_dirty_folio,
|
||||
.releasepage = afs_dir_releasepage,
|
||||
.release_folio = afs_dir_release_folio,
|
||||
.invalidate_folio = afs_dir_invalidate_folio,
|
||||
};
|
||||
|
||||
@@ -2002,9 +2002,8 @@ error:
|
||||
* Release a directory folio and clean up its private state if it's not busy
|
||||
* - return true if the folio can now be released, false if not
|
||||
*/
|
||||
static int afs_dir_releasepage(struct page *subpage, gfp_t gfp_flags)
|
||||
static bool afs_dir_release_folio(struct folio *folio, gfp_t gfp_flags)
|
||||
{
|
||||
struct folio *folio = page_folio(subpage);
|
||||
struct afs_vnode *dvnode = AFS_FS_I(folio_inode(folio));
|
||||
|
||||
_enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, folio_index(folio));
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
#include "internal.h"
|
||||
|
||||
static int afs_file_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
static int afs_symlink_readpage(struct file *file, struct page *page);
|
||||
static int afs_symlink_read_folio(struct file *file, struct folio *folio);
|
||||
static void afs_invalidate_folio(struct folio *folio, size_t offset,
|
||||
size_t length);
|
||||
static int afs_releasepage(struct page *page, gfp_t gfp_flags);
|
||||
static bool afs_release_folio(struct folio *folio, gfp_t gfp_flags);
|
||||
|
||||
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter);
|
||||
static void afs_vm_open(struct vm_area_struct *area);
|
||||
@@ -50,11 +50,11 @@ const struct inode_operations afs_file_inode_operations = {
|
||||
};
|
||||
|
||||
const struct address_space_operations afs_file_aops = {
|
||||
.readpage = netfs_readpage,
|
||||
.read_folio = netfs_read_folio,
|
||||
.readahead = netfs_readahead,
|
||||
.dirty_folio = afs_dirty_folio,
|
||||
.launder_folio = afs_launder_folio,
|
||||
.releasepage = afs_releasepage,
|
||||
.release_folio = afs_release_folio,
|
||||
.invalidate_folio = afs_invalidate_folio,
|
||||
.write_begin = afs_write_begin,
|
||||
.write_end = afs_write_end,
|
||||
@@ -63,8 +63,8 @@ const struct address_space_operations afs_file_aops = {
|
||||
};
|
||||
|
||||
const struct address_space_operations afs_symlink_aops = {
|
||||
.readpage = afs_symlink_readpage,
|
||||
.releasepage = afs_releasepage,
|
||||
.read_folio = afs_symlink_read_folio,
|
||||
.release_folio = afs_release_folio,
|
||||
.invalidate_folio = afs_invalidate_folio,
|
||||
};
|
||||
|
||||
@@ -332,11 +332,10 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq)
|
||||
afs_put_read(fsreq);
|
||||
}
|
||||
|
||||
static int afs_symlink_readpage(struct file *file, struct page *page)
|
||||
static int afs_symlink_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
|
||||
struct afs_vnode *vnode = AFS_FS_I(folio->mapping->host);
|
||||
struct afs_read *fsreq;
|
||||
struct folio *folio = page_folio(page);
|
||||
int ret;
|
||||
|
||||
fsreq = afs_alloc_read(GFP_NOFS);
|
||||
@@ -347,13 +346,13 @@ static int afs_symlink_readpage(struct file *file, struct page *page)
|
||||
fsreq->len = folio_size(folio);
|
||||
fsreq->vnode = vnode;
|
||||
fsreq->iter = &fsreq->def_iter;
|
||||
iov_iter_xarray(&fsreq->def_iter, READ, &page->mapping->i_pages,
|
||||
iov_iter_xarray(&fsreq->def_iter, READ, &folio->mapping->i_pages,
|
||||
fsreq->pos, fsreq->len);
|
||||
|
||||
ret = afs_fetch_data(fsreq->vnode, fsreq);
|
||||
if (ret == 0)
|
||||
SetPageUptodate(page);
|
||||
unlock_page(page);
|
||||
folio_mark_uptodate(folio);
|
||||
folio_unlock(folio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -482,16 +481,15 @@ static void afs_invalidate_folio(struct folio *folio, size_t offset,
|
||||
* release a page and clean up its private state if it's not busy
|
||||
* - return true if the page can now be released, false if not
|
||||
*/
|
||||
static int afs_releasepage(struct page *page, gfp_t gfp)
|
||||
static bool afs_release_folio(struct folio *folio, gfp_t gfp)
|
||||
{
|
||||
struct folio *folio = page_folio(page);
|
||||
struct afs_vnode *vnode = AFS_FS_I(folio_inode(folio));
|
||||
|
||||
_enter("{{%llx:%llu}[%lu],%lx},%x",
|
||||
vnode->fid.vid, vnode->fid.vnode, folio_index(folio), folio->flags,
|
||||
gfp);
|
||||
|
||||
/* deny if page is being written to the cache and the caller hasn't
|
||||
/* deny if folio is being written to the cache and the caller hasn't
|
||||
* elected to wait */
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
if (folio_test_fscache(folio)) {
|
||||
|
||||
@@ -311,7 +311,7 @@ struct afs_net {
|
||||
atomic_t n_lookup; /* Number of lookups done */
|
||||
atomic_t n_reval; /* Number of dentries needing revalidation */
|
||||
atomic_t n_inval; /* Number of invalidations by the server */
|
||||
atomic_t n_relpg; /* Number of invalidations by releasepage */
|
||||
atomic_t n_relpg; /* Number of invalidations by release_folio */
|
||||
atomic_t n_read_dir; /* Number of directory pages read */
|
||||
atomic_t n_dir_cr; /* Number of directory entry creation edits */
|
||||
atomic_t n_dir_rm; /* Number of directory entry removal edits */
|
||||
@@ -1535,7 +1535,7 @@ bool afs_dirty_folio(struct address_space *, struct folio *);
|
||||
#define afs_dirty_folio filemap_dirty_folio
|
||||
#endif
|
||||
extern int afs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **pagep, void **fsdata);
|
||||
extern int afs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned copied,
|
||||
|
||||
@@ -42,7 +42,7 @@ static void afs_folio_start_fscache(bool caching, struct folio *folio)
|
||||
* prepare to perform part of a write to a page
|
||||
*/
|
||||
int afs_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
loff_t pos, unsigned len,
|
||||
struct page **_page, void **fsdata)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
|
||||
@@ -60,7 +60,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
|
||||
* file. We need to do this before we get a lock on the page in case
|
||||
* there's more than one writer competing for the same cache block.
|
||||
*/
|
||||
ret = netfs_write_begin(file, mapping, pos, len, flags, &folio, fsdata);
|
||||
ret = netfs_write_begin(file, mapping, pos, len, &folio, fsdata);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
static int befs_readdir(struct file *, struct dir_context *);
|
||||
static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
|
||||
static int befs_readpage(struct file *file, struct page *page);
|
||||
static int befs_read_folio(struct file *file, struct folio *folio);
|
||||
static sector_t befs_bmap(struct address_space *mapping, sector_t block);
|
||||
static struct dentry *befs_lookup(struct inode *, struct dentry *,
|
||||
unsigned int);
|
||||
@@ -48,7 +48,7 @@ static struct inode *befs_iget(struct super_block *, unsigned long);
|
||||
static struct inode *befs_alloc_inode(struct super_block *sb);
|
||||
static void befs_free_inode(struct inode *inode);
|
||||
static void befs_destroy_inodecache(void);
|
||||
static int befs_symlink_readpage(struct file *, struct page *);
|
||||
static int befs_symlink_read_folio(struct file *, struct folio *);
|
||||
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
|
||||
char **out, int *out_len);
|
||||
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
|
||||
@@ -87,12 +87,12 @@ static const struct inode_operations befs_dir_inode_operations = {
|
||||
};
|
||||
|
||||
static const struct address_space_operations befs_aops = {
|
||||
.readpage = befs_readpage,
|
||||
.read_folio = befs_read_folio,
|
||||
.bmap = befs_bmap,
|
||||
};
|
||||
|
||||
static const struct address_space_operations befs_symlink_aops = {
|
||||
.readpage = befs_symlink_readpage,
|
||||
.read_folio = befs_symlink_read_folio,
|
||||
};
|
||||
|
||||
static const struct export_operations befs_export_operations = {
|
||||
@@ -102,16 +102,16 @@ static const struct export_operations befs_export_operations = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Called by generic_file_read() to read a page of data
|
||||
* Called by generic_file_read() to read a folio of data
|
||||
*
|
||||
* In turn, simply calls a generic block read function and
|
||||
* passes it the address of befs_get_block, for mapping file
|
||||
* positions to disk blocks.
|
||||
*/
|
||||
static int
|
||||
befs_readpage(struct file *file, struct page *page)
|
||||
befs_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
return block_read_full_page(page, befs_get_block);
|
||||
return block_read_full_folio(folio, befs_get_block);
|
||||
}
|
||||
|
||||
static sector_t
|
||||
@@ -468,8 +468,9 @@ befs_destroy_inodecache(void)
|
||||
* The data stream become link name. Unless the LONG_SYMLINK
|
||||
* flag is set.
|
||||
*/
|
||||
static int befs_symlink_readpage(struct file *unused, struct page *page)
|
||||
static int befs_symlink_read_folio(struct file *unused, struct folio *folio)
|
||||
{
|
||||
struct page *page = &folio->page;
|
||||
struct inode *inode = page->mapping->host;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct befs_inode_info *befs_ino = BEFS_I(inode);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user