
---

---


---


diff -puN fs/nfs/nfs4_fs.h~nfs-secinfo-exception fs/nfs/nfs4_fs.h
--- linux-2.6.18-rc5/fs/nfs/nfs4_fs.h~nfs-secinfo-exception	2006-10-17 16:18:09.000000000 -0400
+++ linux-2.6.18-rc5-andros/fs/nfs/nfs4_fs.h	2006-10-17 16:18:09.000000000 -0400
@@ -139,10 +139,16 @@ struct nfs4_state {
 	atomic_t count;
 };
 
+struct nfs4_wrongsec_info {
+	int op;
+	struct nfs_fh *fh;
+	struct qstr *name;
+};
 
 struct nfs4_exception {
 	long timeout;
 	int retry;
+	struct nfs4_wrongsec_info wrongsec;
 };
 
 struct nfs4_state_recovery_ops {
diff -puN fs/nfs/nfs4proc.c~nfs-secinfo-exception fs/nfs/nfs4proc.c
--- linux-2.6.18-rc5/fs/nfs/nfs4proc.c~nfs-secinfo-exception	2006-10-17 16:18:09.000000000 -0400
+++ linux-2.6.18-rc5-andros/fs/nfs/nfs4proc.c	2006-10-17 16:18:09.000000000 -0400
@@ -715,6 +715,12 @@ static const struct rpc_call_ops nfs4_op
 	.rpc_release = nfs4_open_release,
 };
 
+static void nfs4_set_wrongsec(struct nfs4_exception *exc, struct nfs_fh *fh, struct qstr *name)
+{
+	exc->wrongsec.fh = fh;
+	exc->wrongsec.name = name;
+}
+
 /*
  * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
  */
@@ -740,6 +746,10 @@ static int _nfs4_proc_open(struct nfs4_o
 	if (status != 0) {
 		data->cancelled = 1;
 		smp_wmb();
+		if (status == -NFS4ERR_WRONGSEC)
+			nfs4_set_wrongsec(o_res->exc,
+					(struct nfs_fh *)o_arg->fh,
+					(struct qstr *)o_arg->name);
 	} else
 		status = data->rpc_status;
 	rpc_release_task(task);
@@ -804,7 +814,7 @@ int nfs4_recover_expired_lease(struct nf
  * 	reclaim state on the server after a network partition.
  * 	Assumes caller holds the appropriate lock
  */
-static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry, struct nfs4_exception *exc)
 {
 	struct inode *inode = state->inode;
 	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
@@ -823,6 +833,7 @@ static int _nfs4_open_expired(struct nfs
 	opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
 	if (opendata == NULL)
 		return -ENOMEM;
+	opendata->o_res.exc = exc;
 	ret = nfs4_open_recover(opendata, state);
 	if (ret == -ESTALE) {
 		/* Invalidate the state owner so we don't ever use it again */
@@ -840,7 +851,7 @@ static inline int nfs4_do_open_expired(s
 	int err;
 
 	do {
-		err = _nfs4_open_expired(sp, state, dentry);
+		err = _nfs4_open_expired(sp, state, dentry, &exception);
 		if (err == -NFS4ERR_DELAY)
 			nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -948,7 +959,7 @@ static struct nfs4_state *nfs4_open_dele
 /*
  * Returns a referenced nfs4_state
  */
-static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res, struct nfs4_exception *exc)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
@@ -971,6 +982,7 @@ static int _nfs4_do_open(struct inode *d
 	opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
 	if (opendata == NULL)
 		goto err_put_state_owner;
+	opendata->o_res.exc = exc;
 
 	status = _nfs4_proc_open(opendata);
 	if (status != 0)
@@ -1006,7 +1018,8 @@ static struct nfs4_state *nfs4_do_open(s
 	int status;
 
 	do {
-		status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
+		status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res,
+				&exception);
 		if (status == 0)
 			break;
 		/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1534,7 +1547,7 @@ nfs4_proc_setattr(struct dentry *dentry,
 
 static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
 		struct qstr *name, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+		struct nfs_fattr *fattr, struct nfs4_exception *exc)
 {
 	int		       status;
 	struct nfs4_lookup_arg args = {
@@ -1546,6 +1559,7 @@ static int _nfs4_proc_lookupfh(struct nf
 		.server = server,
 		.fattr = fattr,
 		.fh = fhandle,
+		.exc = exc,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
@@ -1560,6 +1574,8 @@ static int _nfs4_proc_lookupfh(struct nf
 	dprintk("NFS reply lookupfh: %d\n", status);
 	if (status == -NFS4ERR_MOVED)
 		status = -EREMOTE;
+	if (status == -NFS4ERR_WRONGSEC)
+		nfs4_set_wrongsec(res.exc, dirfh, name);
 	return status;
 }
 
@@ -1572,14 +1588,15 @@ static int nfs4_proc_lookupfh(struct nfs
 	do {
 		err = nfs4_handle_exception(server,
 				_nfs4_proc_lookupfh(server, dirfh, name,
-						    fhandle, fattr),
+					fhandle, fattr, &exception),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
 static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+		struct nfs4_exception *exc)
 {
 	int		       status;
 	struct nfs_server *server = NFS_SERVER(dir);
@@ -1592,6 +1609,7 @@ static int _nfs4_proc_lookup(struct inod
 		.server = server,
 		.fattr = fattr,
 		.fh = fhandle,
+		.exc = exc,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
@@ -1605,6 +1623,8 @@ static int _nfs4_proc_lookup(struct inod
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (status == -NFS4ERR_MOVED)
 		status = nfs4_get_referral(dir, name, fattr, fhandle);
+	if (status == -NFS4ERR_WRONGSEC)
+		nfs4_set_wrongsec(res.exc, NFS_FH(dir), name);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
@@ -1615,7 +1635,8 @@ static int nfs4_proc_lookup(struct inode
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr,
+					&exception),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1988,7 +2009,8 @@ static int nfs4_proc_unlink_done(struct 
 }
 
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
-		struct inode *new_dir, struct qstr *new_name)
+		struct inode *new_dir, struct qstr *new_name,
+		struct nfs4_exception *exc)
 {
 	struct nfs_server *server = NFS_SERVER(old_dir);
 	struct nfs4_rename_arg arg = {
@@ -2003,6 +2025,7 @@ static int _nfs4_proc_rename(struct inod
 		.server = server,
 		.old_fattr = &old_fattr,
 		.new_fattr = &new_fattr,
+		.exc = exc,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
@@ -2020,6 +2043,8 @@ static int _nfs4_proc_rename(struct inod
 		nfs_post_op_update_inode(old_dir, res.old_fattr);
 		update_changeattr(new_dir, &res.new_cinfo);
 		nfs_post_op_update_inode(new_dir, res.new_fattr);
+		if (status == -NFS4ERR_WRONGSEC)
+			nfs4_set_wrongsec(res.exc, NFS_FH(old_dir), old_name);
 	}
 	return status;
 }
@@ -2032,13 +2057,13 @@ static int nfs4_proc_rename(struct inode
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(old_dir),
 				_nfs4_proc_rename(old_dir, old_name,
-					new_dir, new_name),
+					new_dir, new_name, &exception),
 				&exception);
 	} while (exception.retry);
 	return err;
 }
 
-static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name, struct nfs4_exception *exc)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_link_arg arg = {
@@ -2052,6 +2077,7 @@ static int _nfs4_proc_link(struct inode 
 		.server = server,
 		.fattr = &fattr,
 		.dir_attr = &dir_attr,
+		.exc = exc,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
@@ -2067,6 +2093,8 @@ static int _nfs4_proc_link(struct inode 
 		update_changeattr(dir, &res.cinfo);
 		nfs_post_op_update_inode(dir, res.dir_attr);
 		nfs_post_op_update_inode(inode, res.fattr);
+		if (status == -NFS4ERR_WRONGSEC)
+			nfs4_set_wrongsec(res.exc, NFS_FH(inode), name);
 	}
 
 	return status;
@@ -2078,7 +2106,7 @@ static int nfs4_proc_link(struct inode *
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(inode),
-				_nfs4_proc_link(inode, dir, name),
+				_nfs4_proc_link(inode, dir, name, &exception),
 				&exception);
 	} while (exception.retry);
 	return err;
diff -puN fs/nfs/nfs4xdr.c~nfs-secinfo-exception fs/nfs/nfs4xdr.c
--- linux-2.6.18-rc5/fs/nfs/nfs4xdr.c~nfs-secinfo-exception	2006-10-17 16:18:09.000000000 -0400
+++ linux-2.6.18-rc5-andros/fs/nfs/nfs4xdr.c	2006-10-17 16:18:09.000000000 -0400
@@ -2128,6 +2128,8 @@ out:
 	} \
 } while (0)
 
+#define SET_WRONGSEC_OP(op) (op) = ntohl(*(xdr.p-2))
+
 static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
 {
 	uint32_t *p;
@@ -3806,6 +3808,8 @@ static int nfs4_xdr_dec_lookup(struct rp
 		goto out;
 	status = decode_getfattr(&xdr, res->fattr, res->server);
 out:
+	if (status == -NFS4ERR_WRONGSEC)
+		SET_WRONGSEC_OP(res->exc->wrongsec.op);
 	return status;
 }
 
@@ -3877,6 +3881,8 @@ static int nfs4_xdr_dec_rename(struct rp
 		goto out;
 	decode_getfattr(&xdr, res->old_fattr, res->server);
 out:
+        if (status == -NFS4ERR_WRONGSEC)
+		SET_WRONGSEC_OP(res->exc->wrongsec.op);
 	return status;
 }
 
@@ -3910,6 +3916,8 @@ static int nfs4_xdr_dec_link(struct rpc_
 		goto out;
 	decode_getfattr(&xdr, res->fattr, res->server);
 out:
+        if (status == -NFS4ERR_WRONGSEC)
+		SET_WRONGSEC_OP(res->exc->wrongsec.op);
 	return status;
 }
 
@@ -4099,6 +4107,8 @@ static int nfs4_xdr_dec_open(struct rpc_
 		goto out;
 	decode_getfattr(&xdr, res->dir_attr, res->server);
 out:
+        if (status == -NFS4ERR_WRONGSEC)
+		SET_WRONGSEC_OP(res->exc->wrongsec.op);
         return status;
 }
 
diff -puN include/linux/nfs_xdr.h~nfs-secinfo-exception include/linux/nfs_xdr.h
--- linux-2.6.18-rc5/include/linux/nfs_xdr.h~nfs-secinfo-exception	2006-10-17 16:18:09.000000000 -0400
+++ linux-2.6.18-rc5-andros/include/linux/nfs_xdr.h	2006-10-17 16:18:09.000000000 -0400
@@ -144,6 +144,7 @@ struct nfs_openres {
 	nfs4_stateid		delegation;
 	__u32			do_recall;
 	__u64			maxsize;
+	struct nfs4_exception *	exc;
 };
 
 /*
@@ -595,6 +596,7 @@ struct nfs4_link_res {
 	struct nfs_fattr *		fattr;
 	struct nfs4_change_info		cinfo;
 	struct nfs_fattr *		dir_attr;
+	struct nfs4_exception *		exc;
 };
 
 
@@ -608,6 +610,7 @@ struct nfs4_lookup_res {
 	const struct nfs_server *	server;
 	struct nfs_fattr *		fattr;
 	struct nfs_fh *			fh;
+	struct nfs4_exception *		exc;
 };
 
 struct nfs4_lookup_root_arg {
@@ -667,6 +670,7 @@ struct nfs4_rename_res {
 	struct nfs_fattr *		old_fattr;
 	struct nfs4_change_info		new_cinfo;
 	struct nfs_fattr *		new_fattr;
+	struct nfs4_exception *		exc;
 };
 
 struct nfs4_setclientid {
_
