From: Andrew Morton <akpm@osdl.org>
To: Chris Mason <mason@suse.com>
Cc: mika.penttila@kolumbus.fi, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] writeback_inodes can race with unmount
Date: Tue, 8 Jun 2004 20:22:17 -0700 [thread overview]
Message-ID: <20040608202217.0b7a6371.akpm@osdl.org> (raw)
In-Reply-To: <1086744565.10973.192.camel@watt.suse.com>
Chris Mason <mason@suse.com> wrote:
>
> On Tue, 2004-06-08 at 17:56, Andrew Morton wrote:
> > Chris Mason <mason@suse.com> wrote:
>
> > > > Why don't we have the same race in the sync() path as well? Moving the
> > > > locking to sync_sb_inodes() itself would fix it also.
> > >
> > > In the sync() path we're already taking a read lock on s_umount sem.
> > > Moving the locking into sync_sb_inodes would be tricky, it is sometimes
> > > called with the write lock on s_umount_sem held and sometimes with a
> > > read lock.
> > >
> >
> > Plus we'd be dead if we had to do the above. If that read_trylock() fails
> > the sync() will forget to sync stuff.
> >
> > And, contra your description, we'll fail the trylock relatively frequently
> > - when some other process is writing back this superblock.
>
> The write lock is taken much less frequently. Should be just on
> mount/unmount no?
OK.
> So, it looks like we get this:
>
> CPU 0 CPU 1
> writeback_inodes generic_shutdown_super
> sync_sb_inodes
> iget(inode)
> spin_unlock(&inode_lock)
> sop->put_super(sb)
> iput(inode)
> generic_delete_inode()
We really shouldn't have got to ->put_super() when there are still live
inodes around. I'd say that the problem lies on the umount path. 2.4
might have the same problem, but it'll be much harder to hit.
Something like this? If so, we should probably lock the inode in
prune_icache() and remove iprune_sem.
--- 25/fs/inode.c~a 2004-06-08 20:06:41.905455400 -0700
+++ 25-akpm/fs/inode.c 2004-06-08 20:19:40.300121424 -0700
@@ -294,10 +294,11 @@ static void dispose_list(struct list_hea
/*
* Invalidate all inodes for a device.
*/
-static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
+static int invalidate_list(struct list_head *head, struct super_block *sb,
+ struct list_head *dispose)
{
struct list_head *next;
- int busy = 0, count = 0;
+ int ret = 0, count = 0;
next = head->next;
for (;;) {
@@ -311,6 +312,17 @@ static int invalidate_list(struct list_h
if (inode->i_sb != sb)
continue;
invalidate_inode_buffers(inode);
+ if (inode->i_state & I_LOCK) {
+ __iget(inode);
+ inodes_stat.nr_unused -= count;
+ count = 0;
+ spin_unlock(&inode_lock);
+ wait_on_inode(inode);
+ iput(inode);
+ ret = 2;
+ spin_lock(&inode_lock);
+ break;
+ }
if (!atomic_read(&inode->i_count)) {
hlist_del_init(&inode->i_hash);
list_move(&inode->i_list, dispose);
@@ -318,11 +330,11 @@ static int invalidate_list(struct list_h
count++;
continue;
}
- busy = 1;
+ ret = 1;
}
/* only unused inodes may be cached with i_count zero */
inodes_stat.nr_unused -= count;
- return busy;
+ return ret;
}
/*
@@ -343,21 +355,23 @@ static int invalidate_list(struct list_h
*/
int invalidate_inodes(struct super_block * sb)
{
- int busy;
+ int state;
LIST_HEAD(throw_away);
down(&iprune_sem);
spin_lock(&inode_lock);
- busy = invalidate_list(&inode_in_use, sb, &throw_away);
- busy |= invalidate_list(&inode_unused, sb, &throw_away);
- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
- busy |= invalidate_list(&sb->s_io, sb, &throw_away);
+ do {
+ state = invalidate_list(&inode_in_use, sb, &throw_away);
+ state |= invalidate_list(&inode_unused, sb, &throw_away);
+ state |= invalidate_list(&sb->s_dirty, sb, &throw_away);
+ state |= invalidate_list(&sb->s_io, sb, &throw_away);
+ } while (state & 2);
spin_unlock(&inode_lock);
dispose_list(&throw_away);
up(&iprune_sem);
- return busy;
+ return state;
}
EXPORT_SYMBOL(invalidate_inodes);
_
next prev parent reply other threads:[~2004-06-09 3:23 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-06-08 19:22 Chris Mason
2004-06-08 19:57 ` Mika Penttilä
2004-06-08 20:18 ` Chris Mason
2004-06-08 21:56 ` Andrew Morton
2004-06-09 1:29 ` Chris Mason
2004-06-09 3:22 ` Andrew Morton [this message]
2004-06-09 5:24 ` Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040608202217.0b7a6371.akpm@osdl.org \
--to=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mason@suse.com \
--cc=mika.penttila@kolumbus.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®