while (!RB_EMPTY_ROOT(&server->cb_promises)) {
                vnode = rb_entry(server->cb_promises.rb_node,
                                 struct afs_vnode, cb_promise);
-               _debug("UNPROMISE { vid=%x vn=%u uq=%u}",
+               _debug("UNPROMISE { vid=%x:%u uq=%u}",
                       vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
                rb_erase(&vnode->cb_promise, &server->cb_promises);
                vnode->cb_promised = false;
 
                /* if the vnode's data version number changed then its contents
                 * are different */
-               if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
-                       _debug("zap data {%x:%u}",
-                              vnode->fid.vid, vnode->fid.vnode);
-                       invalidate_remote_inode(&vnode->vfs_inode);
-               }
+               if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
+                       afs_zap_data(vnode);
        }
 
 out:
 
        .rmdir          = afs_rmdir,
        .rename         = afs_rename,
        .permission     = afs_permission,
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
 };
 
 static struct dentry_operations afs_fs_dentry_operations = {
 
        vnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},%p{%s},",
+       _enter("{%x:%u},%p{%s},",
               vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);
 
        ASSERTCMP(dentry->d_inode, ==, NULL);
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%o",
+       _enter("{%x:%u},{%s},%o",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
        ret = -ENAMETOOLONG;
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s}",
+       _enter("{%x:%u},{%s}",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
        ret = -ENAMETOOLONG;
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s}",
+       _enter("{%x:%u},{%s}",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
        ret = -ENAMETOOLONG;
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%o,",
+       _enter("{%x:%u},{%s},%o,",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
        ret = -ENAMETOOLONG;
        vnode = AFS_FS_I(from->d_inode);
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%x:%d},{%s}",
+       _enter("{%x:%u},{%x:%u},{%s}",
               vnode->fid.vid, vnode->fid.vnode,
               dvnode->fid.vid, dvnode->fid.vnode,
               dentry->d_name.name);
 
        dvnode = AFS_FS_I(dir);
 
-       _enter("{%x:%d},{%s},%s",
+       _enter("{%x:%u},{%s},%s",
               dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
               content);
 
        orig_dvnode = AFS_FS_I(old_dir);
        new_dvnode = AFS_FS_I(new_dir);
 
-       _enter("{%x:%d},{%x:%d},{%x:%d},{%s}",
+       _enter("{%x:%u},{%x:%u},{%x:%u},{%s}",
               orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
               vnode->fid.vid, vnode->fid.vnode,
               new_dvnode->fid.vid, new_dvnode->fid.vnode,
 
 #include <linux/pagemap.h>
 #include "internal.h"
 
-static int afs_file_readpage(struct file *file, struct page *page);
-static void afs_file_invalidatepage(struct page *page, unsigned long offset);
-static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
+static int afs_readpage(struct file *file, struct page *page);
+static void afs_invalidatepage(struct page *page, unsigned long offset);
+static int afs_releasepage(struct page *page, gfp_t gfp_flags);
 
 const struct file_operations afs_file_operations = {
        .open           = afs_open,
 };
 
 const struct inode_operations afs_file_inode_operations = {
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
        .permission     = afs_permission,
 };
 
 const struct address_space_operations afs_fs_aops = {
-       .readpage       = afs_file_readpage,
+       .readpage       = afs_readpage,
        .set_page_dirty = __set_page_dirty_nobuffers,
-       .releasepage    = afs_file_releasepage,
-       .invalidatepage = afs_file_invalidatepage,
+       .releasepage    = afs_releasepage,
+       .invalidatepage = afs_invalidatepage,
 };
 
 /*
        struct key *key;
        int ret;
 
-       _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
+       _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
 
        key = afs_request_key(vnode->volume->cell);
        if (IS_ERR(key)) {
 {
        struct afs_vnode *vnode = AFS_FS_I(inode);
 
-       _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
+       _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
 
        key_put(file->private_data);
        _leave(" = 0");
  * deal with notification that a page was read from the cache
  */
 #ifdef AFS_CACHING_SUPPORT
-static void afs_file_readpage_read_complete(void *cookie_data,
-                                           struct page *page,
-                                           void *data,
-                                           int error)
+static void afs_readpage_read_complete(void *cookie_data,
+                                      struct page *page,
+                                      void *data,
+                                      int error)
 {
        _enter("%p,%p,%p,%d", cookie_data, page, data, error);
 
  * deal with notification that a page was written to the cache
  */
 #ifdef AFS_CACHING_SUPPORT
-static void afs_file_readpage_write_complete(void *cookie_data,
-                                            struct page *page,
-                                            void *data,
-                                            int error)
+static void afs_readpage_write_complete(void *cookie_data,
+                                       struct page *page,
+                                       void *data,
+                                       int error)
 {
        _enter("%p,%p,%p,%d", cookie_data, page, data, error);
 
 #endif
 
 /*
- * AFS read page from file (or symlink)
+ * AFS read page from file, directory or symlink
  */
-static int afs_file_readpage(struct file *file, struct page *page)
+static int afs_readpage(struct file *file, struct page *page)
 {
        struct afs_vnode *vnode;
        struct inode *inode;
        return ret;
 }
 
-/*
- * get a page cookie for the specified page
- */
-#ifdef AFS_CACHING_SUPPORT
-int afs_cache_get_page_cookie(struct page *page,
-                             struct cachefs_page **_page_cookie)
-{
-       int ret;
-
-       _enter("");
-       ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);
-
-       _leave(" = %d", ret);
-       return ret;
-}
-#endif
-
 /*
  * invalidate part or all of a page
  */
-static void afs_file_invalidatepage(struct page *page, unsigned long offset)
+static void afs_invalidatepage(struct page *page, unsigned long offset)
 {
        int ret = 1;
 
-       _enter("{%lu},%lu", page->index, offset);
+       kenter("{%lu},%lu", page->index, offset);
 
        BUG_ON(!PageLocked(page));
 
 /*
  * release a page and cleanup its private data
  */
-static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
+static int afs_releasepage(struct page *page, gfp_t gfp_flags)
 {
-       struct cachefs_page *pageio;
+       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
 
-       _enter("{%lu},%x", page->index, gfp_flags);
+       _enter("{{%x:%u}[%lu],%lx},%x",
+              vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
+              gfp_flags);
 
        if (PagePrivate(page)) {
-#ifdef AFS_CACHING_SUPPORT
-               struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-               cachefs_uncache_page(vnode->cache, page);
-#endif
-
-               pageio = (struct cachefs_page *) page_private(page);
                set_page_private(page, 0);
                ClearPagePrivate(page);
-
-               kfree(pageio);
        }
 
        _leave(" = 0");
 
        struct afs_call *call;
        __be32 *bp;
 
-       _enter(",%x,{%x:%d},,",
+       _enter(",%x,{%x:%u},,",
               key_serial(key), vnode->fid.vid, vnode->fid.vnode);
 
        call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
                call->offset = 0;
                call->unmarshall++;
 
-               if (call->count < PAGE_SIZE) {
-                       page = call->reply3;
-                       buffer = kmap_atomic(page, KM_USER0);
-                       memset(buffer + PAGE_SIZE - call->count, 0,
-                              call->count);
-                       kunmap_atomic(buffer, KM_USER0);
-               }
-
                /* extract the returned data */
        case 2:
                _debug("extract data");
-               page = call->reply3;
-               buffer = kmap_atomic(page, KM_USER0);
-               ret = afs_extract_data(call, skb, last, buffer, call->count);
-               kunmap_atomic(buffer, KM_USER0);
-               switch (ret) {
-               case 0:         break;
-               case -EAGAIN:   return 0;
-               default:        return ret;
+               if (call->count > 0) {
+                       page = call->reply3;
+                       buffer = kmap_atomic(page, KM_USER0);
+                       ret = afs_extract_data(call, skb, last, buffer,
+                                              call->count);
+                       kunmap_atomic(buffer, KM_USER0);
+                       switch (ret) {
+                       case 0:         break;
+                       case -EAGAIN:   return 0;
+                       default:        return ret;
+                       }
                }
 
                call->offset = 0;
        if (!last)
                return 0;
 
+       if (call->count < PAGE_SIZE) {
+               _debug("clear");
+               page = call->reply3;
+               buffer = kmap_atomic(page, KM_USER0);
+               memset(buffer + call->count, 0, PAGE_SIZE - call->count);
+               kunmap_atomic(buffer, KM_USER0);
+       }
+
        _leave(" = 0 [done]");
        return 0;
 }
 
        struct inode *inode;
        int ret;
 
-       _enter(",{%u,%u,%u},,", fid->vid, fid->vnode, fid->unique);
+       _enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);
 
        as = sb->s_fs_info;
        data.volume = as->volume;
        return ERR_PTR(ret);
 }
 
+/*
+ * mark the data attached to an inode as obsolete due to a write on the server
+ * - might also want to ditch all the outstanding writes and dirty pages
+ */
+void afs_zap_data(struct afs_vnode *vnode)
+{
+       kenter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+
+       /* nuke all the non-dirty pages that aren't locked, mapped or being
+        * written back */
+       invalidate_remote_inode(&vnode->vfs_inode);
+}
+
 /*
  * validate a vnode/inode
  * - there are several things we need to check
 
        /* if the vnode's data version number changed then its contents are
         * different */
-       if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
-               _debug("zap data {%x:%d}", vnode->fid.vid, vnode->fid.vnode);
-               invalidate_remote_inode(&vnode->vfs_inode);
-       }
+       if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
+               afs_zap_data(vnode);
 
        clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
        mutex_unlock(&vnode->validate_lock);
 /*
  * read the attributes of an inode
  */
-int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
+int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
                      struct kstat *stat)
 {
        struct inode *inode;
 
        vnode = AFS_FS_I(inode);
 
-       _enter("{%x:%d.%d} v=%u x=%u t=%u }",
+       _enter("{%x:%u.%d} v=%u x=%u t=%u }",
               vnode->fid.vid,
               vnode->fid.vnode,
               vnode->fid.unique,
 
 extern int afs_open(struct inode *, struct file *);
 extern int afs_release(struct inode *, struct file *);
 
-#ifdef AFS_CACHING_SUPPORT
-extern int afs_cache_get_page_cookie(struct page *, struct cachefs_page **);
-#endif
-
 /*
  * fsclient.c
  */
 extern struct inode *afs_iget(struct super_block *, struct key *,
                              struct afs_fid *, struct afs_file_status *,
                              struct afs_callback *);
+extern void afs_zap_data(struct afs_vnode *);
 extern int afs_validate(struct afs_vnode *, struct key *);
-extern int afs_inode_getattr(struct vfsmount *, struct dentry *,
-                            struct kstat *);
-extern void afs_zap_permits(struct rcu_head *);
+extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern void afs_clear_inode(struct inode *);
 
 /*
  */
 extern void afs_clear_permits(struct afs_vnode *);
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
+extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
 extern int afs_permission(struct inode *, int, struct nameidata *);
 
        }                                                               \
 } while(0)
 
+#define ASSERTRANGE(L, OP1, N, OP2, H)                                 \
+do {                                                                   \
+       if (unlikely(!((L) OP1 (N)) || !((N) OP2 (H)))) {               \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "AFS: Assertion failed\n");             \
+               printk(KERN_ERR "%lu "#OP1" %lu "#OP2" %lu is false\n", \
+                      (unsigned long)(L), (unsigned long)(N),          \
+                      (unsigned long)(H));                             \
+               printk(KERN_ERR "0x%lx "#OP1" 0x%lx "#OP2" 0x%lx is false\n", \
+                      (unsigned long)(L), (unsigned long)(N),          \
+                      (unsigned long)(H));                             \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
 #define ASSERTIF(C, X)                                         \
 do {                                                           \
        if (unlikely((C) && !(X))) {                            \
 do {                                           \
 } while(0)
 
+#define ASSERTRANGE(L, OP1, N, OP2, H)         \
+do {                                           \
+} while(0)
+
 #define ASSERTIF(C, X)                         \
 do {                                           \
 } while(0)
 
        afs_vlocation_purge();
        afs_cell_purge();
        afs_proc_cleanup();
+       rcu_barrier();
        printk(KERN_ERR "kAFS: failed to register: %d\n", ret);
        return ret;
 }
        cachefs_unregister_netfs(&afs_cache_netfs);
 #endif
        afs_proc_cleanup();
+       rcu_barrier();
 }
 
 module_exit(afs_exit);
 
 {
        switch (abort_code) {
        case 13:                return -EACCES;
+       case 27:                return -EFBIG;
        case 30:                return -EROFS;
        case VSALVAGE:          return -EIO;
        case VNOVNODE:          return -ENOENT;
 
        .lookup         = afs_mntpt_lookup,
        .follow_link    = afs_mntpt_follow_link,
        .readlink       = page_readlink,
-       .getattr        = afs_inode_getattr,
+       .getattr        = afs_getattr,
 };
 
 static LIST_HEAD(afs_vfsmounts);
        char *buf;
        int ret;
 
-       _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
+       _enter("{%x:%u,%u}",
+              vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
 
        /* read the contents of the symlink into the pagecache */
        page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file);
 
 {
        struct afs_permits *permits;
 
-       _enter("{%x}", vnode->fid.vnode);
+       _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
 
        mutex_lock(&vnode->permits_lock);
        permits = vnode->permits;
        struct afs_vnode *auth_vnode;
        int count, loop;
 
-       _enter("{%x},%x,%lx", vnode->fid.vnode, key_serial(key), acl_order);
+       _enter("{%x:%u},%x,%lx",
+              vnode->fid.vid, vnode->fid.vnode, key_serial(key), acl_order);
 
        auth_vnode = afs_get_auth_inode(vnode, key);
        if (IS_ERR(auth_vnode)) {
        bool valid;
        int loop, ret;
 
-       _enter("");
+       _enter("{%x:%u},%x",
+              vnode->fid.vid, vnode->fid.vnode, key_serial(key));
 
        auth_vnode = afs_get_auth_inode(vnode, key);
        if (IS_ERR(auth_vnode)) {
                        _leave(" = %d", ret);
                        return ret;
                }
+               *_access = vnode->status.caller_access;
        }
 
-       *_access = vnode->status.caller_access;
        iput(&auth_vnode->vfs_inode);
        _leave(" = 0 [access %x]", *_access);
        return 0;
        struct key *key;
        int ret;
 
-       _enter("{{%x:%x},%lx},%x,",
+       _enter("{{%x:%u},%lx},%x,",
               vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);
 
        key = afs_request_key(vnode->volume->cell);
 
 {
        _enter("%p", server);
 
+       ASSERTIF(server->cb_break_head != server->cb_break_tail,
+                delayed_work_pending(&server->cb_break_work));
+
        ASSERTCMP(server->fs_vnodes.rb_node, ==, NULL);
        ASSERTCMP(server->cb_promises.rb_node, ==, NULL);
        ASSERTCMP(server->cb_break_head, ==, server->cb_break_tail);
 
 
        DECLARE_WAITQUEUE(myself, current);
 
-       _enter("%s,{%u,%u,%u}",
+       _enter("%s,{%x:%u.%u}",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
 
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,,,",
+       _enter("%s{%x:%u.%u},%x,,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s,,",
+       _enter("%s{%x:%u.%u},%x,%s,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s",
+       _enter("%s{%x:%u.%u},%x,%s",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%s{%u,%u,%u},%x,%s",
+       _enter("%s{%x:%u.%u},%s{%x:%u.%u},%x,%s",
               dvnode->volume->vlocation->vldb.name,
               dvnode->fid.vid,
               dvnode->fid.vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%x,%s,%s,,,",
+       _enter("%s{%x:%u.%u},%x,%s,%s,,,",
               vnode->volume->vlocation->vldb.name,
               vnode->fid.vid,
               vnode->fid.vnode,
        struct afs_server *server;
        int ret;
 
-       _enter("%s{%u,%u,%u},%s{%u,%u,%u},%x,%s,%s",
+       _enter("%s{%x:%u.%u},%s{%u,%u,%u},%x,%s,%s",
               orig_dvnode->volume->vlocation->vldb.name,
               orig_dvnode->fid.vid,
               orig_dvnode->fid.vnode,