X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=29a276fb5ee0b1d6f3ccfa06b696b428589efa92;hb=6a14f02fb2e18e66bbfd48ff3c5a7a5b677b51ed;hp=8c408b2cd3394a63f6c5af13664f36f3fbd3f55f;hpb=83aa785d927875e69ca4afd58fb53ffc84f24413;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index 8c408b2..29a276f 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -1042,6 +1042,65 @@ static void nfs_pwrite_cb(struct rpc_context *rpc _U_, int status, void *command free_nfs_cb_data(data); } +static void nfs_pwrite_mcb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +{ + struct nfs_mcb_data *mdata = private_data; + struct nfs_cb_data *data = mdata->data; + struct nfs_context *nfs = data->nfs; + WRITE3res *res; + + data->num_calls--; + + if (status == RPC_STATUS_ERROR) { + /* flag the failure but do not invoke callback until we have received all responses */ + data->error = 1; + } + if (status == RPC_STATUS_CANCEL) { + /* flag the cancellation but do not invoke callback until we have received all responses */ + data->cancel = 1; + } + + if (status == RPC_STATUS_SUCCESS) { + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); + data->error = 1; + } else { + if (res->WRITE3res_u.resok.count > 0) { + if ((unsigned)data->max_offset < mdata->offset + res->WRITE3res_u.resok.count) { + data->max_offset = mdata->offset + res->WRITE3res_u.resok.count; + } + } + } + } + + if (data->num_calls > 0) { + /* still waiting for more replies */ + free(mdata); + return; + } + + if (data->error != 0) { + data->cb(-EFAULT, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + free(mdata); + return; + } + if (data->cancel != 0) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + free(mdata); + return; + } + + data->nfsfh->offset = data->max_offset; + data->cb(data->max_offset - data->start_offset, nfs, NULL, data->private_data); + + free_nfs_cb_data(data); + free(mdata); +} + + int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; @@ -1058,12 +1117,54 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, data->nfsfh = nfsfh; nfsfh->offset = offset; - if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - free_nfs_cb_data(data); - return -1; + + if (count <= nfs_get_writemax(nfs)) { + if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + return 0; + } + + /* trying to write more than maximum server write size, we has to chop it up into smaller + * chunks. + * we send all writes in parallell so that performance is still good. + */ + data->max_offset = offset; + data->start_offset = offset; + + while (count > 0) { + size_t writecount = count; + struct nfs_mcb_data *mdata; + + if (writecount > nfs_get_writemax(nfs)) { + writecount = nfs_get_writemax(nfs); + } + + mdata = malloc(sizeof(struct nfs_mcb_data)); + if (mdata == NULL) { + rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure"); + return -1; + } + memset(mdata, 0, sizeof(struct nfs_mcb_data)); + mdata->data = data; + mdata->offset = offset; + mdata->count = writecount; + + if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_mcb, &nfsfh->fh, &buf[offset - data->start_offset], offset, writecount, nfsfh->is_sync?FILE_SYNC:UNSTABLE, mdata) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free(mdata); + return -1; + } + + count -= writecount; + offset += writecount; + data->num_calls++; } + return 0; } @@ -1901,9 +2002,7 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *comm FSSTAT3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; -#ifndef WIN32 struct statvfs svfs; -#endif/*WIN32*/ if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); @@ -1924,7 +2023,6 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *comm return; } -#ifndef WIN32 svfs.f_bsize = 4096; svfs.f_frsize = 4096; svfs.f_blocks = res->FSSTAT3res_u.resok.tbytes/4096; @@ -1938,9 +2036,6 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *comm svfs.f_namemax = 256; data->cb(0, nfs, &svfs, data->private_data); -#else - data->cb(0, nfs,NULL, data->private_data); -#endif/*WIN32*/ free_nfs_cb_data(data); } @@ -2910,7 +3005,11 @@ size_t nfs_get_readmax(struct nfs_context *nfs) */ size_t nfs_get_writemax(struct nfs_context *nfs) { - return nfs->writemax; + /* Some XDR libraries can not marshall PDUs bigger than this */ + if (nfs->writemax < 32768) { + return nfs->writemax; + } + return 32768; } void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) @@ -3103,35 +3202,3 @@ const char *nfs_get_export(struct nfs_context *nfs) { return nfs->export; } - -#if defined(WIN32) -int poll(struct pollfd *fds, int nfsd, int timeout) -{ - fd_set rfds, wfds, efds; - int ret; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - if (fds->events & POLLIN) { - FD_SET(fds->fd, &rfds); - } - if (fds->events & POLLOUT) { - FD_SET(fds->fd, &wfds); - } - FD_SET(fds->fd, &efds); - select(fds->fd + 1, &rfds, &wfds, &efds, NULL); - fds->revents = 0; - if (FD_ISSET(fds->fd, &rfds)) { - fds->revents |= POLLIN; - } - if (FD_ISSET(fds->fd, &wfds)) { - fds->revents |= POLLOUT; - } - if (FD_ISSET(fds->fd, &efds)) { - fds->revents |= POLLHUP; - } - return 1; -} -#endif -