--- --- linux-2.6.18-rc5-andros/fs/nfs/nfs4proc.c | 128 ++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 34 deletions(-) diff -puN fs/nfs/nfs4proc.c~nfs-secinfo-do-exception fs/nfs/nfs4proc.c --- linux-2.6.18-rc5/fs/nfs/nfs4proc.c~nfs-secinfo-do-exception 2006-10-11 17:37:01.000000000 -0400 +++ linux-2.6.18-rc5-andros/fs/nfs/nfs4proc.c 2006-10-11 17:37:01.000000000 -0400 @@ -51,6 +51,7 @@ #include "nfs4_fs.h" #include "delegation.h" +#include "internal.h" #include "iostat.h" #define NFSDBG_FACILITY NFSDBG_PROC @@ -2815,6 +2816,92 @@ static int nfs4_proc_set_acl(struct inod } static int +_nfs4_proc_secinfo(struct nfs_server *server, struct nfs_fh *dir_fh, struct qstr *name, struct nfs4_secinfo_res *res) +{ + int status; + struct nfs4_secinfo_arg args = { + .dir_fh = dir_fh, + .name = name, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO], + .rpc_argp = &args, + .rpc_resp = res, + }; + + dprintk("NFS call secinfo %s\n", name->name); + status = rpc_call_sync(server->client, &msg, 0); + dprintk("NFS reply secinfo: %d\n", status); + return status; +} + +static int +nfs4_proc_secinfo(struct nfs_server *server, struct nfs_fh *dir_fh, struct qstr *name, struct nfs4_secinfo_res *res) +{ + struct nfs4_exception exception = { }; + int err; + + do { + err = nfs4_handle_exception(server, + _nfs4_proc_secinfo(server, dir_fh, name, res), + &exception); + } while (exception.retry); + return err; +} + +static int nfs4_do_secinfo(struct nfs4_wrongsec_info *info, struct nfs_server *server) +{ + struct nfs_client *clp = server->nfs_client; + struct rpc_cred *cred; + int i, ret = -EPERM; + struct nfs4_secinfo_res res = { + .nflavors = 0, + }; + + dprintk("%s: op=%d server=0x%p fh=%p name=%p %s\n", __FUNCTION__, + info->op, server, info->fh, info->name, + (info->name ? info->name->name : NULL)); + + cred = rpcauth_lookupcred(server->client->cl_auth, 0); + if (IS_ERR(cred)) + return PTR_ERR(cred); + + switch (info->op) { + case OP_LOOKUP: + case OP_OPEN: + case OP_LINK: + case OP_RENAME: + ret = nfs4_proc_secinfo(server, info->fh, info->name, &res); + if (ret) + break; + ret = -EPERM; + for (i = 0; i < res.nflavors; i++) { + ret = nfs4_clnt_switch_flavor(server->client, + res.flavors[i], &cred); + break; + } + break; + case OP_PUTROOTFH: + ret = nfs4_clnt_try_each_flavor(clp->cl_rpcclient, + &res, &cred); + break; + case OP_PUTFH: + // FIXME + case OP_RESTOREFH: + case OP_PUTPUBFH: + // not yet implemented + case OP_READDIR: + // ignored in nfs4xdr.c:nfs4_decode_dirent() + default: + dprintk("ERROR: %s() don't know what to do for op=%d\n", + __FUNCTION__, info->op); + } + + dprintk("%s: ret=%d\n", __FUNCTION__, ret); + return ret; +} + +static int nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; @@ -2892,6 +2979,7 @@ static int nfs4_delay(struct rpc_clnt *c return res; } + /* This is the error handling routine for processes that are allowed * to sleep. */ @@ -2919,6 +3007,12 @@ int nfs4_handle_exception(const struct n break; case -NFS4ERR_OLD_STATEID: exception->retry = 1; + break; + case -NFS4ERR_WRONGSEC: + ret = nfs4_do_secinfo(&exception->wrongsec, + (struct nfs_server *)server); + if (ret == 0) + exception->retry = 1; } /* We failed to handle the error */ return nfs4_map_errors(ret); @@ -3722,40 +3816,6 @@ int nfs4_proc_fs_locations(struct inode return status; } -static int -_nfs4_proc_secinfo(struct nfs_server *server, struct nfs_fh *dir_fh, struct qstr *name, struct nfs4_secinfo_res *res) -{ - int status; - struct nfs4_secinfo_arg args = { - .dir_fh = dir_fh, - .name = name, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO], - .rpc_argp = &args, - .rpc_resp = res, - }; - - dprintk("NFS call secinfo %s\n", name->name); - status = rpc_call_sync(server->client, &msg, 0); - dprintk("NFS reply secinfo: %d\n", status); - return status; -} - -static int -nfs4_proc_secinfo(struct nfs_server *server, struct nfs_fh *dir_fh, struct qstr *name, struct nfs4_secinfo_res *res) -{ - struct nfs4_exception exception = { }; - int err; - - do { - err = nfs4_handle_exception(server, - _nfs4_proc_secinfo(server, dir_fh, name, res), - &exception); - } while (exception.retry); - return err; -} - struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim, _