/*
  * check that a directory page is valid
  */
-static inline bool afs_dir_check_page(struct inode *dir, struct page *page)
+bool afs_dir_check_page(struct inode *dir, struct page *page)
 {
        struct afs_dir_page *dbuf;
-       loff_t latter;
+       struct afs_vnode *vnode = AFS_FS_I(dir);
+       loff_t latter, i_size, off;
        int tmp, qty;
 
 #if 0
        }
 #endif
 
-       /* determine how many magic numbers there should be in this page */
-       latter = dir->i_size - page_offset(page);
+       /* Determine how many magic numbers there should be in this page, but
+        * we must take care because the directory may change size under us.
+        */
+       off = page_offset(page);
+       i_size = i_size_read(dir);
+       if (i_size <= off)
+               goto checked;
+
+       latter = i_size - off;
        if (latter >= PAGE_SIZE)
                qty = PAGE_SIZE;
        else
        dbuf = page_address(page);
        for (tmp = 0; tmp < qty; tmp++) {
                if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
-                       printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
+                       printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n",
                               __func__, dir->i_ino, tmp, qty,
                               ntohs(dbuf->blocks[tmp].pagehdr.magic));
+                       trace_afs_dir_check_failed(vnode, off, i_size);
                        goto error;
                }
        }
 
+checked:
        SetPageChecked(page);
        return true;
 
 static inline void afs_dir_put_page(struct page *page)
 {
        kunmap(page);
+       unlock_page(page);
        put_page(page);
 }
 
 
        page = read_cache_page(dir->i_mapping, index, afs_page_filler, key);
        if (!IS_ERR(page)) {
+               lock_page(page);
                kmap(page);
                if (unlikely(!PageChecked(page))) {
-                       if (PageError(page) || !afs_dir_check_page(dir, page))
+                       if (PageError(page))
                                goto fail;
                }
        }
  */
 static int afs_readdir(struct file *file, struct dir_context *ctx)
 {
-       return afs_dir_iterate(file_inode(file),
-                             ctx, file->private_data);
+       return afs_dir_iterate(file_inode(file), ctx, file->private_data);
 }
 
 /*
 
                      __entry->cursor, __entry->ret)
            );
 
+TRACE_EVENT(afs_dir_check_failed,
+           TP_PROTO(struct afs_vnode *vnode, loff_t off, loff_t i_size),
+
+           TP_ARGS(vnode, off, i_size),
+
+           TP_STRUCT__entry(
+                   __field(struct afs_vnode *,         vnode           )
+                   __field(loff_t,                     off             )
+                   __field(loff_t,                     i_size          )
+                            ),
+
+           TP_fast_assign(
+                   __entry->vnode = vnode;
+                   __entry->off = off;
+                   __entry->i_size = i_size;
+                          ),
+
+           TP_printk("vn=%p %llx/%llx",
+                     __entry->vnode, __entry->off, __entry->i_size)
+           );
+
 #endif /* _TRACE_AFS_H */
 
 /* This part must be outside protection */