libnfs.c: always pass the attributes to the callback for recursive lookups

Always pass a fattr3 structure to the callbacks for the internal function
to perform recursive lookups : nfs_lookuppath_async().
This will allow us to access for example the mtime for an object before we
start performing any expensive functions.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2014-06-08 09:45:22 -07:00
parent c63ba81eeb
commit 20379f03fc
1 changed files with 89 additions and 44 deletions

View File

@ -112,7 +112,8 @@ void nfs_free_nfsdir(struct nfsdir *nfsdir)
}
struct nfs_cb_data;
typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data);
typedef int (*continue_func)(struct nfs_context *nfs, fattr3 *attr,
struct nfs_cb_data *data);
struct nfs_cb_data {
struct nfs_context *nfs;
@ -147,7 +148,7 @@ struct nfs_mcb_data {
int update_pos;
};
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr, struct nfs_cb_data *data, struct nfs_fh3 *fh);
void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
{
@ -640,9 +641,6 @@ static void free_nfs_cb_data(struct nfs_cb_data *data)
}
static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
struct nfs_cb_data *data = private_data;
@ -848,6 +846,7 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
LOOKUP3res *res;
fattr3 *attr;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
@ -870,15 +869,17 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm
return;
}
if (nfs_lookup_path_async_internal(nfs, data, &res->LOOKUP3res_u.resok.object) != 0) {
rpc_set_error(nfs->rpc, "Failed to create lookup pdu");
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
return;
}
attr = res->LOOKUP3res_u.resok.obj_attributes.attributes_follow ?
&res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes :
NULL;
/* This function will always invoke the callback and cleanup
* for failures. So no need to check the return value.
*/
nfs_lookup_path_async_internal(nfs, attr, data, &res->LOOKUP3res_u.resok.object);
}
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data, struct nfs_fh3 *fh)
{
char *path, *slash;
LOOKUP3args args;
@ -917,11 +918,10 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb
if (slash != NULL) {
*slash = '/';
}
data->continue_cb(nfs, data);
data->continue_cb(nfs, attr, data);
return 0;
}
memset(&args, 0, sizeof(LOOKUP3args));
args.what.dir = *fh;
args.what.name = path;
@ -1038,9 +1038,45 @@ static int nfs_normalize_path(struct nfs_context *nfs, char *path)
return 0;
}
static void nfs_lookup_path_getattr_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;
GETATTR3res *res;
fattr3 *attr;
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);
return;
}
if (status == RPC_STATUS_CANCEL) {
data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
free_nfs_cb_data(data);
return;
}
res = command_data;
if (res->status != NFS3_OK) {
rpc_set_error(nfs->rpc, "NFS: GETATTR of %s failed with %s(%d)", data->saved_path, 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);
return;
}
attr = &res->GETATTR3res_u.resok.obj_attributes;
/* This function will always invoke the callback and cleanup
* for failures. So no need to check the return value.
*/
nfs_lookup_path_async_internal(nfs, attr, data, &nfs->rootfh);
}
static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), int continue_int)
{
struct nfs_cb_data *data;
struct GETATTR3args args;
if (path[0] == '\0') {
path = ".";
@ -1086,18 +1122,27 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c
}
data->path = data->saved_path;
if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
/* return 0 here since the callback will be invoked if there is a failure */
if (data->path[0]) {
/* This function will always invoke the callback and cleanup
* for failures. So no need to check the return value.
*/
nfs_lookup_path_async_internal(nfs, NULL, data, &nfs->rootfh);
return 0;
}
/* We have a request for "", so just perform a GETATTR3 so we can
* return the attributes to the caller.
*/
memset(&args, 0, sizeof(GETATTR3args));
args.object = nfs->rootfh;
if (rpc_nfs3_getattr_async(nfs->rpc, nfs_lookup_path_getattr_cb, &args, data) != 0) {
free_nfs_cb_data(data);
return -1;
}
return 0;
}
/*
* Async stat()
*/
@ -1159,7 +1204,7 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat
free_nfs_cb_data(data);
}
static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_stat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct GETATTR3args args;
@ -1239,7 +1284,7 @@ static void nfs_stat64_1_cb(struct rpc_context *rpc, int status, void *command_d
free_nfs_cb_data(data);
}
static int nfs_stat64_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_stat64_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct GETATTR3args args;
@ -1419,7 +1464,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data,
free_nfs_cb_data(data);
}
static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_open_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
int nfsmode = 0;
ACCESS3args args;
@ -1463,7 +1508,7 @@ int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb
/*
* Async chdir()
*/
static int nfs_chdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_chdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
/* steal saved_path */
free(nfs->cwd);
@ -2127,7 +2172,7 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t l
/*
* Async truncate()
*/
static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_truncate_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
uint64_t offset = data->continue_int;
struct nfsfh nfsfh;
@ -2198,7 +2243,7 @@ static void nfs_mkdir_cb(struct rpc_context *rpc, int status, void *command_data
free_nfs_cb_data(data);
}
static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_mkdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
MKDIR3args args;
@ -2289,7 +2334,7 @@ static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data
free_nfs_cb_data(data);
}
static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_rmdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
RMDIR3args args;
@ -2434,7 +2479,7 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da
return;
}
static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_creat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
CREATE3args args;
@ -2525,7 +2570,7 @@ static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_dat
free_nfs_cb_data(data);
}
static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_unlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
struct REMOVE3args args;
@ -2624,7 +2669,7 @@ static void nfs_mknod_cb(struct rpc_context *rpc, int status, void *command_data
free_nfs_cb_data(data);
}
static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_mknod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct mknod_cb_data *cb_data = data->continue_data;
char *str = cb_data->path;
@ -3046,7 +3091,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da
free_nfs_cb_data(data);
}
static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_opendir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
READDIRPLUS3args args;
@ -3267,7 +3312,7 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_
free_nfs_cb_data(data);
}
static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_statvfs_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
FSSTAT3args args;
@ -3329,7 +3374,7 @@ static void nfs_readlink_1_cb(struct rpc_context *rpc, int status, void *command
free_nfs_cb_data(data);
}
static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_readlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
READLINK3args args;
@ -3391,7 +3436,7 @@ static void nfs_chmod_cb(struct rpc_context *rpc, int status, void *command_data
free_nfs_cb_data(data);
}
static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_chmod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
@ -3446,7 +3491,7 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs
}
memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
if (nfs_chmod_continue_internal(nfs, data) != 0) {
if (nfs_chmod_continue_internal(nfs, NULL, data) != 0) {
return -1;
}
@ -3494,7 +3539,7 @@ struct nfs_chown_data {
gid_t gid;
};
static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_chown_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
struct nfs_chown_data *chown_data = data->continue_data;
@ -3580,7 +3625,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int
}
memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
if (nfs_chown_continue_internal(nfs, data) != 0) {
if (nfs_chown_continue_internal(nfs, NULL, data) != 0) {
return -1;
}
@ -3625,7 +3670,7 @@ static void nfs_utimes_cb(struct rpc_context *rpc, int status, void *command_dat
free_nfs_cb_data(data);
}
static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_utimes_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
struct timeval *utimes_data = data->continue_data;
@ -3763,7 +3808,7 @@ static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_dat
free_nfs_cb_data(data);
}
static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_access_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
int nfsmode = 0;
ACCESS3args args;
@ -3860,7 +3905,7 @@ static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_da
free_nfs_cb_data(data);
}
static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_symlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_symlink_data *symlink_data = data->continue_data;
SYMLINK3args args;
@ -3996,7 +4041,7 @@ static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_dat
free_nfs_cb_data(data);
}
static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_rename_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_rename_data *rename_data = data->continue_data;
RENAME3args args;
@ -4019,7 +4064,7 @@ static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb
}
static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_rename_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_rename_data *rename_data = data->continue_data;
char* newpath = strdup(rename_data->newpath);
@ -4166,7 +4211,7 @@ static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data,
free_nfs_cb_data(data);
}
static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_link_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_link_data *link_data = data->continue_data;
LINK3args args;
@ -4189,7 +4234,7 @@ static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_d
}
static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
static int nfs_link_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_link_data *link_data = data->continue_data;