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