Allocate larger buffer for write operations in NFS4

The NFS4 pwrite operations contains a memory corruption if a write
is large than 4KB. The reason is that the buffer allocated within
nfs4_compund_async has a size of 4K and it does not account
for the size of the write buffer. To fix this the patch
padds a rpc_allocate_ndu2 function which an additional parameter
as an extra hint for the allocation.
master
Dirk Meister 2020-05-18 20:57:06 -07:00
parent 394b185486
commit 483be177fe
3 changed files with 48 additions and 10 deletions

View File

@ -2270,6 +2270,28 @@ struct COMPOUND4args;
EXTERN int rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args,
void *private_data);
/*
* Call NFS4/COMPOUND with extra allocation.
* Function returns
* 0 : The command was queued successfully. The callback will be invoked once
* the command completes.
* <0 : An error occured when trying to queue the command.
* The callback will not be invoked.
*
* When the callback is invoked, status indicates the result:
* RPC_STATUS_SUCCESS : We got a successful response from the server.
* data is COMPOUND4res *.
* RPC_STATUS_ERROR : The command failed with an error.
* data is the error string.
* RPC_STATUS_CANCEL : The command was cancelled.
* data is NULL.
*/
struct COMPOUND4args;
EXTERN int rpc_nfs4_compound_async2(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args,
void *private_data,
size_t alloc_hint);
/*
* Call <generic>/NULL

View File

@ -2852,10 +2852,12 @@ nfs4_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh,
args.argarray.argarray_len = i;
args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_pwrite_cb, &args,
data) != 0) {
if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_pwrite_cb, &args,
data, count) != 0) {
nfs_set_error(nfs, "PWRITE "
"failed: %s", rpc_get_error(nfs->rpc));
free_nfs4_cb_data(data);
return -1;
return -EIO;
}
return 0;
@ -2957,10 +2959,12 @@ nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count,
data->filler.blob1.len = (int)count;
data->filler.blob1.free = NULL;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_write_append_cb,
&args, data) != 0) {
if (rpc_nfs4_compound_async2(nfs->rpc, nfs4_write_append_cb,
&args, data, count) != 0) {
nfs_set_error(nfs, "PWRITE "
"failed: %s", rpc_get_error(nfs->rpc));
free_nfs4_cb_data(data);
return -1;
return -EIO;
}
return 0;

View File

@ -202,14 +202,17 @@ rpc_nfs4_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
}
int
rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args, void *private_data)
rpc_nfs4_compound_async2(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args,
void *private_data,
size_t alloc_hint)
{
struct rpc_pdu *pdu;
pdu = rpc_allocate_pdu(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_COMPOUND,
pdu = rpc_allocate_pdu2(rpc, NFS4_PROGRAM, NFS_V4, NFSPROC4_COMPOUND,
cb, private_data, (zdrproc_t)zdr_COMPOUND4res,
sizeof(COMPOUND4res));
sizeof(COMPOUND4res),
alloc_hint);
if (pdu == NULL) {
rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for "
"NFS4/COMPOUND call");
@ -230,3 +233,12 @@ rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
return 0;
}
int
rpc_nfs4_compound_async(struct rpc_context *rpc, rpc_cb cb,
struct COMPOUND4args *args,
void *private_data)
{
return rpc_nfs4_compound_async2(rpc, cb, args, private_data, 0);
}