summary refs log tree commit diff
path: root/fs/logfs
diff options
context:
space:
mode:
authorPrasad Joshi <prasadjoshi.linux@gmail.com>2012-03-09 06:27:12 +0530
committerPrasad Joshi <prasadjoshi.linux@gmail.com>2012-04-02 09:20:33 +0530
commitd2dcd9083f101584e029cbd4f0e1a4e573170d43 (patch)
tree1b64355958937bd425901f950342be58fa2a6286 /fs/logfs
parentdd775ae2549217d3ae09363e3edb305d0fa19928 (diff)
downloadlinux-d2dcd9083f101584e029cbd4f0e1a4e573170d43.tar.gz
logfs: destroy the reserved inodes while unmounting
We were assuming that the evict_inode() would never be called on
reserved inodes. However, (after the commit 8e22c1a4e logfs: get rid
of magical inodes) while unmounting the file system, in put_super, we
call iput() on all of the reserved inodes.

The following simple test used to cause a kernel panic on LogFS:

1. Mount a LogFS file system on /mnt

2. Create a file
   $ touch /mnt/a

3. Try to unmount the FS
   $ umount /mnt

The simple fix would be to drop the assumption and properly destroy
the reserved inodes.

Signed-off-by: Prasad Joshi <prasadjoshi.linux@gmail.com>
Diffstat (limited to 'fs/logfs')
-rw-r--r--fs/logfs/inode.c16
-rw-r--r--fs/logfs/readwrite.c1
-rw-r--r--fs/logfs/segment.c2
3 files changed, 17 insertions, 2 deletions
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index a422f42238b2..df093d9e4da1 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -156,10 +156,26 @@ static void __logfs_destroy_inode(struct inode *inode)
 	call_rcu(&inode->i_rcu, logfs_i_callback);
 }
 
+static void __logfs_destroy_meta_inode(struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	BUG_ON(li->li_block);
+	call_rcu(&inode->i_rcu, logfs_i_callback);
+}
+
 static void logfs_destroy_inode(struct inode *inode)
 {
 	struct logfs_inode *li = logfs_inode(inode);
 
+	if (inode->i_ino < LOGFS_RESERVED_INOS) {
+		/*
+		 * The reserved inodes are never destroyed unless we are in
+		 * unmont path.
+		 */
+		__logfs_destroy_meta_inode(inode);
+		return;
+	}
+
 	BUG_ON(list_empty(&li->li_freeing_list));
 	spin_lock(&logfs_inode_lock);
 	li->li_refcount--;
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index e3ab5e5a904c..c8ea8664699c 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -2189,7 +2189,6 @@ void logfs_evict_inode(struct inode *inode)
 		return;
 	}
 
-	BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS);
 	page = inode_to_page(inode);
 	BUG_ON(!page); /* FIXME: Use emergency page */
 	logfs_put_write_page(page);
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index e28d090c98d6..038da0991794 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -886,7 +886,7 @@ static struct logfs_area *alloc_area(struct super_block *sb)
 
 static void map_invalidatepage(struct page *page, unsigned long l)
 {
-	BUG();
+	return;
 }
 
 static int map_releasepage(struct page *page, gfp_t g)