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 *); _