Commit 0050d7f5 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Andrew Morton

afs: split afs_pagecache_valid() out of afs_validate()

For the map_pages() method, we need a test that does not sleep.  The page
fault handler will continue to call the fault() method where we can sleep
and do the full revalidation there.

Link: https://lkml.kernel.org/r/20230327174515.1811532-3-willy@infradead.orgSigned-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Tested-by: default avatarDavid Howells <dhowells@redhat.com>
Cc: Darrick J. Wong <djwong@kernel.org>
Cc: Dave Chinner <david@fromorbit.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 945ea457
...@@ -569,20 +569,10 @@ static void afs_vm_close(struct vm_area_struct *vma) ...@@ -569,20 +569,10 @@ static void afs_vm_close(struct vm_area_struct *vma)
static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff) static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff)
{ {
struct afs_vnode *vnode = AFS_FS_I(file_inode(vmf->vma->vm_file)); struct afs_vnode *vnode = AFS_FS_I(file_inode(vmf->vma->vm_file));
struct afs_file *af = vmf->vma->vm_file->private_data;
switch (afs_validate(vnode, af->key)) { if (afs_pagecache_valid(vnode))
case 0:
return filemap_map_pages(vmf, start_pgoff, end_pgoff); return filemap_map_pages(vmf, start_pgoff, end_pgoff);
case -ENOMEM: return 0;
return VM_FAULT_OOM;
case -EINTR:
case -ERESTARTSYS:
return VM_FAULT_RETRY;
case -ESTALE:
default:
return VM_FAULT_SIGBUS;
}
} }
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
......
...@@ -667,6 +667,24 @@ bool afs_check_validity(struct afs_vnode *vnode) ...@@ -667,6 +667,24 @@ bool afs_check_validity(struct afs_vnode *vnode)
return false; return false;
} }
/*
* Returns true if the pagecache is still valid. Does not sleep.
*/
bool afs_pagecache_valid(struct afs_vnode *vnode)
{
if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) {
if (vnode->netfs.inode.i_nlink)
clear_nlink(&vnode->netfs.inode);
return true;
}
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) &&
afs_check_validity(vnode))
return true;
return false;
}
/* /*
* validate a vnode/inode * validate a vnode/inode
* - there are several things we need to check * - there are several things we need to check
...@@ -684,14 +702,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) ...@@ -684,14 +702,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
vnode->fid.vid, vnode->fid.vnode, vnode->flags, vnode->fid.vid, vnode->fid.vnode, vnode->flags,
key_serial(key)); key_serial(key));
if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) { if (afs_pagecache_valid(vnode))
if (vnode->netfs.inode.i_nlink)
clear_nlink(&vnode->netfs.inode);
goto valid;
}
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) &&
afs_check_validity(vnode))
goto valid; goto valid;
down_write(&vnode->validate_lock); down_write(&vnode->validate_lock);
......
...@@ -1171,6 +1171,7 @@ extern struct inode *afs_iget(struct afs_operation *, struct afs_vnode_param *); ...@@ -1171,6 +1171,7 @@ extern struct inode *afs_iget(struct afs_operation *, struct afs_vnode_param *);
extern struct inode *afs_root_iget(struct super_block *, struct key *); extern struct inode *afs_root_iget(struct super_block *, struct key *);
extern bool afs_check_validity(struct afs_vnode *); extern bool afs_check_validity(struct afs_vnode *);
extern int afs_validate(struct afs_vnode *, struct key *); extern int afs_validate(struct afs_vnode *, struct key *);
bool afs_pagecache_valid(struct afs_vnode *);
extern int afs_getattr(struct mnt_idmap *idmap, const struct path *, extern int afs_getattr(struct mnt_idmap *idmap, const struct path *,
struct kstat *, u32, unsigned int); struct kstat *, u32, unsigned int);
extern int afs_setattr(struct mnt_idmap *idmap, struct dentry *, struct iattr *); extern int afs_setattr(struct mnt_idmap *idmap, struct dentry *, struct iattr *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment