patch-2.1.48 linux/fs/inode.c
Next file: linux/fs/namei.c
Previous file: linux/fs/hpfs/hpfs_fs.c
Back to the patch index
Back to the overall index
- Lines: 127
- Date:
Sun Aug 3 00:22:23 1997
- Orig file:
v2.1.47/linux/fs/inode.c
- Orig date:
Sun Jul 27 12:11:01 1997
diff -u --recursive --new-file v2.1.47/linux/fs/inode.c linux/fs/inode.c
@@ -206,14 +206,36 @@
inode->i_state = 0;
}
-#define CAN_UNUSE(inode) \
- (((inode)->i_count == 0) && \
- ((inode)->i_nrpages == 0) && \
- (!(inode)->i_state))
+/*
+ * Dispose-list gets a local list, so it doesn't need to
+ * worry about list corruption.
+ */
+static void dispose_list(struct list_head * head)
+{
+ struct list_head *next;
+
+ next = head->next;
+ for (;;) {
+ struct list_head * tmp = next;
+ struct inode * inode;
-static void invalidate_list(struct list_head *head, kdev_t dev)
+ next = next->next;
+ if (tmp == head)
+ 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);
+}
+
+static int invalidate_list(struct list_head *head, kdev_t dev, struct list_head * dispose)
{
struct list_head *next;
+ int busy = 0;
next = head->next;
for (;;) {
@@ -225,22 +247,39 @@
break;
inode = list_entry(tmp, struct inode, i_list);
if (inode->i_dev != dev)
- continue;
- if (!CAN_UNUSE(inode))
continue;
- list_del(&inode->i_hash);
- INIT_LIST_HEAD(&inode->i_hash);
- list_del(&inode->i_list);
- list_add(&inode->i_list, &inode_unused);
+ if (!inode->i_count && !inode->i_state) {
+ list_del(&inode->i_hash);
+ INIT_LIST_HEAD(&inode->i_hash);
+ list_del(&inode->i_list);
+ list_add(&inode->i_list, dispose);
+ continue;
+ }
+ busy = 1;
}
+ return busy;
}
-void invalidate_inodes(kdev_t dev)
+/*
+ * This is a two-stage process. First we collect all
+ * offending inodes onto the throw-away list, and in
+ * the second stage we actually dispose of them. This
+ * is because we don't want to sleep while messing
+ * with the global lists..
+ */
+int invalidate_inodes(kdev_t dev)
{
+ int busy;
+ LIST_HEAD(throw_away);
+
spin_lock(&inode_lock);
- invalidate_list(&inode_in_use, dev);
- invalidate_list(&inode_dirty, dev);
+ busy = invalidate_list(&inode_in_use, dev, &throw_away);
+ busy |= invalidate_list(&inode_dirty, dev, &throw_away);
spin_unlock(&inode_lock);
+
+ dispose_list(&throw_away);
+
+ return busy;
}
/*
@@ -251,6 +290,11 @@
* Otherwise we just move the inode to be the first inode and expect to
* get back to the problem later..
*/
+#define CAN_UNUSE(inode) \
+ (((inode)->i_count == 0) && \
+ ((inode)->i_nrpages == 0) && \
+ (!(inode)->i_state))
+
static void try_to_free_inodes(void)
{
struct list_head * tmp;
@@ -504,7 +548,22 @@
return root->d_count == 1;
}
+/* This belongs in file_table.c, not here... */
int fs_may_remount_ro(struct super_block *sb)
{
- return 1;
+ struct file *file;
+ kdev_t dev = sb->s_dev;
+
+ /* Check that no files are currently opened for writing. */
+ for (file = inuse_filps; file; file = file->f_next) {
+ struct inode *inode;
+ if (!file->f_dentry)
+ continue;
+ inode = file->f_dentry->d_inode;
+ if (!inode || inode->i_dev != dev)
+ continue;
+ if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE)
+ return 0;
+ }
+ return 1; /* Tis' cool bro. */
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov