Re: 2.1.50 VFS: Busy inodes after unmount. Self-destruct in 5 seconds.

Bill Hawes (whawes@star.net)
Sat, 16 Aug 1997 16:59:29 -0400


This is a multi-part message in MIME format.
--------------0545BB4EA1E727515F4BA8C0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Craig Schlenter wrote:
> I get the messages in the subject when trying to unmount a iso9660 cdrom.
> I also get them when trying to unmount a loop mounted iso9660 filesystem
> (been playing with a cdwriter).

Craig,
I tried playing with a CDROM and didn't get any busy inodes, so maybe
the cdwriter is forgetting to release an inode.

I made some changes to invalidate_inodes so that it can be called prior
to the unmounting, as it's really not safe to proceed with unmounting
with inodes still in use. The attached patch will check for this and
print out a list of the busy inodes -- by name if they have a name,
otherwise by number.

Could you please try to reproduce the problem and see what inodes are
busy? Then hopefully the cdwriter (or kernel) can be fixed ...

Regards,
Bill
--------------0545BB4EA1E727515F4BA8C0
Content-Type: text/plain; charset=us-ascii; name="inode_busy50-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="inode_busy50-patch"

--- fs/inode.c.old Thu Aug 14 18:44:06 1997
+++ fs/inode.c Sat Aug 16 16:39:04 1997
@@ -251,14 +254,15 @@
break;
inode = list_entry(tmp, struct inode, i_list);
truncate_inode_pages(inode, 0);
}

/* Add them all to the unused list in one fell swoop */
spin_lock(&inode_lock);
list_splice(head, &inode_unused);
spin_unlock(&inode_lock);
}

+#define INODE_PARANOIA 1
/*
* Invalidate all inodes for a device.
*/
@@ -278,6 +284,8 @@
inode = list_entry(tmp, struct inode, i_list);
if (inode->i_sb != sb)
continue;
+ if (sb->s_root && inode == sb->s_root->d_inode)
+ continue;
if (!inode->i_count) {
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
@@ -287,6 +295,39 @@
}
busy = 1;
}
+
+#ifdef INODE_PARANOIA
+ /*
+ * Display the busy inodes
+ */
+ if (busy) {
+ struct list_head * tmp;
+ struct inode * inode;
+ struct dentry * alias;
+
+ printk("Busy Inodes for Device %s:\n", kdevname(sb->s_dev));
+ for (tmp = head->next; tmp != head; tmp = tmp->next) {
+ inode = list_entry(tmp, struct inode, i_list);
+ if (inode->i_sb != sb)
+ continue;
+ if (sb->s_root && inode == sb->s_root->d_inode)
+ continue;
+ if (!inode->i_count)
+ continue;
+ if (!list_empty(&inode->i_dentry)) {
+ alias = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ printk("inode %s/%s: count=%d state=%lx\n",
+ alias->d_parent->d_name.name,
+ alias->d_name.name,
+ inode->i_count, inode->i_state);
+ } else
+ printk("inode %ld: count=%d state=%lx\n",
+ inode->i_ino, inode->i_count,
+ inode->i_state);
+ }
+ }
+#endif
return busy;
}

--- fs/super.c.old Thu Aug 14 18:44:06 1997
+++ fs/super.c Sat Aug 16 16:31:24 1997
@@ -628,6 +629,8 @@
*/
shrink_dcache();
fsync_dev(dev);
+ if (invalidate_inodes(sb))
+ return -EBUSY;

retval = d_umount(sb);
if (retval)

--------------0545BB4EA1E727515F4BA8C0--