
---


---

 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,
_
