forked from Minki/linux
NFS client updates for Linux 3.20
Highlights include: - Fix a use-after-free in decode_cb_sequence_args() - Fix a compile error when #undef CONFIG_PROC_FS - NFSv4.1 backchannel spinlocking issue - Cleanups in the NFS unstable write code requested by Linus - NFSv4.1 fix issues when the server denies our backchannel request - Cleanups in create_session and bind_conn_to_session -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJU51zBAAoJEGcL54qWCgDyyvwQALp7vxXCTwC3/OSoPkhujd2C HGMoI2nVSl8CY0LFYxoT6auhefZCgQChmQXkGtlZwO+bkEr9rvJ6ii8lhuDR+JXF M0bAwOX+bNxUFkpqYYF3Q4Hi//tMJCIZdqUp2irtyFLL/qlNoN2ktoEYMIjMY5uO 4L1fxj9KaVuMtFuqt3xeSSe41LaXxitKyefyVJfbqz5qbcPGiXzS7WKYAun4RyvM 7rCir9kfnxxEX3+hc7xHxWeFJnW0jUMklrjNvnrubnpHE/fX2sUAnjX2hmx5bLg/ 4puxADzhPT4f3LdGDKXVWaULuTy20VksOJnB82TKJ3rLIELJixGZw88svOrFcGvt 5CMI8BvOihwn8ov+sSj7Xedz4046btwA1YHkUcwPV3LZAlyx/FSq4nasO4Cn27yl OPdkcAL1YR5I83mEKA+8BOVXJuFx5vKhkwmMdReJkBmxsWbSwB/qp6caPD9DtuXI K0qJYWHMqN+Dv9npi0Q4WR6vmnzxV+Eq7Z2D9WPW0FL8nT3STE0eWIrNipyqOv+7 bHptPxrrZej+i3c922bZ6hdaE2uAlwG8FPgEGhHFtm+s09RgDPDG7NiaeCutf9cQ 9ub82Hlk9nLTqq5X3poUPV35RS6THnZcybhngNMy8F1cPSUTs+/H+l91sEW/Zhgw odMB/DEa9sRnZGX5rQXE =NieR -----END PGP SIGNATURE----- Merge tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull more NFS client updates from Trond Myklebust: "Highlights include: - Fix a use-after-free in decode_cb_sequence_args() - Fix a compile error when #undef CONFIG_PROC_FS - NFSv4.1 backchannel spinlocking issue - Cleanups in the NFS unstable write code requested by Linus - NFSv4.1 fix issues when the server denies our backchannel request - Cleanups in create_session and bind_conn_to_session" * tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.1: Clean up bind_conn_to_session NFSv4.1: Always set up a forward channel when binding the session NFSv4.1: Don't set up a backchannel if the server didn't agree to do so NFSv4.1: Clean up create_session pnfs: Refactor the *_layout_mark_request_commit to use pnfs_layout_mark_request_commit NFSv4: Kill unused nfs_inode->delegation_state field NFS: struct nfs_commit_info.lock must always point to inode->i_lock nfs: Can call nfs_clear_page_commit() instead nfs: Provide and use helper functions for marking a page as unstable SUNRPC: Always manipulate rpc_rqst::rq_bc_pa_list under xprt->bc_pa_lock SUNRPC: Fix a compile error when #undef CONFIG_PROC_FS NFSv4.1: Convert open-coded array allocation calls to kmalloc_array() NFSv4.1: Fix a kfree() of uninitialised pointers in decode_cb_sequence_args
This commit is contained in:
commit
24a52e412e
@ -427,6 +427,8 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
|
||||
if (clp == NULL)
|
||||
goto out;
|
||||
|
||||
if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
|
||||
goto out;
|
||||
tbl = &clp->cl_session->bc_slot_table;
|
||||
|
||||
spin_lock(&tbl->slot_tbl_lock);
|
||||
|
@ -313,7 +313,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
|
||||
goto out;
|
||||
}
|
||||
|
||||
args->devs = kmalloc(n * sizeof(*args->devs), GFP_KERNEL);
|
||||
args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
|
||||
if (!args->devs) {
|
||||
status = htonl(NFS4ERR_DELAY);
|
||||
goto out;
|
||||
@ -415,7 +415,7 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
|
||||
rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
|
||||
if (unlikely(p == NULL))
|
||||
goto out;
|
||||
rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
|
||||
rc_list->rcl_refcalls = kmalloc_array(rc_list->rcl_nrefcalls,
|
||||
sizeof(*rc_list->rcl_refcalls),
|
||||
GFP_KERNEL);
|
||||
if (unlikely(rc_list->rcl_refcalls == NULL))
|
||||
@ -464,10 +464,12 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
|
||||
|
||||
for (i = 0; i < args->csa_nrclists; i++) {
|
||||
status = decode_rc_list(xdr, &args->csa_rclists[i]);
|
||||
if (status)
|
||||
if (status) {
|
||||
args->csa_nrclists = i;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
}
|
||||
status = 0;
|
||||
|
||||
dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
|
||||
|
@ -180,7 +180,6 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
|
||||
delegation->cred = get_rpccred(cred);
|
||||
clear_bit(NFS_DELEGATION_NEED_RECLAIM,
|
||||
&delegation->flags);
|
||||
NFS_I(inode)->delegation_state = delegation->type;
|
||||
spin_unlock(&delegation->lock);
|
||||
put_rpccred(oldcred);
|
||||
rcu_read_unlock();
|
||||
@ -275,7 +274,6 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi,
|
||||
set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
list_del_rcu(&delegation->super_list);
|
||||
delegation->inode = NULL;
|
||||
nfsi->delegation_state = 0;
|
||||
rcu_assign_pointer(nfsi->delegation, NULL);
|
||||
spin_unlock(&delegation->lock);
|
||||
return delegation;
|
||||
@ -355,7 +353,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
|
||||
&delegation->stateid)) {
|
||||
nfs_update_inplace_delegation(old_delegation,
|
||||
delegation);
|
||||
nfsi->delegation_state = old_delegation->type;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@ -379,7 +376,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
|
||||
goto out;
|
||||
}
|
||||
list_add_rcu(&delegation->super_list, &server->delegations);
|
||||
nfsi->delegation_state = delegation->type;
|
||||
rcu_assign_pointer(nfsi->delegation, delegation);
|
||||
delegation = NULL;
|
||||
|
||||
|
@ -283,7 +283,7 @@ static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
|
||||
void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo,
|
||||
struct nfs_direct_req *dreq)
|
||||
{
|
||||
cinfo->lock = &dreq->lock;
|
||||
cinfo->lock = &dreq->inode->i_lock;
|
||||
cinfo->mds = &dreq->mds_cinfo;
|
||||
cinfo->ds = &dreq->ds_cinfo;
|
||||
cinfo->dreq = dreq;
|
||||
|
@ -960,15 +960,10 @@ filelayout_mark_request_commit(struct nfs_page *req,
|
||||
{
|
||||
struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
|
||||
u32 i, j;
|
||||
struct list_head *list;
|
||||
struct pnfs_commit_bucket *buckets;
|
||||
|
||||
if (fl->commit_through_mds) {
|
||||
list = &cinfo->mds->list;
|
||||
spin_lock(cinfo->lock);
|
||||
goto mds_commit;
|
||||
}
|
||||
|
||||
nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo);
|
||||
} else {
|
||||
/* Note that we are calling nfs4_fl_calc_j_index on each page
|
||||
* that ends up being committed to a data server. An attractive
|
||||
* alternative is to add a field to nfs_write_data and nfs_page
|
||||
@ -977,35 +972,7 @@ filelayout_mark_request_commit(struct nfs_page *req,
|
||||
*/
|
||||
j = nfs4_fl_calc_j_index(lseg, req_offset(req));
|
||||
i = select_bucket_index(fl, j);
|
||||
spin_lock(cinfo->lock);
|
||||
buckets = cinfo->ds->buckets;
|
||||
list = &buckets[i].written;
|
||||
if (list_empty(list)) {
|
||||
/* Non-empty buckets hold a reference on the lseg. That ref
|
||||
* is normally transferred to the COMMIT call and released
|
||||
* there. It could also be released if the last req is pulled
|
||||
* off due to a rewrite, in which case it will be done in
|
||||
* pnfs_generic_clear_request_commit
|
||||
*/
|
||||
buckets[i].wlseg = pnfs_get_lseg(lseg);
|
||||
}
|
||||
set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
|
||||
cinfo->ds->nwritten++;
|
||||
|
||||
mds_commit:
|
||||
/* nfs_request_add_commit_list(). We need to add req to list without
|
||||
* dropping cinfo lock.
|
||||
*/
|
||||
set_bit(PG_CLEAN, &(req)->wb_flags);
|
||||
nfs_list_add_request(req, list);
|
||||
cinfo->mds->ncommit++;
|
||||
spin_unlock(cinfo->lock);
|
||||
if (!cinfo->dreq) {
|
||||
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
|
||||
inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
|
||||
BDI_RECLAIMABLE);
|
||||
__mark_inode_dirty(req->wb_context->dentry->d_inode,
|
||||
I_DIRTY_DATASYNC);
|
||||
pnfs_layout_mark_request_commit(req, lseg, cinfo, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1332,47 +1332,6 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
|
||||
return PNFS_ATTEMPTED;
|
||||
}
|
||||
|
||||
static void
|
||||
ff_layout_mark_request_commit(struct nfs_page *req,
|
||||
struct pnfs_layout_segment *lseg,
|
||||
struct nfs_commit_info *cinfo,
|
||||
u32 ds_commit_idx)
|
||||
{
|
||||
struct list_head *list;
|
||||
struct pnfs_commit_bucket *buckets;
|
||||
|
||||
spin_lock(cinfo->lock);
|
||||
buckets = cinfo->ds->buckets;
|
||||
list = &buckets[ds_commit_idx].written;
|
||||
if (list_empty(list)) {
|
||||
/* Non-empty buckets hold a reference on the lseg. That ref
|
||||
* is normally transferred to the COMMIT call and released
|
||||
* there. It could also be released if the last req is pulled
|
||||
* off due to a rewrite, in which case it will be done in
|
||||
* pnfs_common_clear_request_commit
|
||||
*/
|
||||
WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
|
||||
buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
|
||||
}
|
||||
set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
|
||||
cinfo->ds->nwritten++;
|
||||
|
||||
/* nfs_request_add_commit_list(). We need to add req to list without
|
||||
* dropping cinfo lock.
|
||||
*/
|
||||
set_bit(PG_CLEAN, &(req)->wb_flags);
|
||||
nfs_list_add_request(req, list);
|
||||
cinfo->mds->ncommit++;
|
||||
spin_unlock(cinfo->lock);
|
||||
if (!cinfo->dreq) {
|
||||
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
|
||||
inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
|
||||
BDI_RECLAIMABLE);
|
||||
__mark_inode_dirty(req->wb_context->dentry->d_inode,
|
||||
I_DIRTY_DATASYNC);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
|
||||
{
|
||||
return i;
|
||||
@ -1540,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
|
||||
.pg_write_ops = &ff_layout_pg_write_ops,
|
||||
.get_ds_info = ff_layout_get_ds_info,
|
||||
.free_deviceid_node = ff_layout_free_deveiceid_node,
|
||||
.mark_request_commit = ff_layout_mark_request_commit,
|
||||
.mark_request_commit = pnfs_layout_mark_request_commit,
|
||||
.clear_request_commit = pnfs_generic_clear_request_commit,
|
||||
.scan_commit_lists = pnfs_generic_scan_commit_lists,
|
||||
.recover_commit_reqs = pnfs_generic_recover_commit_reqs,
|
||||
|
@ -1775,7 +1775,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
|
||||
#if IS_ENABLED(CONFIG_NFS_V4)
|
||||
INIT_LIST_HEAD(&nfsi->open_states);
|
||||
nfsi->delegation = NULL;
|
||||
nfsi->delegation_state = 0;
|
||||
init_rwsem(&nfsi->rwsem);
|
||||
nfsi->layout = NULL;
|
||||
#endif
|
||||
|
@ -597,6 +597,19 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
|
||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the page as unstable and mark its inode as dirty.
|
||||
*/
|
||||
static inline
|
||||
void nfs_mark_page_unstable(struct page *page)
|
||||
{
|
||||
struct inode *inode = page_file_mapping(page)->host;
|
||||
|
||||
inc_zone_page_state(page, NR_UNSTABLE_NFS);
|
||||
inc_bdi_stat(inode_to_bdi(inode), BDI_RECLAIMABLE);
|
||||
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the number of bytes of data the page contains
|
||||
*/
|
||||
|
@ -6648,47 +6648,47 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
|
||||
int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
|
||||
{
|
||||
int status;
|
||||
struct nfs41_bind_conn_to_session_args args = {
|
||||
.client = clp,
|
||||
.dir = NFS4_CDFC4_FORE_OR_BOTH,
|
||||
};
|
||||
struct nfs41_bind_conn_to_session_res res;
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc =
|
||||
&nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
|
||||
.rpc_argp = clp,
|
||||
.rpc_argp = &args,
|
||||
.rpc_resp = &res,
|
||||
.rpc_cred = cred,
|
||||
};
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
|
||||
res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
|
||||
if (unlikely(res.session == NULL)) {
|
||||
status = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
|
||||
if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
|
||||
args.dir = NFS4_CDFC4_FORE;
|
||||
|
||||
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
|
||||
trace_nfs4_bind_conn_to_session(clp, status);
|
||||
if (status == 0) {
|
||||
if (memcmp(res.session->sess_id.data,
|
||||
if (memcmp(res.sessionid.data,
|
||||
clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
|
||||
dprintk("NFS: %s: Session ID mismatch\n", __func__);
|
||||
status = -EIO;
|
||||
goto out_session;
|
||||
goto out;
|
||||
}
|
||||
if (res.dir != NFS4_CDFS4_BOTH) {
|
||||
if ((res.dir & args.dir) != res.dir || res.dir == 0) {
|
||||
dprintk("NFS: %s: Unexpected direction from server\n",
|
||||
__func__);
|
||||
status = -EIO;
|
||||
goto out_session;
|
||||
goto out;
|
||||
}
|
||||
if (res.use_conn_in_rdma_mode) {
|
||||
if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
|
||||
dprintk("NFS: %s: Server returned RDMA mode = true\n",
|
||||
__func__);
|
||||
status = -EIO;
|
||||
goto out_session;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out_session:
|
||||
kfree(res.session);
|
||||
out:
|
||||
dprintk("<-- %s status= %d\n", __func__, status);
|
||||
return status;
|
||||
@ -7166,10 +7166,11 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
|
||||
args->bc_attrs.max_reqs);
|
||||
}
|
||||
|
||||
static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
|
||||
static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
|
||||
struct nfs41_create_session_res *res)
|
||||
{
|
||||
struct nfs4_channel_attrs *sent = &args->fc_attrs;
|
||||
struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
|
||||
struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
|
||||
|
||||
if (rcvd->max_resp_sz > sent->max_resp_sz)
|
||||
return -EINVAL;
|
||||
@ -7188,11 +7189,14 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
|
||||
static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
|
||||
struct nfs41_create_session_res *res)
|
||||
{
|
||||
struct nfs4_channel_attrs *sent = &args->bc_attrs;
|
||||
struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
|
||||
struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
|
||||
|
||||
if (!(res->flags & SESSION4_BACK_CHAN))
|
||||
goto out;
|
||||
if (rcvd->max_rqst_sz > sent->max_rqst_sz)
|
||||
return -EINVAL;
|
||||
if (rcvd->max_resp_sz < sent->max_resp_sz)
|
||||
@ -7204,18 +7208,30 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
|
||||
return -EINVAL;
|
||||
if (rcvd->max_reqs != sent->max_reqs)
|
||||
return -EINVAL;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
|
||||
struct nfs4_session *session)
|
||||
struct nfs41_create_session_res *res)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nfs4_verify_fore_channel_attrs(args, session);
|
||||
ret = nfs4_verify_fore_channel_attrs(args, res);
|
||||
if (ret)
|
||||
return ret;
|
||||
return nfs4_verify_back_channel_attrs(args, session);
|
||||
return nfs4_verify_back_channel_attrs(args, res);
|
||||
}
|
||||
|
||||
static void nfs4_update_session(struct nfs4_session *session,
|
||||
struct nfs41_create_session_res *res)
|
||||
{
|
||||
nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
|
||||
session->flags = res->flags;
|
||||
memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
|
||||
if (res->flags & SESSION4_BACK_CHAN)
|
||||
memcpy(&session->bc_attrs, &res->bc_attrs,
|
||||
sizeof(session->bc_attrs));
|
||||
}
|
||||
|
||||
static int _nfs4_proc_create_session(struct nfs_client *clp,
|
||||
@ -7224,11 +7240,12 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
|
||||
struct nfs4_session *session = clp->cl_session;
|
||||
struct nfs41_create_session_args args = {
|
||||
.client = clp,
|
||||
.clientid = clp->cl_clientid,
|
||||
.seqid = clp->cl_seqid,
|
||||
.cb_program = NFS4_CALLBACK,
|
||||
};
|
||||
struct nfs41_create_session_res res = {
|
||||
.client = clp,
|
||||
};
|
||||
struct nfs41_create_session_res res;
|
||||
|
||||
struct rpc_message msg = {
|
||||
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
|
||||
.rpc_argp = &args,
|
||||
@ -7245,11 +7262,15 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
|
||||
|
||||
if (!status) {
|
||||
/* Verify the session's negotiated channel_attrs values */
|
||||
status = nfs4_verify_channel_attrs(&args, session);
|
||||
status = nfs4_verify_channel_attrs(&args, &res);
|
||||
/* Increment the clientid slot sequence id */
|
||||
if (clp->cl_seqid == res.seqid)
|
||||
clp->cl_seqid++;
|
||||
if (status)
|
||||
goto out;
|
||||
nfs4_update_session(session, &res);
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -450,7 +450,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
|
||||
tbl = &ses->fc_slot_table;
|
||||
tbl->session = ses;
|
||||
status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
|
||||
if (status) /* -ENOMEM */
|
||||
if (status || !(ses->flags & SESSION4_BACK_CHAN)) /* -ENOMEM */
|
||||
return status;
|
||||
/* Back channel */
|
||||
tbl = &ses->bc_slot_table;
|
||||
|
@ -118,6 +118,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
|
||||
const struct nfs4_sessionid *src)
|
||||
{
|
||||
memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CRC32
|
||||
/*
|
||||
* nfs_session_id_hash - calculate the crc32 hash for the session id
|
||||
|
@ -1715,17 +1715,17 @@ static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, stru
|
||||
#if defined(CONFIG_NFS_V4_1)
|
||||
/* NFSv4.1 operations */
|
||||
static void encode_bind_conn_to_session(struct xdr_stream *xdr,
|
||||
struct nfs4_session *session,
|
||||
struct nfs41_bind_conn_to_session_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
{
|
||||
__be32 *p;
|
||||
|
||||
encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
|
||||
decode_bind_conn_to_session_maxsz, hdr);
|
||||
encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
|
||||
encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
|
||||
p = xdr_reserve_space(xdr, 8);
|
||||
*p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH);
|
||||
*p = 0; /* use_conn_in_rdma_mode = False */
|
||||
*p++ = cpu_to_be32(args->dir);
|
||||
*p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
|
||||
}
|
||||
|
||||
static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
|
||||
@ -1806,8 +1806,8 @@ static void encode_create_session(struct xdr_stream *xdr,
|
||||
|
||||
encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
|
||||
p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
|
||||
p = xdr_encode_hyper(p, clp->cl_clientid);
|
||||
*p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */
|
||||
p = xdr_encode_hyper(p, args->clientid);
|
||||
*p++ = cpu_to_be32(args->seqid); /*Sequence id */
|
||||
*p++ = cpu_to_be32(args->flags); /*flags */
|
||||
|
||||
/* Fore Channel */
|
||||
@ -2734,14 +2734,14 @@ static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
|
||||
*/
|
||||
static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
|
||||
struct xdr_stream *xdr,
|
||||
struct nfs_client *clp)
|
||||
struct nfs41_bind_conn_to_session_args *args)
|
||||
{
|
||||
struct compound_hdr hdr = {
|
||||
.minorversion = clp->cl_mvops->minor_version,
|
||||
.minorversion = args->client->cl_mvops->minor_version,
|
||||
};
|
||||
|
||||
encode_compound_hdr(xdr, req, &hdr);
|
||||
encode_bind_conn_to_session(xdr, clp->cl_session, &hdr);
|
||||
encode_bind_conn_to_session(xdr, args, &hdr);
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
@ -5613,7 +5613,7 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr,
|
||||
|
||||
status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
|
||||
if (!status)
|
||||
status = decode_sessionid(xdr, &res->session->sess_id);
|
||||
status = decode_sessionid(xdr, &res->sessionid);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
|
||||
@ -5641,12 +5641,10 @@ static int decode_create_session(struct xdr_stream *xdr,
|
||||
{
|
||||
__be32 *p;
|
||||
int status;
|
||||
struct nfs_client *clp = res->client;
|
||||
struct nfs4_session *session = clp->cl_session;
|
||||
|
||||
status = decode_op_hdr(xdr, OP_CREATE_SESSION);
|
||||
if (!status)
|
||||
status = decode_sessionid(xdr, &session->sess_id);
|
||||
status = decode_sessionid(xdr, &res->sessionid);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
|
||||
@ -5654,13 +5652,13 @@ static int decode_create_session(struct xdr_stream *xdr,
|
||||
p = xdr_inline_decode(xdr, 8);
|
||||
if (unlikely(!p))
|
||||
goto out_overflow;
|
||||
clp->cl_seqid = be32_to_cpup(p++);
|
||||
session->flags = be32_to_cpup(p);
|
||||
res->seqid = be32_to_cpup(p++);
|
||||
res->flags = be32_to_cpup(p);
|
||||
|
||||
/* Channel attributes */
|
||||
status = decode_chan_attrs(xdr, &session->fc_attrs);
|
||||
status = decode_chan_attrs(xdr, &res->fc_attrs);
|
||||
if (!status)
|
||||
status = decode_chan_attrs(xdr, &session->bc_attrs);
|
||||
status = decode_chan_attrs(xdr, &res->bc_attrs);
|
||||
return status;
|
||||
out_overflow:
|
||||
print_overflow_msg(__func__, xdr);
|
||||
|
@ -344,6 +344,10 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
||||
struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
|
||||
struct xdr_stream *xdr,
|
||||
gfp_t gfp_flags);
|
||||
void pnfs_layout_mark_request_commit(struct nfs_page *req,
|
||||
struct pnfs_layout_segment *lseg,
|
||||
struct nfs_commit_info *cinfo,
|
||||
u32 ds_commit_idx);
|
||||
|
||||
static inline bool nfs_have_layout(struct inode *inode)
|
||||
{
|
||||
|
@ -838,3 +838,33 @@ out_err:
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr);
|
||||
|
||||
void
|
||||
pnfs_layout_mark_request_commit(struct nfs_page *req,
|
||||
struct pnfs_layout_segment *lseg,
|
||||
struct nfs_commit_info *cinfo,
|
||||
u32 ds_commit_idx)
|
||||
{
|
||||
struct list_head *list;
|
||||
struct pnfs_commit_bucket *buckets;
|
||||
|
||||
spin_lock(cinfo->lock);
|
||||
buckets = cinfo->ds->buckets;
|
||||
list = &buckets[ds_commit_idx].written;
|
||||
if (list_empty(list)) {
|
||||
/* Non-empty buckets hold a reference on the lseg. That ref
|
||||
* is normally transferred to the COMMIT call and released
|
||||
* there. It could also be released if the last req is pulled
|
||||
* off due to a rewrite, in which case it will be done in
|
||||
* pnfs_common_clear_request_commit
|
||||
*/
|
||||
WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
|
||||
buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
|
||||
}
|
||||
set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
|
||||
cinfo->ds->nwritten++;
|
||||
spin_unlock(cinfo->lock);
|
||||
|
||||
nfs_request_add_commit_list(req, list, cinfo);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
|
||||
|
@ -789,13 +789,8 @@ nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
|
||||
nfs_list_add_request(req, dst);
|
||||
cinfo->mds->ncommit++;
|
||||
spin_unlock(cinfo->lock);
|
||||
if (!cinfo->dreq) {
|
||||
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
|
||||
inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
|
||||
BDI_RECLAIMABLE);
|
||||
__mark_inode_dirty(req->wb_context->dentry->d_inode,
|
||||
I_DIRTY_DATASYNC);
|
||||
}
|
||||
if (!cinfo->dreq)
|
||||
nfs_mark_page_unstable(req->wb_page);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_request_add_commit_list);
|
||||
|
||||
@ -1605,11 +1600,8 @@ void nfs_retry_commit(struct list_head *page_list,
|
||||
req = nfs_list_entry(page_list->next);
|
||||
nfs_list_remove_request(req);
|
||||
nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx);
|
||||
if (!cinfo->dreq) {
|
||||
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
|
||||
dec_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
|
||||
BDI_RECLAIMABLE);
|
||||
}
|
||||
if (!cinfo->dreq)
|
||||
nfs_clear_page_commit(req->wb_page);
|
||||
nfs_unlock_and_release_request(req);
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,6 @@ struct nfs_inode {
|
||||
/* NFSv4 state */
|
||||
struct list_head open_states;
|
||||
struct nfs_delegation __rcu *delegation;
|
||||
fmode_t delegation_state;
|
||||
struct rw_semaphore rwsem;
|
||||
|
||||
/* pNFS layout information */
|
||||
|
@ -1167,8 +1167,15 @@ struct nfs41_impl_id {
|
||||
struct nfstime4 date;
|
||||
};
|
||||
|
||||
struct nfs41_bind_conn_to_session_args {
|
||||
struct nfs_client *client;
|
||||
struct nfs4_sessionid sessionid;
|
||||
u32 dir;
|
||||
bool use_conn_in_rdma_mode;
|
||||
};
|
||||
|
||||
struct nfs41_bind_conn_to_session_res {
|
||||
struct nfs4_session *session;
|
||||
struct nfs4_sessionid sessionid;
|
||||
u32 dir;
|
||||
bool use_conn_in_rdma_mode;
|
||||
};
|
||||
@ -1185,6 +1192,8 @@ struct nfs41_exchange_id_res {
|
||||
|
||||
struct nfs41_create_session_args {
|
||||
struct nfs_client *client;
|
||||
u64 clientid;
|
||||
uint32_t seqid;
|
||||
uint32_t flags;
|
||||
uint32_t cb_program;
|
||||
struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
|
||||
@ -1192,7 +1201,11 @@ struct nfs41_create_session_args {
|
||||
};
|
||||
|
||||
struct nfs41_create_session_res {
|
||||
struct nfs_client *client;
|
||||
struct nfs4_sessionid sessionid;
|
||||
uint32_t seqid;
|
||||
uint32_t flags;
|
||||
struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
|
||||
struct nfs4_channel_attrs bc_attrs; /* Back Channel */
|
||||
};
|
||||
|
||||
struct nfs41_reclaim_complete_args {
|
||||
@ -1351,7 +1364,7 @@ struct nfs_commit_completion_ops {
|
||||
};
|
||||
|
||||
struct nfs_commit_info {
|
||||
spinlock_t *lock;
|
||||
spinlock_t *lock; /* inode->i_lock */
|
||||
struct nfs_mds_commit_info *mds;
|
||||
struct pnfs_ds_commit_info *ds;
|
||||
struct nfs_direct_req *dreq; /* O_DIRECT request */
|
||||
|
@ -89,8 +89,11 @@ void rpc_free_iostats(struct rpc_iostats *);
|
||||
static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
|
||||
static inline void rpc_count_iostats(const struct rpc_task *task,
|
||||
struct rpc_iostats *stats) {}
|
||||
static inline void rpc_count_iostats_metrics(const struct rpc_task *,
|
||||
struct rpc_iostats *) {}
|
||||
static inline void rpc_count_iostats_metrics(const struct rpc_task *task,
|
||||
struct rpc_iostats *stats)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
|
||||
static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
|
||||
|
||||
|
@ -309,12 +309,15 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
struct svc_serv *bc_serv = xprt->bc_serv;
|
||||
|
||||
spin_lock(&xprt->bc_pa_lock);
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
spin_unlock(&xprt->bc_pa_lock);
|
||||
|
||||
req->rq_private_buf.len = copied;
|
||||
set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
|
||||
|
||||
dprintk("RPC: add callback request to list\n");
|
||||
spin_lock(&bc_serv->sv_cb_lock);
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
|
||||
wake_up(&bc_serv->sv_cb_waitq);
|
||||
spin_unlock(&bc_serv->sv_cb_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user