diff options
author | Eric Sandeen <sandeen@redhat.com> | 2009-12-14 14:00:30 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2009-12-23 07:44:11 -0500 |
commit | b8a052d01669977f224255b0f9f2737018171ddb (patch) | |
tree | 2ef6c2e038d269f2bc4eb73e82439f0301d5c6b1 /fs/ext3 | |
parent | 4854a5f0cbb1967fc7db3ea861d97afeea78b88b (diff) |
ext3: Replace lock/unlock_super() with an explicit lock for the orphan list
Use a separate lock to protect the orphan list, so we can stop
overloading the use of lock_super().
Port of ext4 commit 3b9d4ed26680771295d904a6b83e88e620780893
by Theodore Ts'o <tytso@mit.edu>.
CC: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/namei.c | 20 | ||||
-rw-r--r-- | fs/ext3/super.c | 1 |
2 files changed, 12 insertions, 9 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 81f7348b2de3..7b0e44f7d66f 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1920,7 +1920,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) | |||
1920 | struct ext3_iloc iloc; | 1920 | struct ext3_iloc iloc; |
1921 | int err = 0, rc; | 1921 | int err = 0, rc; |
1922 | 1922 | ||
1923 | lock_super(sb); | 1923 | mutex_lock(&EXT3_SB(sb)->s_orphan_lock); |
1924 | if (!list_empty(&EXT3_I(inode)->i_orphan)) | 1924 | if (!list_empty(&EXT3_I(inode)->i_orphan)) |
1925 | goto out_unlock; | 1925 | goto out_unlock; |
1926 | 1926 | ||
@@ -1929,9 +1929,13 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) | |||
1929 | 1929 | ||
1930 | /* @@@ FIXME: Observation from aviro: | 1930 | /* @@@ FIXME: Observation from aviro: |
1931 | * I think I can trigger J_ASSERT in ext3_orphan_add(). We block | 1931 | * I think I can trigger J_ASSERT in ext3_orphan_add(). We block |
1932 | * here (on lock_super()), so race with ext3_link() which might bump | 1932 | * here (on s_orphan_lock), so race with ext3_link() which might bump |
1933 | * ->i_nlink. For, say it, character device. Not a regular file, | 1933 | * ->i_nlink. For, say it, character device. Not a regular file, |
1934 | * not a directory, not a symlink and ->i_nlink > 0. | 1934 | * not a directory, not a symlink and ->i_nlink > 0. |
1935 | * | ||
1936 | * tytso, 4/25/2009: I'm not sure how that could happen; | ||
1937 | * shouldn't the fs core protect us from these sort of | ||
1938 | * unlink()/link() races? | ||
1935 | */ | 1939 | */ |
1936 | J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1940 | J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
1937 | S_ISLNK(inode->i_mode)) || inode->i_nlink == 0); | 1941 | S_ISLNK(inode->i_mode)) || inode->i_nlink == 0); |
@@ -1968,7 +1972,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) | |||
1968 | jbd_debug(4, "orphan inode %lu will point to %d\n", | 1972 | jbd_debug(4, "orphan inode %lu will point to %d\n", |
1969 | inode->i_ino, NEXT_ORPHAN(inode)); | 1973 | inode->i_ino, NEXT_ORPHAN(inode)); |
1970 | out_unlock: | 1974 | out_unlock: |
1971 | unlock_super(sb); | 1975 | mutex_unlock(&EXT3_SB(sb)->s_orphan_lock); |
1972 | ext3_std_error(inode->i_sb, err); | 1976 | ext3_std_error(inode->i_sb, err); |
1973 | return err; | 1977 | return err; |
1974 | } | 1978 | } |
@@ -1986,11 +1990,9 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) | |||
1986 | struct ext3_iloc iloc; | 1990 | struct ext3_iloc iloc; |
1987 | int err = 0; | 1991 | int err = 0; |
1988 | 1992 | ||
1989 | lock_super(inode->i_sb); | 1993 | mutex_lock(&EXT3_SB(inode->i_sb)->s_orphan_lock); |
1990 | if (list_empty(&ei->i_orphan)) { | 1994 | if (list_empty(&ei->i_orphan)) |
1991 | unlock_super(inode->i_sb); | 1995 | goto out; |
1992 | return 0; | ||
1993 | } | ||
1994 | 1996 | ||
1995 | ino_next = NEXT_ORPHAN(inode); | 1997 | ino_next = NEXT_ORPHAN(inode); |
1996 | prev = ei->i_orphan.prev; | 1998 | prev = ei->i_orphan.prev; |
@@ -2040,7 +2042,7 @@ int ext3_orphan_del(handle_t *handle, struct inode *inode) | |||
2040 | out_err: | 2042 | out_err: |
2041 | ext3_std_error(inode->i_sb, err); | 2043 | ext3_std_error(inode->i_sb, err); |
2042 | out: | 2044 | out: |
2043 | unlock_super(inode->i_sb); | 2045 | mutex_unlock(&EXT3_SB(inode->i_sb)->s_orphan_lock); |
2044 | return err; | 2046 | return err; |
2045 | 2047 | ||
2046 | out_brelse: | 2048 | out_brelse: |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 806b8b780add..97dd3828384c 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -1928,6 +1928,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1928 | sb->dq_op = &ext3_quota_operations; | 1928 | sb->dq_op = &ext3_quota_operations; |
1929 | #endif | 1929 | #endif |
1930 | INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ | 1930 | INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ |
1931 | mutex_init(&sbi->s_orphan_lock); | ||
1931 | 1932 | ||
1932 | sb->s_root = NULL; | 1933 | sb->s_root = NULL; |
1933 | 1934 | ||