static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static void nfs_zap_acl_cache(struct inode *);
 
 static struct rpc_program      nfs_program;
 
 
        nfs_wb_all(inode);
        BUG_ON (!list_empty(&nfsi->open_files));
+       nfs_zap_acl_cache(inode);
        cred = nfsi->cache_access.cred;
        if (cred)
                put_rpccred(cred);
 
        memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        else
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+}
+
+static void nfs_zap_acl_cache(struct inode *inode)
+{
+       void (*clear_acl_cache)(struct inode *);
+
+       clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+       if (clear_acl_cache != NULL)
+               clear_acl_cache(inode);
+       NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
 }
 
 /*
                }
        }
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-               NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+               NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        nfs_end_data_update(inode);
        unlock_kernel();
        return error;
                /* This ensures we revalidate dentries */
                nfsi->cache_change_attribute++;
        }
+       if (flags & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
                inode->i_sb->s_id,
                (long long)NFS_FILEID(inode));
        if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
                        || inode->i_uid != fattr->uid
                        || inode->i_gid != fattr->gid)
-               nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
 
        /* Has the link count changed? */
        if (inode->i_nlink != fattr->nlink)
 #endif
                nfsi->change_attr = fattr->change_attr;
                if (!data_unstable)
-                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        }
 
-       memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+       /* If ctime has changed we should definitely clear access+acl caches */
+       if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
+               if (!data_unstable)
+                       invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+               memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+       }
        memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 
        if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
            inode->i_uid != fattr->uid ||
            inode->i_gid != fattr->gid)
-               invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+               invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 
        inode->i_mode = fattr->mode;
        inode->i_nlink = fattr->nlink;