mirror of https://gitee.com/openkylin/linux.git
NFS client bugfixes for Linux 5.7
Highlights include: Stable fixes: - nfs: fix NULL deference in nfs4_get_valid_delegation Bugfixes: - Fix corruption of the return value in cachefiles_read_or_alloc_pages() - Fix several fscache cookie issues - Fix a fscache queuing race that can trigger a BUG_ON - NFS: Fix 2 use-after-free regressions due to the RPC_TASK_CRED_NOREF flag - SUNRPC: Fix a use-after-free regression in rpc_free_client_work() - SUNRPC: Fix a race when tearing down the rpc client debugfs directory - SUNRPC: Signalled ASYNC tasks need to exit - NFSv3: fix rpc receive buffer size for MOUNT call -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAl6/AkgACgkQZwvnipYK APICLQ/9ENY+mQmVMSbtw2VGlBphS+GLN44k70NgmjAaI9n8f3ILZyLl0/iHEPFU ZaCWhPWEs76olLfCWwoQFzISIUTHWVUow8mJn7gTh4mq8n9UFv8zgUxtJ3HTfEHt rtujG9xsK0Oa351UPJWE5yC7PvFzMohcc1vVD8WQeGJQ3sMBVHTuOuPatIv3vK6s 8MflKTbtz/gUkcbWMCk9ljMPXr6/Ksgu9GZDnDFAYZBfFkwx//RNmq6K+z1Ru15s tkmPPZGNMCfKblrnUXUmPt78wxSExmWrXroSMNas2fyeOXgPL0ogNx8vfdFcFsxs sHpMkF97+npntNj1y5om6GrdU4SRYUFqXT7pNqV4wuGguOfFELIXrJIQuCDaKrGD ApEoo9UDisGCLdqs738ascZFHZiTQoy6drbpR8moalqhYkTI7Al/pPxHnozGDYsJ +wElaFXZX2hlPc6ih1q54RcB+D4qswDC9QudArKc9hJEKPv+SsmiVhBG/f+X+Jca M19UJGWZvRtY8L+0yJdG22O9Hwo0zSK917gtOZNgkwtkkKgzjj2kcNHTK2jGBEuR pqEIQCreUH8Le0WR9cPeJeYc2/HeCEWDHrf/q+gFRClaZMe+0Sfu3z3pBH3v0T9q qoZ1VvCDUhggsZyJZebcPTCL+ghqOXFJajHLlcA6BSdGJ/iXq2M= =lqFu -----END PGP SIGNATURE----- Merge tag 'nfs-for-5.7-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client bugfixes from Trond Myklebust: "Highlights include: Stable fixes: - nfs: fix NULL deference in nfs4_get_valid_delegation Bugfixes: - Fix corruption of the return value in cachefiles_read_or_alloc_pages() - Fix several fscache cookie issues - Fix a fscache queuing race that can trigger a BUG_ON - NFS: Fix two use-after-free regressions due to the RPC_TASK_CRED_NOREF flag - SUNRPC: Fix a use-after-free regression in rpc_free_client_work() - SUNRPC: Fix a race when tearing down the rpc client debugfs directory - SUNRPC: Signalled ASYNC tasks need to exit - NFSv3: fix rpc receive buffer size for MOUNT call" * tag 'nfs-for-5.7-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv3: fix rpc receive buffer size for MOUNT call SUNRPC: 'Directory with parent 'rpc_clnt' already present!' NFS/pnfs: Don't use RPC_TASK_CRED_NOREF with pnfs NFS: Don't use RPC_TASK_CRED_NOREF with delegreturn SUNRPC: Signalled ASYNC tasks need to exit nfs: fix NULL deference in nfs4_get_valid_delegation SUNRPC: fix use-after-free in rpc_free_client_work() cachefiles: Fix race between read_waiter and read_copier involving op->to_do NFSv4: Fix fscache cookie aux_data to ensure change_attr is included NFS: Fix fscache super_cookie allocation NFS: Fix fscache super_cookie index_key from changing after umount cachefiles: Fix corruption of the return value in cachefiles_read_or_alloc_pages()
This commit is contained in:
commit
12bf0b632e
|
@ -60,9 +60,9 @@ static int cachefiles_read_waiter(wait_queue_entry_t *wait, unsigned mode,
|
||||||
object = container_of(op->op.object, struct cachefiles_object, fscache);
|
object = container_of(op->op.object, struct cachefiles_object, fscache);
|
||||||
spin_lock(&object->work_lock);
|
spin_lock(&object->work_lock);
|
||||||
list_add_tail(&monitor->op_link, &op->to_do);
|
list_add_tail(&monitor->op_link, &op->to_do);
|
||||||
|
fscache_enqueue_retrieval(op);
|
||||||
spin_unlock(&object->work_lock);
|
spin_unlock(&object->work_lock);
|
||||||
|
|
||||||
fscache_enqueue_retrieval(op);
|
|
||||||
fscache_put_retrieval(op);
|
fscache_put_retrieval(op);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
sector_t block;
|
sector_t block;
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
int ret;
|
int ret, ret2;
|
||||||
|
|
||||||
object = container_of(op->op.object,
|
object = container_of(op->op.object,
|
||||||
struct cachefiles_object, fscache);
|
struct cachefiles_object, fscache);
|
||||||
|
@ -430,8 +430,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
|
||||||
block = page->index;
|
block = page->index;
|
||||||
block <<= shift;
|
block <<= shift;
|
||||||
|
|
||||||
ret = bmap(inode, &block);
|
ret2 = bmap(inode, &block);
|
||||||
ASSERT(ret < 0);
|
ASSERT(ret2 == 0);
|
||||||
|
|
||||||
_debug("%llx -> %llx",
|
_debug("%llx -> %llx",
|
||||||
(unsigned long long) (page->index << shift),
|
(unsigned long long) (page->index << shift),
|
||||||
|
@ -739,8 +739,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
|
||||||
block = page->index;
|
block = page->index;
|
||||||
block <<= shift;
|
block <<= shift;
|
||||||
|
|
||||||
ret = bmap(inode, &block);
|
ret2 = bmap(inode, &block);
|
||||||
ASSERT(!ret);
|
ASSERT(ret2 == 0);
|
||||||
|
|
||||||
_debug("%llx -> %llx",
|
_debug("%llx -> %llx",
|
||||||
(unsigned long long) (page->index << shift),
|
(unsigned long long) (page->index << shift),
|
||||||
|
|
|
@ -118,8 +118,6 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
|
||||||
|
|
||||||
nfss->fscache_key = NULL;
|
nfss->fscache_key = NULL;
|
||||||
nfss->fscache = NULL;
|
nfss->fscache = NULL;
|
||||||
if (!(nfss->options & NFS_OPTION_FSCACHE))
|
|
||||||
return;
|
|
||||||
if (!uniq) {
|
if (!uniq) {
|
||||||
uniq = "";
|
uniq = "";
|
||||||
ulen = 1;
|
ulen = 1;
|
||||||
|
@ -188,7 +186,8 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
|
||||||
/* create a cache index for looking up filehandles */
|
/* create a cache index for looking up filehandles */
|
||||||
nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
|
nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
|
||||||
&nfs_fscache_super_index_def,
|
&nfs_fscache_super_index_def,
|
||||||
key, sizeof(*key) + ulen,
|
&key->key,
|
||||||
|
sizeof(key->key) + ulen,
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
nfss, 0, true);
|
nfss, 0, true);
|
||||||
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
|
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
|
||||||
|
@ -226,6 +225,19 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
|
||||||
|
struct nfs_inode *nfsi)
|
||||||
|
{
|
||||||
|
memset(auxdata, 0, sizeof(*auxdata));
|
||||||
|
auxdata->mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec;
|
||||||
|
auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
|
||||||
|
auxdata->ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec;
|
||||||
|
auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
|
||||||
|
|
||||||
|
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
|
||||||
|
auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialise the per-inode cache cookie pointer for an NFS inode.
|
* Initialise the per-inode cache cookie pointer for an NFS inode.
|
||||||
*/
|
*/
|
||||||
|
@ -239,14 +251,7 @@ void nfs_fscache_init_inode(struct inode *inode)
|
||||||
if (!(nfss->fscache && S_ISREG(inode->i_mode)))
|
if (!(nfss->fscache && S_ISREG(inode->i_mode)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(&auxdata, 0, sizeof(auxdata));
|
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||||
auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec;
|
|
||||||
auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
|
|
||||||
auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec;
|
|
||||||
auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
|
|
||||||
|
|
||||||
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
|
|
||||||
auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
|
|
||||||
|
|
||||||
nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
|
nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
|
||||||
&nfs_fscache_inode_object_def,
|
&nfs_fscache_inode_object_def,
|
||||||
|
@ -266,11 +271,7 @@ void nfs_fscache_clear_inode(struct inode *inode)
|
||||||
|
|
||||||
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
|
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
|
||||||
|
|
||||||
memset(&auxdata, 0, sizeof(auxdata));
|
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||||
auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec;
|
|
||||||
auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
|
|
||||||
auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec;
|
|
||||||
auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
|
|
||||||
fscache_relinquish_cookie(cookie, &auxdata, false);
|
fscache_relinquish_cookie(cookie, &auxdata, false);
|
||||||
nfsi->fscache = NULL;
|
nfsi->fscache = NULL;
|
||||||
}
|
}
|
||||||
|
@ -310,11 +311,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
|
||||||
if (!fscache_cookie_valid(cookie))
|
if (!fscache_cookie_valid(cookie))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(&auxdata, 0, sizeof(auxdata));
|
nfs_fscache_update_auxdata(&auxdata, nfsi);
|
||||||
auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec;
|
|
||||||
auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
|
|
||||||
auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec;
|
|
||||||
auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
|
|
||||||
|
|
||||||
if (inode_is_open_for_write(inode)) {
|
if (inode_is_open_for_write(inode)) {
|
||||||
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
|
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN))
|
#define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN))
|
||||||
#define MNT_status_sz (1)
|
#define MNT_status_sz (1)
|
||||||
#define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE)
|
#define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE)
|
||||||
|
#define MNT_fhandlev3_sz XDR_QUADLEN(NFS3_FHSIZE)
|
||||||
#define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS)
|
#define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -37,7 +38,7 @@
|
||||||
*/
|
*/
|
||||||
#define MNT_enc_dirpath_sz encode_dirpath_sz
|
#define MNT_enc_dirpath_sz encode_dirpath_sz
|
||||||
#define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz)
|
#define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz)
|
||||||
#define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \
|
#define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandlev3_sz + \
|
||||||
MNT_authflav3_sz)
|
MNT_authflav3_sz)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -6347,7 +6347,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
|
||||||
.rpc_client = server->client,
|
.rpc_client = server->client,
|
||||||
.rpc_message = &msg,
|
.rpc_message = &msg,
|
||||||
.callback_ops = &nfs4_delegreturn_ops,
|
.callback_ops = &nfs4_delegreturn_ops,
|
||||||
.flags = RPC_TASK_ASYNC | RPC_TASK_CRED_NOREF | RPC_TASK_TIMEOUT,
|
.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
|
||||||
};
|
};
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
|
|
@ -734,9 +734,9 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
|
||||||
state = new;
|
state = new;
|
||||||
state->owner = owner;
|
state->owner = owner;
|
||||||
atomic_inc(&owner->so_count);
|
atomic_inc(&owner->so_count);
|
||||||
list_add_rcu(&state->inode_states, &nfsi->open_states);
|
|
||||||
ihold(inode);
|
ihold(inode);
|
||||||
state->inode = inode;
|
state->inode = inode;
|
||||||
|
list_add_rcu(&state->inode_states, &nfsi->open_states);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
/* Note: The reclaim code dictates that we add stateless
|
/* Note: The reclaim code dictates that we add stateless
|
||||||
* and read-only stateids to the end of the list */
|
* and read-only stateids to the end of the list */
|
||||||
|
|
|
@ -752,7 +752,7 @@ int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr,
|
||||||
.callback_ops = call_ops,
|
.callback_ops = call_ops,
|
||||||
.callback_data = hdr,
|
.callback_data = hdr,
|
||||||
.workqueue = nfsiod_workqueue,
|
.workqueue = nfsiod_workqueue,
|
||||||
.flags = RPC_TASK_ASYNC | RPC_TASK_CRED_NOREF | flags,
|
.flags = RPC_TASK_ASYNC | flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
hdr->rw_ops->rw_initiate(hdr, &msg, rpc_ops, &task_setup_data, how);
|
hdr->rw_ops->rw_initiate(hdr, &msg, rpc_ops, &task_setup_data, how);
|
||||||
|
@ -950,7 +950,8 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
|
||||||
hdr->cred,
|
hdr->cred,
|
||||||
NFS_PROTO(hdr->inode),
|
NFS_PROTO(hdr->inode),
|
||||||
desc->pg_rpc_callops,
|
desc->pg_rpc_callops,
|
||||||
desc->pg_ioflags, 0);
|
desc->pg_ioflags,
|
||||||
|
RPC_TASK_CRED_NOREF);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -536,7 +536,8 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
|
||||||
nfs_init_commit(data, NULL, NULL, cinfo);
|
nfs_init_commit(data, NULL, NULL, cinfo);
|
||||||
nfs_initiate_commit(NFS_CLIENT(inode), data,
|
nfs_initiate_commit(NFS_CLIENT(inode), data,
|
||||||
NFS_PROTO(data->inode),
|
NFS_PROTO(data->inode),
|
||||||
data->mds_ops, how, 0);
|
data->mds_ops, how,
|
||||||
|
RPC_TASK_CRED_NOREF);
|
||||||
} else {
|
} else {
|
||||||
nfs_init_commit(data, NULL, data->lseg, cinfo);
|
nfs_init_commit(data, NULL, data->lseg, cinfo);
|
||||||
initiate_commit(data, how);
|
initiate_commit(data, how);
|
||||||
|
|
|
@ -1189,7 +1189,6 @@ static void nfs_get_cache_cookie(struct super_block *sb,
|
||||||
uniq = ctx->fscache_uniq;
|
uniq = ctx->fscache_uniq;
|
||||||
ulen = strlen(ctx->fscache_uniq);
|
ulen = strlen(ctx->fscache_uniq);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nfs_fscache_get_super_cookie(sb, uniq, ulen);
|
nfs_fscache_get_super_cookie(sb, uniq, ulen);
|
||||||
|
|
|
@ -1695,7 +1695,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
|
||||||
.callback_ops = call_ops,
|
.callback_ops = call_ops,
|
||||||
.callback_data = data,
|
.callback_data = data,
|
||||||
.workqueue = nfsiod_workqueue,
|
.workqueue = nfsiod_workqueue,
|
||||||
.flags = RPC_TASK_ASYNC | RPC_TASK_CRED_NOREF | flags,
|
.flags = RPC_TASK_ASYNC | flags,
|
||||||
.priority = priority,
|
.priority = priority,
|
||||||
};
|
};
|
||||||
/* Set up the initial task struct. */
|
/* Set up the initial task struct. */
|
||||||
|
@ -1813,7 +1813,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
|
||||||
nfs_init_commit(data, head, NULL, cinfo);
|
nfs_init_commit(data, head, NULL, cinfo);
|
||||||
atomic_inc(&cinfo->mds->rpcs_out);
|
atomic_inc(&cinfo->mds->rpcs_out);
|
||||||
return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
|
return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
|
||||||
data->mds_ops, how, 0);
|
data->mds_ops, how, RPC_TASK_CRED_NOREF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -889,7 +889,9 @@ static void rpc_free_client_work(struct work_struct *work)
|
||||||
* here.
|
* here.
|
||||||
*/
|
*/
|
||||||
rpc_clnt_debugfs_unregister(clnt);
|
rpc_clnt_debugfs_unregister(clnt);
|
||||||
|
rpc_free_clid(clnt);
|
||||||
rpc_clnt_remove_pipedir(clnt);
|
rpc_clnt_remove_pipedir(clnt);
|
||||||
|
xprt_put(rcu_dereference_raw(clnt->cl_xprt));
|
||||||
|
|
||||||
kfree(clnt);
|
kfree(clnt);
|
||||||
rpciod_down();
|
rpciod_down();
|
||||||
|
@ -907,10 +909,8 @@ rpc_free_client(struct rpc_clnt *clnt)
|
||||||
rpc_unregister_client(clnt);
|
rpc_unregister_client(clnt);
|
||||||
rpc_free_iostats(clnt->cl_metrics);
|
rpc_free_iostats(clnt->cl_metrics);
|
||||||
clnt->cl_metrics = NULL;
|
clnt->cl_metrics = NULL;
|
||||||
xprt_put(rcu_dereference_raw(clnt->cl_xprt));
|
|
||||||
xprt_iter_destroy(&clnt->cl_xpi);
|
xprt_iter_destroy(&clnt->cl_xpi);
|
||||||
put_cred(clnt->cl_cred);
|
put_cred(clnt->cl_cred);
|
||||||
rpc_free_clid(clnt);
|
|
||||||
|
|
||||||
INIT_WORK(&clnt->cl_work, rpc_free_client_work);
|
INIT_WORK(&clnt->cl_work, rpc_free_client_work);
|
||||||
schedule_work(&clnt->cl_work);
|
schedule_work(&clnt->cl_work);
|
||||||
|
@ -2433,6 +2433,11 @@ rpc_check_timeout(struct rpc_task *task)
|
||||||
{
|
{
|
||||||
struct rpc_clnt *clnt = task->tk_client;
|
struct rpc_clnt *clnt = task->tk_client;
|
||||||
|
|
||||||
|
if (RPC_SIGNALLED(task)) {
|
||||||
|
rpc_call_rpcerror(task, -ERESTARTSYS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (xprt_adjust_timeout(task->tk_rqstp) == 0)
|
if (xprt_adjust_timeout(task->tk_rqstp) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue