diff --git a/fs/9p/cache.c b/fs/9p/cache.c index eb2151fb6049..59b59291609c 100644 --- a/fs/9p/cache.c +++ b/fs/9p/cache.c @@ -122,6 +122,30 @@ void v9fs_cache_inode_get_cookie(struct inode *inode) i_size_read(&v9inode->vfs_inode), true); + if (!v9inode->fscache) { + struct v9fs_debug *db, *next; + + mutex_lock(&v9fs_debug_tree_mutex); + db = v9fs_debug_search(inode->i_ino); + printk("[DEBUG] inode: %ld quid: %x.%llx.%x\n", + inode->i_ino, + v9inode->qid.type, + (unsigned long long)v9inode->qid.path, + v9inode->qid.version); + if (db) + printk("[DEBUG] found in tree qid: %x.%llx.%x removing: %d\n", + db->type, (unsigned long long)db->path, + db->version, db->removing); + rbtree_postorder_for_each_entry_safe(db, next, &v9fs_debug_tree, node) { + if (db->path == v9inode->qid.path && + db->version == v9inode->qid.version) + printk("[DEBUG] found dup ino: %ld %x.%llx.%x removing: %d\n", + db->inode, + db->type, (unsigned long long)db->path, + db->version, db->removing); + } + mutex_unlock(&v9fs_debug_tree_mutex); + } p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", inode, v9inode->fscache); } diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 4ca56c5dd637..7935ab56453c 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -119,6 +119,22 @@ struct v9fs_inode { struct inode vfs_inode; }; +struct v9fs_debug { + struct rb_node node; + unsigned long inode; + u8 type; + u32 version; + u64 path; + bool removing; +}; + +extern struct rb_root v9fs_debug_tree; +extern struct mutex v9fs_debug_tree_mutex; +extern void v9fs_debug_remove(unsigned long inode); +extern void v9fs_debug_tag(unsigned long inode); +extern struct v9fs_debug *v9fs_debug_search(unsigned long inode); +extern void v9fs_debug_insert(unsigned long inode, u8 type, u32 version, u64 path); + static inline struct v9fs_inode *V9FS_I(const struct inode *inode) { return container_of(inode, struct v9fs_inode, vfs_inode); diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 795706520b5e..e5ebec787c28 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -377,6 +377,7 @@ void v9fs_evict_inode(struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); + v9fs_debug_tag(inode->i_ino); truncate_inode_pages_final(&inode->i_data); clear_inode(inode); filemap_fdatawrite(&inode->i_data); @@ -387,6 +388,7 @@ void v9fs_evict_inode(struct inode *inode) p9_client_clunk(v9inode->writeback_fid); v9inode->writeback_fid = NULL; } + v9fs_debug_remove(inode->i_ino); } static int v9fs_test_inode(struct inode *inode, void *data) diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index e1c0240b51c0..56a7bc0c627b 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -32,6 +32,9 @@ #include "xattr.h" #include "acl.h" +struct rb_root v9fs_debug_tree = RB_ROOT; +DEFINE_MUTEX(v9fs_debug_tree_mutex); + static int v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, struct dentry *dentry, umode_t omode, dev_t rdev); @@ -94,6 +97,94 @@ static int v9fs_set_inode_dotl(struct inode *inode, void *data) return 0; } +struct v9fs_debug *v9fs_debug_search(unsigned long inode) +{ + struct rb_node *node = v9fs_debug_tree.rb_node; + + while (node) { + struct v9fs_debug *data = container_of(node, struct v9fs_debug, node); + + if (data->inode < inode) + node = node->rb_left; + else if (data->inode > inode) + node = node->rb_right; + else + return data; + } + return NULL; +} + +void v9fs_debug_tag(unsigned long inode) +{ + struct v9fs_debug *node; + + mutex_lock(&v9fs_debug_tree_mutex); + node = v9fs_debug_search(inode); + if (node) + node->removing = true; + else + printk("[DEBUG] can't find %ld for tagging\n", inode); + mutex_unlock(&v9fs_debug_tree_mutex); +} + +void v9fs_debug_remove(unsigned long inode) +{ + struct v9fs_debug *node; + + mutex_lock(&v9fs_debug_tree_mutex); + node = v9fs_debug_search(inode); + if (node) { + rb_erase(&node->node, &v9fs_debug_tree); + kfree(node); + } else + printk("[DEBUG] can't find %ld\n", inode); + mutex_unlock(&v9fs_debug_tree_mutex); +} + +void v9fs_debug_insert(unsigned long inode, u8 type, u32 version, u64 path) +{ + struct v9fs_debug *db = NULL; + struct rb_node **node, *parent = NULL; + + mutex_lock(&v9fs_debug_tree_mutex); + node = &(v9fs_debug_tree.rb_node); + while (*node) { + parent = *node; + db = container_of(*node, struct v9fs_debug, node); + + if (db->inode < inode) + node = &((*node)->rb_left); + else if (db->inode > inode) + node = &((*node)->rb_right); + else + break; + } + if (!db || (db->inode != inode)) { + db = kmalloc(sizeof(*db), GFP_KERNEL); + if (db) { + db->inode = inode; + db->type = type; + db->version = version; + db->path = path; + db->removing = false; + rb_link_node(&db->node, parent, node); + rb_insert_color(&db->node, &v9fs_debug_tree); + } else + printk("[DEBUG] Failed to alloc memory!\n"); + } + if (db) { + if (type != db->type || + version != db->version || + path != db->path) { + db->inode = inode; + db->type = type; + db->version = version; + db->path = path; + } + } + mutex_unlock(&v9fs_debug_tree_mutex); +} + static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, struct p9_qid *qid, struct p9_fid *fid, @@ -134,6 +225,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, if (retval) goto error; + v9fs_debug_insert(inode->i_ino, qid->type, qid->version, qid->path); unlock_new_inode(inode); return inode; error: