Merge pull request #89 from rosslagerwall/create-trunc

Support use of O_TRUNC with nfs_create
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2014-07-20 11:13:04 -07:00
commit 0672f75b57
2 changed files with 80 additions and 8 deletions

View File

@ -330,7 +330,7 @@ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *
* Async open(<filename>)
*
* mode is a combination of the flags :
* O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND
* O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND, O_TRUNC
*
* Function returns
* 0 : The operation was initiated. Once the operation finishes, the callback will be invoked.
@ -341,6 +341,7 @@ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *
* O_RDONLY
* O_WRONLY
* O_RDWR
* O_SYNC
* O_TRUNC (Only valid with O_RDWR or O_WRONLY. Ignored otherwise.)
*
* When the callback is invoked, status indicates the result:
@ -689,6 +690,7 @@ EXTERN int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct
* O_APPEND
* O_SYNC
* O_EXCL
* O_TRUNC
*
* Function returns
* 0 : The operation was initiated. Once the operation finishes, the callback will be invoked.

View File

@ -696,6 +696,16 @@ static void free_nfs_cb_data(struct nfs_cb_data *data)
free(data);
}
static void free_nfsfh(struct nfsfh *nfsfh)
{
if (nfsfh->fh.data.data_val != NULL) {
free(nfsfh->fh.data.data_val);
nfsfh->fh.data.data_val = NULL;
}
free(nfsfh->ra.buf);
free(nfsfh);
}
static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
@ -2135,13 +2145,7 @@ int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count
int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
{
if (nfsfh->fh.data.data_val != NULL){
free(nfsfh->fh.data.data_val);
nfsfh->fh.data.data_val = NULL;
}
free(nfsfh->ra.buf);
free(nfsfh);
free_nfsfh(nfsfh);
cb(0, nfs, NULL, private_data);
return 0;
};
@ -2541,6 +2545,41 @@ static void free_create_cb_data(void *ptr)
free(data);
}
static void nfs_create_trunc_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
struct nfsfh *nfsfh;
SETATTR3res *res;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR) {
data->cb(-EFAULT, nfs, command_data, data->private_data);
free_nfs_cb_data(data);
free_nfsfh(nfsfh);
return;
}
if (status == RPC_STATUS_CANCEL) {
data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
free_nfs_cb_data(data);
free_nfsfh(nfsfh);
return;
}
res = command_data;
if (res->status != NFS3_OK) {
rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
free_nfsfh(nfsfh);
return;
}
data->cb(0, nfs, data->nfsfh, data->private_data);
free_nfs_cb_data(data);
}
static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
LOOKUP3res *res;
@ -2591,8 +2630,39 @@ static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_d
/* copy the filehandle */
nfsfh->fh.data.data_len = res->LOOKUP3res_u.resok.object.data.data_len;
nfsfh->fh.data.data_val = malloc(nfsfh->fh.data.data_len);
if (nfsfh->fh.data.data_val == NULL) {
rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh structure");
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
free(nfsfh);
return -1;
}
memcpy(nfsfh->fh.data.data_val, res->LOOKUP3res_u.resok.object.data.data_val, nfsfh->fh.data.data_len);
/* Try to truncate it if we were requested to */
if (cb_data->flags & O_TRUNC) {
SETATTR3args args;
data->nfsfh = nfsfh;
memset(&args, 0, sizeof(SETATTR3args));
args.object = nfsfh->fh;
args.new_attributes.size.set_it = 1;
args.new_attributes.size.set_size3_u.size = 0;
if (rpc_nfs3_setattr_async(nfs->rpc, nfs_create_trunc_cb,
&args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send "
"SETATTR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc),
data->private_data);
free_nfs_cb_data(data);
free_nfsfh(nfsfh);
return;
}
return;
}
data->cb(0, nfs, nfsfh, data->private_data);
free_nfs_cb_data(data);
}