NFS Client Bugfixes for Linux 6.6
Bugfixes: * Various O_DIRECT related fixes from Trond * Error handling * Locking issues * Use the correct commit infor for joining page groups * Fixes for rescheduling IO * Sunrpc bad verifier fixes * Report EINVAL errors from connect() * Revalidate creds that the server has rejected * Revert "SUNRPC: Fail faster on bad verifier" * Fix pNFS session trunking when MDS=DS * Fix zero-value filehandles for post-open getattr operations * Fix compiler warning about tautological comparisons * Revert "SUNRPC: clean up integer overflow check" before Trond's fix -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmUIjesACgkQ18tUv7Cl QOv/MBAAxxZrW45qlTsEMvhnFXu1cvt08IdqivWURuSxK6oV31tARMqw00MxzhsF ubNX4hynDNmsWYJLryHTTGwUJzaNQOhAGjU46AhwFgS3Lj2wefeuR3IYuEDgQcHF 8uXrrT/GWRIG4a/Uu1IxodfgMvgUPV+HGFc5BQFGkXGqPQdgbdxBDtOtyU1QlmaV rqKnxPgUibEZwVoz8+PNsN+pwNjKSaSR3pH53KKS6HUBAM69sT4jJiJDO/UGSlzb F9U1DHPeyltHXVAaQXUjHlsjh49NbIjzD5/T8xKWscvS7rbQFCcJkUl3MBHyvSEr eixx7muqOMCEm4lNFJqHIY7XrEN+50wi92tKj05Bz9wrnp4L84cxSV/KNZrKNA3T LCeIm4DGynPcLPopEUm9lqZMrabwvdV4wZSiybB6p/F/5ksVyaMnwTLzZZ1+NhkB OglNhF4L6m18/Ai/bY6XOixzgzWfcmYfXRhq7YoeO/JSvixG9Sk2crC6ryjWadgo xbitjjCYXHl3MUkH2TcaQoMGFhmvSShXg//5YXpxm3/0C3EVPa44T7/aFJqelL2p kkVsLcjcevAOwBHxehYLofL6c3GhLqRnwmTV7yqgJqfZf8uGxeQhXCMqOmv57/c0 3iJJM4Llb14B+t3xl3T8MotT4WejzlHDnJKrscipfXJwRT7UDIM= =M6aI -----END PGP SIGNATURE----- Merge tag 'nfs-for-6.6-2' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client fixes from Anna Schumaker: "Various O_DIRECT related fixes from Trond: - Error handling - Locking issues - Use the correct commit info for joining page groups - Fixes for rescheduling IO Sunrpc bad verifier fixes: - Report EINVAL errors from connect() - Revalidate creds that the server has rejected - Revert "SUNRPC: Fail faster on bad verifier" Misc: - Fix pNFS session trunking when MDS=DS - Fix zero-value filehandles for post-open getattr operations - Fix compiler warning about tautological comparisons - Revert 'SUNRPC: clean up integer overflow check' before Trond's fix" * tag 'nfs-for-6.6-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: SUNRPC: Silence compiler complaints about tautological comparisons Revert "SUNRPC: clean up integer overflow check" NFSv4.1: fix zero value filehandle in post open getattr NFSv4.1: fix pnfs MDS=DS session trunking Revert "SUNRPC: Fail faster on bad verifier" SUNRPC: Mark the cred for revalidation if the server rejects it NFS/pNFS: Report EINVAL errors from connect() to the server NFS: More fixes for nfs_direct_write_reschedule_io() NFS: Use the correct commit info in nfs_join_page_group() NFS: More O_DIRECT accounting fixes for error paths NFS: Fix O_DIRECT locking issues NFS: Fix error handling for O_DIRECT write scheduling
This commit is contained in:
commit
2cf0f71562
134
fs/nfs/direct.c
134
fs/nfs/direct.c
|
@ -93,12 +93,10 @@ nfs_direct_handle_truncated(struct nfs_direct_req *dreq,
|
|||
dreq->max_count = dreq_len;
|
||||
if (dreq->count > dreq_len)
|
||||
dreq->count = dreq_len;
|
||||
|
||||
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
|
||||
dreq->error = hdr->error;
|
||||
else /* Clear outstanding error if this is EOF */
|
||||
dreq->error = 0;
|
||||
}
|
||||
|
||||
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && !dreq->error)
|
||||
dreq->error = hdr->error;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -120,6 +118,18 @@ nfs_direct_count_bytes(struct nfs_direct_req *dreq,
|
|||
dreq->count = dreq_len;
|
||||
}
|
||||
|
||||
static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
|
||||
struct nfs_page *req)
|
||||
{
|
||||
loff_t offs = req_offset(req);
|
||||
size_t req_start = (size_t)(offs - dreq->io_start);
|
||||
|
||||
if (req_start < dreq->max_count)
|
||||
dreq->max_count = req_start;
|
||||
if (req_start < dreq->count)
|
||||
dreq->count = req_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_swap_rw - NFS address space operation for swap I/O
|
||||
* @iocb: target I/O control block
|
||||
|
@ -488,7 +498,9 @@ static void nfs_direct_add_page_head(struct list_head *list,
|
|||
kref_get(&head->wb_kref);
|
||||
}
|
||||
|
||||
static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
|
||||
static void nfs_direct_join_group(struct list_head *list,
|
||||
struct nfs_commit_info *cinfo,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct nfs_page *req, *subreq;
|
||||
|
||||
|
@ -510,7 +522,7 @@ static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
|
|||
nfs_release_request(subreq);
|
||||
}
|
||||
} while ((subreq = subreq->wb_this_page) != req);
|
||||
nfs_join_page_group(req, inode);
|
||||
nfs_join_page_group(req, cinfo, inode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,20 +540,15 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
|
|||
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
|
||||
{
|
||||
struct nfs_pageio_descriptor desc;
|
||||
struct nfs_page *req, *tmp;
|
||||
struct nfs_page *req;
|
||||
LIST_HEAD(reqs);
|
||||
struct nfs_commit_info cinfo;
|
||||
LIST_HEAD(failed);
|
||||
|
||||
nfs_init_cinfo_from_dreq(&cinfo, dreq);
|
||||
nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
|
||||
|
||||
nfs_direct_join_group(&reqs, dreq->inode);
|
||||
nfs_direct_join_group(&reqs, &cinfo, dreq->inode);
|
||||
|
||||
dreq->count = 0;
|
||||
dreq->max_count = 0;
|
||||
list_for_each_entry(req, &reqs, wb_list)
|
||||
dreq->max_count += req->wb_bytes;
|
||||
nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo);
|
||||
get_dreq(dreq);
|
||||
|
||||
|
@ -549,27 +556,40 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
|
|||
&nfs_direct_write_completion_ops);
|
||||
desc.pg_dreq = dreq;
|
||||
|
||||
list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
|
||||
while (!list_empty(&reqs)) {
|
||||
req = nfs_list_entry(reqs.next);
|
||||
/* Bump the transmission count */
|
||||
req->wb_nio++;
|
||||
if (!nfs_pageio_add_request(&desc, req)) {
|
||||
nfs_list_move_request(req, &failed);
|
||||
spin_lock(&cinfo.inode->i_lock);
|
||||
dreq->flags = 0;
|
||||
if (desc.pg_error < 0)
|
||||
spin_lock(&dreq->lock);
|
||||
if (dreq->error < 0) {
|
||||
desc.pg_error = dreq->error;
|
||||
} else if (desc.pg_error != -EAGAIN) {
|
||||
dreq->flags = 0;
|
||||
if (!desc.pg_error)
|
||||
desc.pg_error = -EIO;
|
||||
dreq->error = desc.pg_error;
|
||||
else
|
||||
dreq->error = -EIO;
|
||||
spin_unlock(&cinfo.inode->i_lock);
|
||||
} else
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
spin_unlock(&dreq->lock);
|
||||
break;
|
||||
}
|
||||
nfs_release_request(req);
|
||||
}
|
||||
nfs_pageio_complete(&desc);
|
||||
|
||||
while (!list_empty(&failed)) {
|
||||
req = nfs_list_entry(failed.next);
|
||||
while (!list_empty(&reqs)) {
|
||||
req = nfs_list_entry(reqs.next);
|
||||
nfs_list_remove_request(req);
|
||||
nfs_unlock_and_release_request(req);
|
||||
if (desc.pg_error == -EAGAIN) {
|
||||
nfs_mark_request_commit(req, NULL, &cinfo, 0);
|
||||
} else {
|
||||
spin_lock(&dreq->lock);
|
||||
nfs_direct_truncate_request(dreq, req);
|
||||
spin_unlock(&dreq->lock);
|
||||
nfs_release_request(req);
|
||||
}
|
||||
}
|
||||
|
||||
if (put_dreq(dreq))
|
||||
|
@ -589,8 +609,6 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
|||
if (status < 0) {
|
||||
/* Errors in commit are fatal */
|
||||
dreq->error = status;
|
||||
dreq->max_count = 0;
|
||||
dreq->count = 0;
|
||||
dreq->flags = NFS_ODIRECT_DONE;
|
||||
} else {
|
||||
status = dreq->error;
|
||||
|
@ -601,7 +619,12 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
|||
while (!list_empty(&data->pages)) {
|
||||
req = nfs_list_entry(data->pages.next);
|
||||
nfs_list_remove_request(req);
|
||||
if (status >= 0 && !nfs_write_match_verf(verf, req)) {
|
||||
if (status < 0) {
|
||||
spin_lock(&dreq->lock);
|
||||
nfs_direct_truncate_request(dreq, req);
|
||||
spin_unlock(&dreq->lock);
|
||||
nfs_release_request(req);
|
||||
} else if (!nfs_write_match_verf(verf, req)) {
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
/*
|
||||
* Despite the reboot, the write was successful,
|
||||
|
@ -609,7 +632,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
|||
*/
|
||||
req->wb_nio = 0;
|
||||
nfs_mark_request_commit(req, NULL, &cinfo, 0);
|
||||
} else /* Error or match */
|
||||
} else
|
||||
nfs_release_request(req);
|
||||
nfs_unlock_and_release_request(req);
|
||||
}
|
||||
|
@ -662,6 +685,7 @@ static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
|
|||
while (!list_empty(&reqs)) {
|
||||
req = nfs_list_entry(reqs.next);
|
||||
nfs_list_remove_request(req);
|
||||
nfs_direct_truncate_request(dreq, req);
|
||||
nfs_release_request(req);
|
||||
nfs_unlock_and_release_request(req);
|
||||
}
|
||||
|
@ -711,7 +735,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
|
|||
}
|
||||
|
||||
nfs_direct_count_bytes(dreq, hdr);
|
||||
if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags)) {
|
||||
if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags) &&
|
||||
!test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
|
||||
if (!dreq->flags)
|
||||
dreq->flags = NFS_ODIRECT_DO_COMMIT;
|
||||
flags = dreq->flags;
|
||||
|
@ -755,18 +780,23 @@ static void nfs_write_sync_pgio_error(struct list_head *head, int error)
|
|||
static void nfs_direct_write_reschedule_io(struct nfs_pgio_header *hdr)
|
||||
{
|
||||
struct nfs_direct_req *dreq = hdr->dreq;
|
||||
struct nfs_page *req;
|
||||
struct nfs_commit_info cinfo;
|
||||
|
||||
trace_nfs_direct_write_reschedule_io(dreq);
|
||||
|
||||
nfs_init_cinfo_from_dreq(&cinfo, dreq);
|
||||
spin_lock(&dreq->lock);
|
||||
if (dreq->error == 0) {
|
||||
if (dreq->error == 0)
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
/* fake unstable write to let common nfs resend pages */
|
||||
hdr->verf.committed = NFS_UNSTABLE;
|
||||
hdr->good_bytes = hdr->args.offset + hdr->args.count -
|
||||
hdr->io_start;
|
||||
}
|
||||
set_bit(NFS_IOHDR_REDO, &hdr->flags);
|
||||
spin_unlock(&dreq->lock);
|
||||
while (!list_empty(&hdr->pages)) {
|
||||
req = nfs_list_entry(hdr->pages.next);
|
||||
nfs_list_remove_request(req);
|
||||
nfs_unlock_request(req);
|
||||
nfs_mark_request_commit(req, NULL, &cinfo, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
|
||||
|
@ -794,9 +824,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
|||
{
|
||||
struct nfs_pageio_descriptor desc;
|
||||
struct inode *inode = dreq->inode;
|
||||
struct nfs_commit_info cinfo;
|
||||
ssize_t result = 0;
|
||||
size_t requested_bytes = 0;
|
||||
size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
|
||||
bool defer = false;
|
||||
|
||||
trace_nfs_direct_write_schedule_iovec(dreq);
|
||||
|
||||
|
@ -837,17 +869,37 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
|||
break;
|
||||
}
|
||||
|
||||
nfs_lock_request(req);
|
||||
if (!nfs_pageio_add_request(&desc, req)) {
|
||||
result = desc.pg_error;
|
||||
nfs_unlock_and_release_request(req);
|
||||
break;
|
||||
}
|
||||
pgbase = 0;
|
||||
bytes -= req_len;
|
||||
requested_bytes += req_len;
|
||||
pos += req_len;
|
||||
dreq->bytes_left -= req_len;
|
||||
|
||||
if (defer) {
|
||||
nfs_mark_request_commit(req, NULL, &cinfo, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
nfs_lock_request(req);
|
||||
if (nfs_pageio_add_request(&desc, req))
|
||||
continue;
|
||||
|
||||
/* Exit on hard errors */
|
||||
if (desc.pg_error < 0 && desc.pg_error != -EAGAIN) {
|
||||
result = desc.pg_error;
|
||||
nfs_unlock_and_release_request(req);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the error is soft, defer remaining requests */
|
||||
nfs_init_cinfo_from_dreq(&cinfo, dreq);
|
||||
spin_lock(&dreq->lock);
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
spin_unlock(&dreq->lock);
|
||||
nfs_unlock_request(req);
|
||||
nfs_mark_request_commit(req, NULL, &cinfo, 0);
|
||||
desc.pg_error = 0;
|
||||
defer = true;
|
||||
}
|
||||
nfs_direct_release_pages(pagevec, npages);
|
||||
kvfree(pagevec);
|
||||
|
|
|
@ -1235,6 +1235,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
|
|||
case -EPFNOSUPPORT:
|
||||
case -EPROTONOSUPPORT:
|
||||
case -EOPNOTSUPP:
|
||||
case -EINVAL:
|
||||
case -ECONNREFUSED:
|
||||
case -ECONNRESET:
|
||||
case -EHOSTDOWN:
|
||||
|
|
|
@ -417,6 +417,8 @@ static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
|
|||
.net = old->cl_net,
|
||||
.servername = old->cl_hostname,
|
||||
};
|
||||
int max_connect = test_bit(NFS_CS_PNFS, &clp->cl_flags) ?
|
||||
clp->cl_max_connect : old->cl_max_connect;
|
||||
|
||||
if (clp->cl_proto != old->cl_proto)
|
||||
return;
|
||||
|
@ -430,7 +432,7 @@ static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
|
|||
xprt_args.addrlen = clp_salen;
|
||||
|
||||
rpc_clnt_add_xprt(old->cl_rpcclient, &xprt_args,
|
||||
rpc_clnt_test_and_add_xprt, NULL);
|
||||
rpc_clnt_test_and_add_xprt, &max_connect);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1010,6 +1012,8 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
|
|||
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
|
||||
|
||||
__set_bit(NFS_CS_DS, &cl_init.init_flags);
|
||||
__set_bit(NFS_CS_PNFS, &cl_init.init_flags);
|
||||
cl_init.max_connect = NFS_MAX_TRANSPORTS;
|
||||
/*
|
||||
* Set an authflavor equual to the MDS value. Use the MDS nfs_client
|
||||
* cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
|
||||
|
|
|
@ -2703,8 +2703,12 @@ static int _nfs4_proc_open(struct nfs4_opendata *data,
|
|||
return status;
|
||||
}
|
||||
if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
|
||||
struct nfs_fh *fh = &o_res->fh;
|
||||
|
||||
nfs4_sequence_free_slot(&o_res->seq_res);
|
||||
nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, NULL);
|
||||
if (o_arg->claim == NFS4_OPEN_CLAIM_FH)
|
||||
fh = NFS_FH(d_inode(data->dentry));
|
||||
nfs4_proc_getattr(server, fh, o_res->f_attr, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
|
|||
static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
|
||||
static const struct nfs_rw_ops nfs_rw_write_ops;
|
||||
static void nfs_inode_remove_request(struct nfs_page *req);
|
||||
static void nfs_clear_request_commit(struct nfs_page *req);
|
||||
static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
|
||||
struct nfs_page *req);
|
||||
static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
|
||||
struct inode *inode);
|
||||
static struct nfs_page *
|
||||
|
@ -502,8 +503,8 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list,
|
|||
* the (former) group. All subrequests are removed from any write or commit
|
||||
* lists, unlinked from the group and destroyed.
|
||||
*/
|
||||
void
|
||||
nfs_join_page_group(struct nfs_page *head, struct inode *inode)
|
||||
void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct nfs_page *subreq;
|
||||
struct nfs_page *destroy_list = NULL;
|
||||
|
@ -533,7 +534,7 @@ nfs_join_page_group(struct nfs_page *head, struct inode *inode)
|
|||
* Commit list removal accounting is done after locks are dropped */
|
||||
subreq = head;
|
||||
do {
|
||||
nfs_clear_request_commit(subreq);
|
||||
nfs_clear_request_commit(cinfo, subreq);
|
||||
subreq = subreq->wb_this_page;
|
||||
} while (subreq != head);
|
||||
|
||||
|
@ -566,8 +567,10 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)
|
|||
{
|
||||
struct inode *inode = folio_file_mapping(folio)->host;
|
||||
struct nfs_page *head;
|
||||
struct nfs_commit_info cinfo;
|
||||
int ret;
|
||||
|
||||
nfs_init_cinfo_from_inode(&cinfo, inode);
|
||||
/*
|
||||
* A reference is taken only on the head request which acts as a
|
||||
* reference to the whole page group - the group will not be destroyed
|
||||
|
@ -584,7 +587,7 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
nfs_join_page_group(head, inode);
|
||||
nfs_join_page_group(head, &cinfo, inode);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
@ -955,18 +958,16 @@ static void nfs_folio_clear_commit(struct folio *folio)
|
|||
}
|
||||
|
||||
/* Called holding the request lock on @req */
|
||||
static void
|
||||
nfs_clear_request_commit(struct nfs_page *req)
|
||||
static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
|
||||
struct nfs_page *req)
|
||||
{
|
||||
if (test_bit(PG_CLEAN, &req->wb_flags)) {
|
||||
struct nfs_open_context *ctx = nfs_req_openctx(req);
|
||||
struct inode *inode = d_inode(ctx->dentry);
|
||||
struct nfs_commit_info cinfo;
|
||||
|
||||
nfs_init_cinfo_from_inode(&cinfo, inode);
|
||||
mutex_lock(&NFS_I(inode)->commit_mutex);
|
||||
if (!pnfs_clear_request_commit(req, &cinfo)) {
|
||||
nfs_request_remove_commit_list(req, &cinfo);
|
||||
if (!pnfs_clear_request_commit(req, cinfo)) {
|
||||
nfs_request_remove_commit_list(req, cinfo);
|
||||
}
|
||||
mutex_unlock(&NFS_I(inode)->commit_mutex);
|
||||
nfs_folio_clear_commit(nfs_page_to_folio(req));
|
||||
|
|
|
@ -48,6 +48,7 @@ struct nfs_client {
|
|||
#define NFS_CS_NOPING 6 /* - don't ping on connect */
|
||||
#define NFS_CS_DS 7 /* - Server is a DS */
|
||||
#define NFS_CS_REUSEPORT 8 /* - reuse src port on reconnect */
|
||||
#define NFS_CS_PNFS 9 /* - Server used for pnfs */
|
||||
struct sockaddr_storage cl_addr; /* server identifier */
|
||||
size_t cl_addrlen;
|
||||
char * cl_hostname; /* hostname of server */
|
||||
|
|
|
@ -157,7 +157,9 @@ extern void nfs_unlock_request(struct nfs_page *req);
|
|||
extern void nfs_unlock_and_release_request(struct nfs_page *);
|
||||
extern struct nfs_page *nfs_page_group_lock_head(struct nfs_page *req);
|
||||
extern int nfs_page_group_lock_subrequests(struct nfs_page *head);
|
||||
extern void nfs_join_page_group(struct nfs_page *head, struct inode *inode);
|
||||
extern void nfs_join_page_group(struct nfs_page *head,
|
||||
struct nfs_commit_info *cinfo,
|
||||
struct inode *inode);
|
||||
extern int nfs_page_group_lock(struct nfs_page *);
|
||||
extern void nfs_page_group_unlock(struct nfs_page *);
|
||||
extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
|
||||
|
|
|
@ -779,7 +779,9 @@ xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
|
|||
|
||||
if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
|
||||
return -EBADMSG;
|
||||
p = xdr_inline_decode(xdr, size_mul(len, sizeof(*p)));
|
||||
if (U32_MAX >= SIZE_MAX / sizeof(*p) && len > SIZE_MAX / sizeof(*p))
|
||||
return -EBADMSG;
|
||||
p = xdr_inline_decode(xdr, len * sizeof(*p));
|
||||
if (unlikely(!p))
|
||||
return -EBADMSG;
|
||||
if (array == NULL)
|
||||
|
|
|
@ -2725,7 +2725,7 @@ out_unparsable:
|
|||
|
||||
out_verifier:
|
||||
trace_rpc_bad_verifier(task);
|
||||
goto out_err;
|
||||
goto out_garbage;
|
||||
|
||||
out_msg_denied:
|
||||
error = -EACCES;
|
||||
|
@ -2751,6 +2751,7 @@ out_msg_denied:
|
|||
case rpc_autherr_rejectedverf:
|
||||
case rpcsec_gsserr_credproblem:
|
||||
case rpcsec_gsserr_ctxproblem:
|
||||
rpcauth_invalcred(task);
|
||||
if (!task->tk_cred_retry)
|
||||
break;
|
||||
task->tk_cred_retry--;
|
||||
|
@ -2907,19 +2908,22 @@ static const struct rpc_call_ops rpc_cb_add_xprt_call_ops = {
|
|||
* @clnt: pointer to struct rpc_clnt
|
||||
* @xps: pointer to struct rpc_xprt_switch,
|
||||
* @xprt: pointer struct rpc_xprt
|
||||
* @dummy: unused
|
||||
* @in_max_connect: pointer to the max_connect value for the passed in xprt transport
|
||||
*/
|
||||
int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
|
||||
struct rpc_xprt_switch *xps, struct rpc_xprt *xprt,
|
||||
void *dummy)
|
||||
void *in_max_connect)
|
||||
{
|
||||
struct rpc_cb_add_xprt_calldata *data;
|
||||
struct rpc_task *task;
|
||||
int max_connect = clnt->cl_max_connect;
|
||||
|
||||
if (xps->xps_nunique_destaddr_xprts + 1 > clnt->cl_max_connect) {
|
||||
if (in_max_connect)
|
||||
max_connect = *(int *)in_max_connect;
|
||||
if (xps->xps_nunique_destaddr_xprts + 1 > max_connect) {
|
||||
rcu_read_lock();
|
||||
pr_warn("SUNRPC: reached max allowed number (%d) did not add "
|
||||
"transport to server: %s\n", clnt->cl_max_connect,
|
||||
"transport to server: %s\n", max_connect,
|
||||
rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
|
|
Loading…
Reference in New Issue