From: Andreas Gruenbacher <agruen@suse.de>

notify_change() gets called with at most the ATTR_MODE flag set for symlinks,
but it should be called with the ATTR_MODE flag cleared.  This triggers a bug
in fs/reiserfs/xattr_acl.c (reiserfs plus acl patches), and perhaps on other
file systems, too.  (On ext2/ext3 symlinks have no ->setattr, there the bug
does not trigger.)

	int
	reiserfs_acl_chmod (struct inode *inode)
	{
        	struct posix_acl *acl, *clone;
	        int error;

==>	        if (S_ISLNK(inode->i_mode))
==>	                return -EOPNOTSUPP;

This is the fix.
DESC
Fix "Invalid notify_change(symlink, [ATTR_MODE]) in nfsd"
EDESC
From: Neil Brown <neilb@cse.unsw.edu.au>

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 fs/nfsd/vfs.c
--- 25/fs/nfsd/vfs.c~invalid-notify_changesymlink-in-nfsd	Fri May 14 17:30:58 2004
+++ 25-akpm/fs/nfsd/vfs.c	Fri May 14 17:31:02 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 /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
+			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);
 		       }
 		}

_