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.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Acked-by: David Howells <dhowells@redhat.com> Tested-by: David Howells <dhowells@redhat.com> Cc: Darrick J. Wong <djwong@kernel.org> Cc: Dave Chinner <david@fromorbit.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
945ea457b5
commit
0050d7f5ee
@ -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)
|
|||||||
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)
|
|||||||
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 *);
|
|||||||
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 *);
|
||||||
|
Loading…
Reference in New Issue
Block a user