add nfs_umount() which will unregister the client from the mount daemon
This is only implemented for v3 since there is no mount protocol in v4. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>libnfs-4.0.0-vitalif
parent
56287de123
commit
9e63589591
|
@ -122,6 +122,7 @@ int main(int argc, char *argv[])
|
|||
if (nfsfh) {
|
||||
nfs_close(nfs, nfsfh);
|
||||
}
|
||||
nfs_umount(nfs);
|
||||
if (url) {
|
||||
nfs_destroy_url(url);
|
||||
}
|
||||
|
|
|
@ -469,6 +469,7 @@ int nfs3_symlink_async(struct nfs_context *nfs, const char *oldpath,
|
|||
const char *newpath, nfs_cb cb, void *private_data);
|
||||
int nfs3_truncate_async(struct nfs_context *nfs, const char *path,
|
||||
uint64_t length, nfs_cb cb, void *private_data);
|
||||
int nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data);
|
||||
int nfs3_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
|
||||
void *private_data);
|
||||
int nfs3_utime_async(struct nfs_context *nfs, const char *path,
|
||||
|
|
|
@ -316,6 +316,39 @@ EXTERN int nfs_mount(struct nfs_context *nfs, const char *server,
|
|||
const char *exportname);
|
||||
|
||||
|
||||
/*
|
||||
* UNMOUNT THE EXPORT
|
||||
*/
|
||||
/*
|
||||
* Async nfs umount.
|
||||
* For NFSv4 this is a NO-OP.
|
||||
* For NFSv3 this function returns unregisters the mount from the MOUNT Daemon.
|
||||
*
|
||||
* 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:
|
||||
* 0 : Success.
|
||||
* data is NULL
|
||||
* -errno : An error occured.
|
||||
* data is the error string.
|
||||
*/
|
||||
EXTERN int nfs_umount_async(struct nfs_context *nfs, nfs_cb cb,
|
||||
void *private_data);
|
||||
/*
|
||||
* Sync nfs umount.
|
||||
* For NFSv4 this is a NO-OP.
|
||||
* For NFSv3 this function returns unregisters the mount from the MOUNT Daemon.
|
||||
*
|
||||
* Function returns
|
||||
* 0 : The operation was successful.
|
||||
* -errno : The command failed.
|
||||
*/
|
||||
EXTERN int nfs_umount(struct nfs_context *nfs);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -228,6 +228,57 @@ nfs_mount(struct nfs_context *nfs, const char *server, const char *export)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* unregister the mount
|
||||
*/
|
||||
static void
|
||||
umount_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
|
||||
{
|
||||
struct sync_cb_data *cb_data = private_data;
|
||||
|
||||
cb_data->is_finished = 1;
|
||||
cb_data->status = status;
|
||||
|
||||
if (status < 0) {
|
||||
nfs_set_error(nfs, "%s: %s",
|
||||
__FUNCTION__, nfs_get_error(nfs));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nfs_umount(struct nfs_context *nfs)
|
||||
{
|
||||
struct sync_cb_data cb_data;
|
||||
struct rpc_context *rpc = nfs_get_rpc_context(nfs);
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
cb_data.is_finished = 0;
|
||||
|
||||
if (nfs_umount_async(nfs, umount_cb, &cb_data) != 0) {
|
||||
nfs_set_error(nfs, "nfs_umount_async failed. %s",
|
||||
nfs_get_error(nfs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait_for_nfs_reply(nfs, &cb_data);
|
||||
|
||||
/* Dont want any more callbacks even if the socket is closed */
|
||||
rpc->connect_cb = NULL;
|
||||
|
||||
/* Ensure that no RPCs are pending. In error case (e.g. timeout in
|
||||
* wait_for_nfs_reply()) we can disconnect; in success case all RPCs
|
||||
* are completed by definition.
|
||||
*/
|
||||
if (cb_data.status) {
|
||||
rpc_disconnect(rpc, "failed mount");
|
||||
}
|
||||
|
||||
return cb_data.status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* stat()
|
||||
*/
|
||||
|
|
|
@ -101,6 +101,8 @@ nfs_symlink
|
|||
nfs_symlink_async
|
||||
nfs_truncate
|
||||
nfs_truncate_async
|
||||
nfs_umount
|
||||
nfs_umount_async
|
||||
nfs_unlink
|
||||
nfs_unlink_async
|
||||
nfs_utime
|
||||
|
|
20
lib/libnfs.c
20
lib/libnfs.c
|
@ -865,6 +865,26 @@ nfs_mount_async(struct nfs_context *nfs, const char *server,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Async call for umounting an nfs share
|
||||
*/
|
||||
int
|
||||
nfs_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data)
|
||||
{
|
||||
switch (nfs->version) {
|
||||
case NFS_V3:
|
||||
return nfs3_umount_async(nfs, cb, private_data);
|
||||
case NFS_V4:
|
||||
/* umount is a no-op in v4 */
|
||||
(*cb)(0, nfs, NULL, private_data);
|
||||
return 0;
|
||||
default:
|
||||
nfs_set_error(nfs, "%s does not support NFSv%d",
|
||||
__FUNCTION__, nfs->version);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nfs_normalize_path(struct nfs_context *nfs, char *path)
|
||||
{
|
||||
|
|
86
lib/nfs_v3.c
86
lib/nfs_v3.c
|
@ -1152,6 +1152,92 @@ nfs3_mount_async(struct nfs_context *nfs, const char *server,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nfs3_umount_2_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;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (check_nfs3_error(nfs, status, data, command_data)) {
|
||||
free_nfs_cb_data(data);
|
||||
return;
|
||||
}
|
||||
|
||||
rpc_disconnect(rpc, "umount");
|
||||
data->cb(0, nfs, NULL, data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
}
|
||||
|
||||
static void
|
||||
nfs3_umount_1_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;
|
||||
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (check_nfs3_error(nfs, status, data, command_data)) {
|
||||
free_nfs_cb_data(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rpc_mount3_umnt_async(rpc, nfs3_umount_2_cb, nfs->export,
|
||||
data) != 0) {
|
||||
nfs_set_error(nfs, "%s: %s.", __FUNCTION__, nfs_get_error(nfs));
|
||||
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
|
||||
free_nfs_cb_data(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nfs3_umount_async(struct nfs_context *nfs, nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs_cb_data *data;
|
||||
|
||||
data = malloc(sizeof(struct nfs_cb_data));
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "out of memory. failed to allocate "
|
||||
"memory for nfs mount data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(struct nfs_cb_data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
rpc_disconnect(nfs->rpc, "umount");
|
||||
|
||||
if (nfs->mountport) {
|
||||
if (rpc_connect_port_async(nfs->rpc, nfs->server,
|
||||
nfs->mountport,
|
||||
MOUNT_PROGRAM, MOUNT_V3,
|
||||
nfs3_umount_1_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "Failed to start connection. %s",
|
||||
nfs_get_error(nfs));
|
||||
free_nfs_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rpc_connect_program_async(nfs->rpc, nfs->server,
|
||||
MOUNT_PROGRAM, MOUNT_V3,
|
||||
nfs3_umount_1_cb, data) != 0) {
|
||||
nfs_set_error(nfs, "Failed to start connection. %s",
|
||||
nfs_get_error(nfs));
|
||||
free_nfs_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct nfs_link_data {
|
||||
char *oldpath;
|
||||
|
|
Loading…
Reference in New Issue