From: Neil Brown Well, firstly that patch is clearly wrong or at least incomplete. It makes sure that ATTR_MODE is not set, and then goes on to make sure ia_mode has an appropriate value which is no longer needed. Further, it allows ATTR_UID, ATTR_GID, ATTR_SIZE to still be set and potentially calls notify_change to change all these values, which certainly isn't appropriate. I think that "symlink" should be able to set the mode of the new symlinks. I have seen at least one version of Unix where the umask was used to modify the mode of a symlink at symlink creation. Many filesystems do store mode information, though it is generally ignored. NFS can communicate the mode information, and it would appear that VFS can to. So if a client sets a non-standard mode, and the filesystem is happy to record that it should be permitted. You didn't really say exactly what the bug was, but I'm guessing that symlink requests got EOPNOTSUPP (or some translation there-of) coming back from the NFS server. If that is the case, then I would suggest that a better fix would be the following (against 2-6-6-rc3-mm2 which already has the bad patch). unbreak nfsd_symlink breakage and don't worry about EOPNOTSUPP when chmod symlink --- 25-akpm/fs/nfsd/vfs.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) diff -puN fs/nfsd/vfs.c~invalid-notify_changesymlink-in-nfsd-fix fs/nfsd/vfs.c --- 25/fs/nfsd/vfs.c~invalid-notify_changesymlink-in-nfsd-fix Mon May 10 16:38:17 2004 +++ 25-akpm/fs/nfsd/vfs.c Mon May 10 16:38:17 2004 @@ -1212,15 +1212,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str if (EX_ISSYNC(fhp->fh_export)) nfsd_sync_dir(dentry); if (iap) { - iap->ia_valid &= ~ATTR_MODE; + iap->ia_valid &= ATTR_MODE /* ~(ATTR_SIZE|ATTR_UID|ATTR_GID)*/; if (iap->ia_valid) { iap->ia_valid |= ATTR_CTIME; iap->ia_mode = (iap->ia_mode&S_IALLUGO) | S_IFLNK; err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) + if (err) { + if (err == -EOPNOTSUPP) + err = nfs_ok; + else + err = nfserrno(err); + } else if (EX_ISSYNC(fhp->fh_export)) write_inode_now(dentry->d_inode, 1); } } _