From: NeilBrown unlike v2/v3, nfsv4 returns nfserr_inval when attempting to read, write, commit or test lock a symlink. nfsv4 does return nfserr_symlink on lookup and open, so a simple fix in fh_verify() will not work. --- fs/nfsd/nfs4proc.c | 14 +++++++++++--- fs/nfsd/nfs4state.c | 2 ++ fs/nfsd/nfs4xdr.c | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) diff -puN fs/nfsd/nfs4proc.c~knfsd-symlink-fixes fs/nfsd/nfs4proc.c --- 25/fs/nfsd/nfs4proc.c~knfsd-symlink-fixes 2004-02-25 02:32:15.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4proc.c 2004-02-25 02:32:15.000000000 -0800 @@ -224,11 +224,16 @@ nfsd4_access(struct svc_rqst *rqstp, str static inline int nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) { + int status; + u32 *p = (u32 *)commit->co_verf.data; *p++ = nfssvc_boot.tv_sec; *p++ = nfssvc_boot.tv_usec; - return nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count); + status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count); + if (status == nfserr_symlink) + status = nfserr_inval; + return status; } static inline int @@ -558,9 +563,12 @@ zero_stateid: *p++ = nfssvc_boot.tv_sec; *p++ = nfssvc_boot.tv_usec; - return (nfsd_write(rqstp, current_fh, write->wr_offset, + status = nfsd_write(rqstp, current_fh, write->wr_offset, write->wr_vec, write->wr_vlen, write->wr_buflen, - &write->wr_how_written)); + &write->wr_how_written); + if (status == nfserr_symlink) + status = nfserr_inval; + return status; out: nfs4_unlock_state(); return status; diff -puN fs/nfsd/nfs4state.c~knfsd-symlink-fixes fs/nfsd/nfs4state.c --- 25/fs/nfsd/nfs4state.c~knfsd-symlink-fixes 2004-02-25 02:32:15.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4state.c 2004-02-25 02:32:15.000000000 -0800 @@ -1974,6 +1974,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) { printk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); + if (status == nfserr_symlink) + status = nfserr_inval; goto out; } diff -puN fs/nfsd/nfs4xdr.c~knfsd-symlink-fixes fs/nfsd/nfs4xdr.c --- 25/fs/nfsd/nfs4xdr.c~knfsd-symlink-fixes 2004-02-25 02:32:15.000000000 -0800 +++ 25-akpm/fs/nfsd/nfs4xdr.c 2004-02-25 02:32:15.000000000 -0800 @@ -2005,6 +2005,8 @@ nfsd4_encode_read(struct nfsd4_compoundr read->rd_offset, read->rd_iov, read->rd_vlen, &maxcount); + if (nfserr == nfserr_symlink) + nfserr = nfserr_inval; if (nfserr) return nfserr; eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); _