AFS fixes
-----BEGIN PGP SIGNATURE----- iQIVAwUAWiFCXfSw1s6N8H32AQLtWg/+OWWvsRVmxw3voxdd8jZhSizm9gig40KJ BN+nf8eEPniTZPfHhQyoYCdMSOJXm1xfEqAETVvrrPGcatDCbxsKfohZlCMOn0v5 WCEAdCDy8XBBW1HuCBIKZX85HY6UTNVFIVtP3E+IjoPBjsV+gqUvxUDVLSVH2VIH UDyLRtO0Pl9AQS5pshJ7LfCQkwBDiw9Y5lD8DSyq5eAfxgAUFYl4uwCP9/JzZYyp +jUW1QfWl9lKh9y//Iz89TSWkaidVYr7YtKptE9uRm0XtNUymh7t5cNJ3ao79P93 oMZOHHgysl4j5o386str2sVmH76hiWArY56RTjXHMEvtzaMfOn1EuDeszPeAveWU ZwAdzeeuDW29DsdjZ/Vl6REnbgeuhsnUkjZUZ+B8k/yCTSH+X1ClP/00Z2RmDsaj Tc8EvCcsDCqB8rAa1qGBjDWPCNy4nMhf4yOAAW8qP9eNw7tEYNWMrbhyEh2yXWgd 1dhcFFYjghXUlKLQvnXnRsUKUi2liOQrUk+wvKYtrL4N6XIdgZRp/hQlKgjpdYxn 71Qop+dbn1EuOyGkcgpNxM+MPONWEqhavoQ1KawQxFJsBwo2GguzJ78BegEA5BYq iCVFS4adBtPGjjhmnCEP7nGqeJEP517YevcMo7Oo8o2XUOHWva5v8xaAK+CisEVM IJWmOvzd6rg= =1krM -----END PGP SIGNATURE----- Merge tag 'afs-fixes-20171201' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs Pull AFS fixes from David Howells: "Two fix patches for the AFS filesystem: - Fix the refcounting on permit caching. - AFS inode (afs_vnode) fields need resetting after allocation because they're only initialised when slab pages are obtained from the page allocator" * tag 'afs-fixes-20171201' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Properly reset afs_vnode (inode) fields afs: Fix permit refcounting
This commit is contained in:
Коммит
ae753ee277
|
@ -441,7 +441,10 @@ enum afs_lock_state {
|
|||
};
|
||||
|
||||
/*
|
||||
* AFS inode private data
|
||||
* AFS inode private data.
|
||||
*
|
||||
* Note that afs_alloc_inode() *must* reset anything that could incorrectly
|
||||
* leak from one inode to another.
|
||||
*/
|
||||
struct afs_vnode {
|
||||
struct inode vfs_inode; /* the VFS's inode record */
|
||||
|
|
|
@ -120,7 +120,7 @@ static void afs_hash_permits(struct afs_permits *permits)
|
|||
void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
|
||||
unsigned int cb_break)
|
||||
{
|
||||
struct afs_permits *permits, *xpermits, *replacement, *new = NULL;
|
||||
struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL;
|
||||
afs_access_t caller_access = READ_ONCE(vnode->status.caller_access);
|
||||
size_t size = 0;
|
||||
bool changed = false;
|
||||
|
@ -204,7 +204,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
|
|||
new = kzalloc(sizeof(struct afs_permits) +
|
||||
sizeof(struct afs_permit) * size, GFP_NOFS);
|
||||
if (!new)
|
||||
return;
|
||||
goto out_put;
|
||||
|
||||
refcount_set(&new->usage, 1);
|
||||
new->nr_permits = size;
|
||||
|
@ -229,8 +229,6 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
|
|||
|
||||
afs_hash_permits(new);
|
||||
|
||||
afs_put_permits(permits);
|
||||
|
||||
/* Now see if the permit list we want is actually already available */
|
||||
spin_lock(&afs_permits_lock);
|
||||
|
||||
|
@ -262,11 +260,15 @@ found:
|
|||
kfree(new);
|
||||
|
||||
spin_lock(&vnode->lock);
|
||||
if (cb_break != (vnode->cb_break + vnode->cb_interest->server->cb_s_break) ||
|
||||
permits != rcu_access_pointer(vnode->permit_cache))
|
||||
goto someone_else_changed_it_unlock;
|
||||
zap = rcu_access_pointer(vnode->permit_cache);
|
||||
if (cb_break == (vnode->cb_break + vnode->cb_interest->server->cb_s_break) &&
|
||||
zap == permits)
|
||||
rcu_assign_pointer(vnode->permit_cache, replacement);
|
||||
else
|
||||
zap = replacement;
|
||||
spin_unlock(&vnode->lock);
|
||||
afs_put_permits(zap);
|
||||
out_put:
|
||||
afs_put_permits(permits);
|
||||
return;
|
||||
|
||||
|
|
|
@ -536,7 +536,9 @@ static void afs_kill_super(struct super_block *sb)
|
|||
}
|
||||
|
||||
/*
|
||||
* initialise an inode cache slab element prior to any use
|
||||
* Initialise an inode cache slab element prior to any use. Note that
|
||||
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one
|
||||
* inode to another.
|
||||
*/
|
||||
static void afs_i_init_once(void *_vnode)
|
||||
{
|
||||
|
@ -568,11 +570,21 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
|
|||
|
||||
atomic_inc(&afs_count_active_inodes);
|
||||
|
||||
/* Reset anything that shouldn't leak from one inode to the next. */
|
||||
memset(&vnode->fid, 0, sizeof(vnode->fid));
|
||||
memset(&vnode->status, 0, sizeof(vnode->status));
|
||||
|
||||
vnode->volume = NULL;
|
||||
vnode->lock_key = NULL;
|
||||
vnode->permit_cache = NULL;
|
||||
vnode->cb_interest = NULL;
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
vnode->cache = NULL;
|
||||
#endif
|
||||
|
||||
vnode->flags = 1 << AFS_VNODE_UNSET;
|
||||
vnode->cb_type = 0;
|
||||
vnode->lock_state = AFS_VNODE_LOCK_NONE;
|
||||
|
||||
_leave(" = %p", &vnode->vfs_inode);
|
||||
return &vnode->vfs_inode;
|
||||
|
|
Загрузка…
Ссылка в новой задаче