From: viro@www.linux.org.uk

* hpfs_unlink() should not try to truncate the victim unless it's a
  regular file; truncate will not help for anything else and it will screw
  the page cache if victim happens to be a block device.

* network filesystems should *not* invalidate page cache of block device
  node when inode gets invalidated; fixed, added a new helper -
  invalidate_remote_inode().

* nfs setattr syncs the file before sending SETATTR to server; that makes
  a lot of sense for regular files, but not for anything else.  Fixed.



 fs/afs/callback.c  |    2 +-
 fs/afs/dir.c       |    2 +-
 fs/cifs/cifsfs.c   |   10 ++++++----
 fs/hpfs/namei.c    |    1 +
 fs/nfs/inode.c     |   19 ++++++++++---------
 fs/smbfs/inode.c   |    4 ++--
 include/linux/fs.h |    6 ++++++
 7 files changed, 27 insertions(+), 17 deletions(-)

diff -puN fs/afs/callback.c~large-dev_t-06 fs/afs/callback.c
--- 25/fs/afs/callback.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/afs/callback.c	2003-08-26 18:28:52.000000000 -0700
@@ -146,7 +146,7 @@ int SRXAFSCM_CallBack(afs_server_t *serv
 			spin_unlock(&vnode->lock);
 
 			if (valid) {
-				invalidate_inode_pages(inode->i_mapping);
+				invalidate_remote_inode(inode);
 				afs_put_server(server);
 			}
 			iput(inode);
diff -puN fs/afs/dir.c~large-dev_t-06 fs/afs/dir.c
--- 25/fs/afs/dir.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/afs/dir.c	2003-08-26 18:28:52.000000000 -0700
@@ -569,7 +569,7 @@ static int afs_d_revalidate(struct dentr
 			spin_lock(&AFS_FS_I(inode)->lock);
 			AFS_FS_I(inode)->flags |= AFS_VNODE_DELETED;
 			spin_unlock(&AFS_FS_I(inode)->lock);
-			invalidate_inode_pages(inode->i_mapping);
+			invalidate_remote_inode(inode);
 			goto out_bad;
 		}
 
diff -puN fs/cifs/cifsfs.c~large-dev_t-06 fs/cifs/cifsfs.c
--- 25/fs/cifs/cifsfs.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/cifs/cifsfs.c	2003-08-26 18:28:52.000000000 -0700
@@ -598,10 +598,12 @@ static int cifs_oplock_thread(void * dum
 				netfid = oplock_item->netfid;
 				DeleteOplockQEntry(oplock_item);
 				write_unlock(&GlobalMid_Lock);
-				rc = filemap_fdatawrite(inode->i_mapping);
-				if(rc)
-					CIFS_I(inode)->write_behind_rc 
-						= rc;
+				if (S_ISREG(inode->i_mode))
+					rc = filemap_fdatawrite(inode->i_mapping);
+				else
+					rc = 0;
+				if (rc)
+					CIFS_I(inode)->write_behind_rc = rc;
 				cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
 				rc = CIFSSMBLock(0, pTcon, netfid,
 					0 /* len */ , 0 /* offset */, 0, 
diff -puN fs/hpfs/namei.c~large-dev_t-06 fs/hpfs/namei.c
--- 25/fs/hpfs/namei.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/hpfs/namei.c	2003-08-26 18:28:52.000000000 -0700
@@ -375,6 +375,7 @@ again:
 		spin_lock(&dentry->d_lock);
 		if (atomic_read(&dentry->d_count) > 1 ||
 		    permission(inode, MAY_WRITE, NULL) ||
+		    !S_ISREG(inode->i_mode) ||
 		    get_write_access(inode)) {
 			spin_unlock(&dentry->d_lock);
 			d_rehash(dentry);
diff -puN fs/nfs/inode.c~large-dev_t-06 fs/nfs/inode.c
--- 25/fs/nfs/inode.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/nfs/inode.c	2003-08-26 18:28:52.000000000 -0700
@@ -620,7 +620,7 @@ nfs_zap_caches(struct inode *inode)
 	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
 	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 
-	invalidate_inode_pages(inode->i_mapping);
+	invalidate_remote_inode(inode);
 
 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
 	NFS_CACHEINV(inode);
@@ -823,14 +823,15 @@ printk("nfs_setattr: revalidate failed, 
 		goto out;
 	}
 
-	if (!S_ISREG(inode->i_mode))
+	if (!S_ISREG(inode->i_mode)) {
 		attr->ia_valid &= ~ATTR_SIZE;
-
-	filemap_fdatawrite(inode->i_mapping);
-	error = nfs_wb_all(inode);
-	filemap_fdatawait(inode->i_mapping);
-	if (error)
-		goto out;
+	} else {
+		filemap_fdatawrite(inode->i_mapping);
+		error = nfs_wb_all(inode);
+		filemap_fdatawait(inode->i_mapping);
+		if (error)
+			goto out;
+	}
 
 	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
 	if (error)
@@ -1205,7 +1206,7 @@ __nfs_refresh_inode(struct inode *inode,
 	if (invalid) {
 		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
 		nfsi->attrtimeo_timestamp = jiffies;
-		invalidate_inode_pages(inode->i_mapping);
+		invalidate_remote_inode(inode);
 		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
 	} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
 		if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
diff -puN fs/smbfs/inode.c~large-dev_t-06 fs/smbfs/inode.c
--- 25/fs/smbfs/inode.c~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/fs/smbfs/inode.c	2003-08-26 18:28:52.000000000 -0700
@@ -212,7 +212,7 @@ smb_set_inode_attr(struct inode *inode, 
 			(long) last_sz, (long) inode->i_size);
 
 		if (!S_ISDIR(inode->i_mode))
-			invalidate_inode_pages(inode->i_mapping);
+			invalidate_remote_inode(inode);
 	}
 }
 
@@ -276,7 +276,7 @@ smb_refresh_inode(struct dentry *dentry)
 			 * But we do want to invalidate the caches ...
 			 */
 			if (!S_ISDIR(inode->i_mode))
-				invalidate_inode_pages(inode->i_mapping);
+				invalidate_remote_inode(inode);
 			else
 				smb_invalid_dir_cache(inode);
 			error = -EIO;
diff -puN include/linux/fs.h~large-dev_t-06 include/linux/fs.h
--- 25/include/linux/fs.h~large-dev_t-06	2003-08-26 18:28:52.000000000 -0700
+++ 25-akpm/include/linux/fs.h	2003-08-26 18:28:52.000000000 -0700
@@ -1176,6 +1176,12 @@ extern int invalidate_partition(struct g
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
 unsigned long invalidate_inode_pages(struct address_space *mapping);
+static inline void invalidate_remote_inode(struct inode *inode)
+{
+	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+	    S_ISLNK(inode->i_mode))
+		invalidate_inode_pages(inode->i_mapping);
+}
 extern void invalidate_inode_pages2(struct address_space *mapping);
 extern void write_inode_now(struct inode *, int);
 extern int filemap_fdatawrite(struct address_space *);

_