mirror of https://github.com/torvalds/linux.git
NFSv4: Remove duplicate lookups, capability probes and fsinfo calls
When crossing into a new filesystem, the NFSv4 client will look up the new directory, and then call nfs4_server_capabilities() as well as nfs4_do_fsinfo() at least twice. This patch removes the duplicate calls, and reduces the initial lookup to retrieve just a minimal set of attributes. Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
b01f21cacd
commit
b9defd611a
|
|
@ -63,7 +63,7 @@ struct nfs4_minor_version_ops {
|
||||||
bool (*match_stateid)(const nfs4_stateid *,
|
bool (*match_stateid)(const nfs4_stateid *,
|
||||||
const nfs4_stateid *);
|
const nfs4_stateid *);
|
||||||
int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
|
int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
|
||||||
struct nfs_fsinfo *);
|
struct nfs_fattr *);
|
||||||
void (*free_lock_state)(struct nfs_server *,
|
void (*free_lock_state)(struct nfs_server *,
|
||||||
struct nfs4_lock_state *);
|
struct nfs4_lock_state *);
|
||||||
int (*test_and_free_expired)(struct nfs_server *,
|
int (*test_and_free_expired)(struct nfs_server *,
|
||||||
|
|
@ -296,7 +296,8 @@ extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *,
|
||||||
extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int);
|
extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int);
|
||||||
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, const struct cred *, struct nfs4_setclientid_res *);
|
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, const struct cred *, struct nfs4_setclientid_res *);
|
||||||
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, const struct cred *);
|
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, const struct cred *);
|
||||||
extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool);
|
extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *,
|
||||||
|
struct nfs_fattr *, bool);
|
||||||
extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, const struct cred *cred);
|
extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, const struct cred *cred);
|
||||||
extern int nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cred);
|
extern int nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cred);
|
||||||
extern int nfs4_destroy_clientid(struct nfs_client *clp);
|
extern int nfs4_destroy_clientid(struct nfs_client *clp);
|
||||||
|
|
|
||||||
|
|
@ -12,30 +12,28 @@
|
||||||
|
|
||||||
int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe)
|
int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe)
|
||||||
{
|
{
|
||||||
struct nfs_fsinfo fsinfo;
|
struct nfs_fattr *fattr = nfs_alloc_fattr();
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
fsinfo.fattr = nfs_alloc_fattr();
|
if (fattr == NULL)
|
||||||
if (fsinfo.fattr == NULL)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Start by getting the root filehandle from the server */
|
/* Start by getting the root filehandle from the server */
|
||||||
ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, auth_probe);
|
ret = nfs4_proc_get_rootfh(server, mntfh, fattr, auth_probe);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
|
dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
|
if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || !S_ISDIR(fattr->mode)) {
|
||||||
|| !S_ISDIR(fsinfo.fattr->mode)) {
|
|
||||||
printk(KERN_ERR "nfs4_get_rootfh:"
|
printk(KERN_ERR "nfs4_get_rootfh:"
|
||||||
" getroot encountered non-directory\n");
|
" getroot encountered non-directory\n");
|
||||||
ret = -ENOTDIR;
|
ret = -ENOTDIR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
|
memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
|
||||||
out:
|
out:
|
||||||
nfs_free_fattr(fsinfo.fattr);
|
nfs_free_fattr(fattr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4240,15 +4240,18 @@ static int nfs4_discover_trunking(struct nfs_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info)
|
struct nfs_fattr *fattr)
|
||||||
{
|
{
|
||||||
u32 bitmask[3];
|
u32 bitmask[3] = {
|
||||||
|
[0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE |
|
||||||
|
FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID,
|
||||||
|
};
|
||||||
struct nfs4_lookup_root_arg args = {
|
struct nfs4_lookup_root_arg args = {
|
||||||
.bitmask = bitmask,
|
.bitmask = bitmask,
|
||||||
};
|
};
|
||||||
struct nfs4_lookup_res res = {
|
struct nfs4_lookup_res res = {
|
||||||
.server = server,
|
.server = server,
|
||||||
.fattr = info->fattr,
|
.fattr = fattr,
|
||||||
.fh = fhandle,
|
.fh = fhandle,
|
||||||
};
|
};
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
|
|
@ -4257,27 +4260,20 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
.rpc_resp = &res,
|
.rpc_resp = &res,
|
||||||
};
|
};
|
||||||
|
|
||||||
bitmask[0] = nfs4_fattr_bitmap[0];
|
nfs_fattr_init(fattr);
|
||||||
bitmask[1] = nfs4_fattr_bitmap[1];
|
|
||||||
/*
|
|
||||||
* Process the label in the upcoming getfattr
|
|
||||||
*/
|
|
||||||
bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL;
|
|
||||||
|
|
||||||
nfs_fattr_init(info->fattr);
|
|
||||||
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
|
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info)
|
struct nfs_fattr *fattr)
|
||||||
{
|
{
|
||||||
struct nfs4_exception exception = {
|
struct nfs4_exception exception = {
|
||||||
.interruptible = true,
|
.interruptible = true,
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
do {
|
do {
|
||||||
err = _nfs4_lookup_root(server, fhandle, info);
|
err = _nfs4_lookup_root(server, fhandle, fattr);
|
||||||
trace_nfs4_lookup_root(server, fhandle, info->fattr, err);
|
trace_nfs4_lookup_root(server, fhandle, fattr, err);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 0:
|
case 0:
|
||||||
case -NFS4ERR_WRONGSEC:
|
case -NFS4ERR_WRONGSEC:
|
||||||
|
|
@ -4290,8 +4286,9 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
static int nfs4_lookup_root_sec(struct nfs_server *server,
|
||||||
struct nfs_fsinfo *info, rpc_authflavor_t flavor)
|
struct nfs_fh *fhandle, struct nfs_fattr *fattr,
|
||||||
|
rpc_authflavor_t flavor)
|
||||||
{
|
{
|
||||||
struct rpc_auth_create_args auth_args = {
|
struct rpc_auth_create_args auth_args = {
|
||||||
.pseudoflavor = flavor,
|
.pseudoflavor = flavor,
|
||||||
|
|
@ -4301,7 +4298,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
|
||||||
auth = rpcauth_create(&auth_args, server->client);
|
auth = rpcauth_create(&auth_args, server->client);
|
||||||
if (IS_ERR(auth))
|
if (IS_ERR(auth))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
return nfs4_lookup_root(server, fhandle, info);
|
return nfs4_lookup_root(server, fhandle, fattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -4314,7 +4311,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
|
||||||
* negative errno value.
|
* negative errno value.
|
||||||
*/
|
*/
|
||||||
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info)
|
struct nfs_fattr *fattr)
|
||||||
{
|
{
|
||||||
/* Per 3530bis 15.33.5 */
|
/* Per 3530bis 15.33.5 */
|
||||||
static const rpc_authflavor_t flav_array[] = {
|
static const rpc_authflavor_t flav_array[] = {
|
||||||
|
|
@ -4330,7 +4327,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
if (server->auth_info.flavor_len > 0) {
|
if (server->auth_info.flavor_len > 0) {
|
||||||
/* try each flavor specified by user */
|
/* try each flavor specified by user */
|
||||||
for (i = 0; i < server->auth_info.flavor_len; i++) {
|
for (i = 0; i < server->auth_info.flavor_len; i++) {
|
||||||
status = nfs4_lookup_root_sec(server, fhandle, info,
|
status = nfs4_lookup_root_sec(
|
||||||
|
server, fhandle, fattr,
|
||||||
server->auth_info.flavors[i]);
|
server->auth_info.flavors[i]);
|
||||||
if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
|
if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -4339,7 +4337,7 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
} else {
|
} else {
|
||||||
/* no flavors specified by user, try default list */
|
/* no flavors specified by user, try default list */
|
||||||
for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
|
for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
|
||||||
status = nfs4_lookup_root_sec(server, fhandle, info,
|
status = nfs4_lookup_root_sec(server, fhandle, fattr,
|
||||||
flav_array[i]);
|
flav_array[i]);
|
||||||
if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
|
if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -4363,28 +4361,22 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
* nfs4_proc_get_rootfh - get file handle for server's pseudoroot
|
* nfs4_proc_get_rootfh - get file handle for server's pseudoroot
|
||||||
* @server: initialized nfs_server handle
|
* @server: initialized nfs_server handle
|
||||||
* @fhandle: we fill in the pseudo-fs root file handle
|
* @fhandle: we fill in the pseudo-fs root file handle
|
||||||
* @info: we fill in an FSINFO struct
|
* @fattr: we fill in a bare bones struct fattr
|
||||||
* @auth_probe: probe the auth flavours
|
* @auth_probe: probe the auth flavours
|
||||||
*
|
*
|
||||||
* Returns zero on success, or a negative errno.
|
* Returns zero on success, or a negative errno.
|
||||||
*/
|
*/
|
||||||
int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
|
int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info,
|
struct nfs_fattr *fattr, bool auth_probe)
|
||||||
bool auth_probe)
|
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (!auth_probe)
|
if (!auth_probe)
|
||||||
status = nfs4_lookup_root(server, fhandle, info);
|
status = nfs4_lookup_root(server, fhandle, fattr);
|
||||||
|
|
||||||
if (auth_probe || status == NFS4ERR_WRONGSEC)
|
if (auth_probe || status == NFS4ERR_WRONGSEC)
|
||||||
status = server->nfs_client->cl_mvops->find_root_sec(server,
|
status = server->nfs_client->cl_mvops->find_root_sec(
|
||||||
fhandle, info);
|
server, fhandle, fattr);
|
||||||
|
|
||||||
if (status == 0)
|
|
||||||
status = nfs4_server_capabilities(server, fhandle);
|
|
||||||
if (status == 0)
|
|
||||||
status = nfs4_do_fsinfo(server, fhandle, info);
|
|
||||||
|
|
||||||
return nfs4_map_errors(status);
|
return nfs4_map_errors(status);
|
||||||
}
|
}
|
||||||
|
|
@ -10351,10 +10343,10 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
|
||||||
* Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
|
* Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
|
||||||
* possible) as per RFC3530bis and RFC5661 Security Considerations sections
|
* possible) as per RFC3530bis and RFC5661 Security Considerations sections
|
||||||
*/
|
*/
|
||||||
static int
|
static int _nfs41_proc_secinfo_no_name(struct nfs_server *server,
|
||||||
_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info,
|
struct nfs4_secinfo_flavors *flavors,
|
||||||
struct nfs4_secinfo_flavors *flavors, bool use_integrity)
|
bool use_integrity)
|
||||||
{
|
{
|
||||||
struct nfs41_secinfo_no_name_args args = {
|
struct nfs41_secinfo_no_name_args args = {
|
||||||
.style = SECINFO_STYLE_CURRENT_FH,
|
.style = SECINFO_STYLE_CURRENT_FH,
|
||||||
|
|
@ -10398,9 +10390,9 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int nfs41_proc_secinfo_no_name(struct nfs_server *server,
|
||||||
nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
struct nfs_fh *fhandle,
|
||||||
struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
|
struct nfs4_secinfo_flavors *flavors)
|
||||||
{
|
{
|
||||||
struct nfs4_exception exception = {
|
struct nfs4_exception exception = {
|
||||||
.interruptible = true,
|
.interruptible = true,
|
||||||
|
|
@ -10412,7 +10404,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
|
|
||||||
/* try to use integrity protection with machine cred */
|
/* try to use integrity protection with machine cred */
|
||||||
if (_nfs4_is_integrity_protected(server->nfs_client))
|
if (_nfs4_is_integrity_protected(server->nfs_client))
|
||||||
err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
|
err = _nfs41_proc_secinfo_no_name(server, fhandle,
|
||||||
flavors, true);
|
flavors, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -10422,7 +10414,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
* the current filesystem's rpc_client and the user cred.
|
* the current filesystem's rpc_client and the user cred.
|
||||||
*/
|
*/
|
||||||
if (err == -NFS4ERR_WRONGSEC)
|
if (err == -NFS4ERR_WRONGSEC)
|
||||||
err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
|
err = _nfs41_proc_secinfo_no_name(server, fhandle,
|
||||||
flavors, false);
|
flavors, false);
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
@ -10438,9 +10430,8 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int nfs41_find_root_sec(struct nfs_server *server,
|
||||||
nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
|
||||||
struct nfs_fsinfo *info)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
@ -10456,14 +10447,14 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
flavors = page_address(page);
|
flavors = page_address(page);
|
||||||
err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
|
err = nfs41_proc_secinfo_no_name(server, fhandle, flavors);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fall back on "guess and check" method if
|
* Fall back on "guess and check" method if
|
||||||
* the server doesn't support SECINFO_NO_NAME
|
* the server doesn't support SECINFO_NO_NAME
|
||||||
*/
|
*/
|
||||||
if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
|
if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
|
||||||
err = nfs4_find_root_sec(server, fhandle, info);
|
err = nfs4_find_root_sec(server, fhandle, fattr);
|
||||||
goto out_freepage;
|
goto out_freepage;
|
||||||
}
|
}
|
||||||
if (err)
|
if (err)
|
||||||
|
|
@ -10488,8 +10479,8 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||||
flavor = RPC_AUTH_MAXFLAVOR;
|
flavor = RPC_AUTH_MAXFLAVOR;
|
||||||
|
|
||||||
if (flavor != RPC_AUTH_MAXFLAVOR) {
|
if (flavor != RPC_AUTH_MAXFLAVOR) {
|
||||||
err = nfs4_lookup_root_sec(server, fhandle,
|
err = nfs4_lookup_root_sec(server, fhandle, fattr,
|
||||||
info, flavor);
|
flavor);
|
||||||
if (!err)
|
if (!err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue