summaryrefslogtreecommitdiffstats
path: root/fs/ufs/super.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-06-17 12:02:56 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-07-06 17:39:25 -0400
commit724bb09fdc06d4ff03757b25d6dba9ef1b133e8f (patch)
tree5ef4441867f681e132d820c78948b34c0f0ca1df /fs/ufs/super.c
parent4af7b2c080715b9452fdaefb7ada72b4dc79593e (diff)
downloadlinux-724bb09fdc06d4ff03757b25d6dba9ef1b133e8f.tar.gz
linux-724bb09fdc06d4ff03757b25d6dba9ef1b133e8f.tar.bz2
linux-724bb09fdc06d4ff03757b25d6dba9ef1b133e8f.zip
ufs: don't use lock_ufs() for block pointers tree protection
* stores to block pointers are under per-inode seqlock (meta_lock) and mutex (truncate_mutex) * fetches of block pointers are either under truncate_mutex, or wrapped into seqretry loop on meta_lock * all changes of ->i_size are under truncate_mutex and i_mutex * all changes of ->i_lastfrag are under truncate_mutex It's similar to what ext2 is doing; the main difference is that unlike ext2 we can't rely upon the atomicity of stores into block pointers - on UFS2 they are 64bit. So we can't cut the corner when switching a pointer from NULL to non-NULL as we could in ext2_splice_branch() and need to use meta_lock on all modifications. We use seqlock where ext2 uses rwlock; ext2 could probably also benefit from such change... Another non-trivial difference is that with UFS we *cannot* have reader grab truncate_mutex in case of race - it has to keep retrying. That might be possible to change, but not until we lift tail unpacking several levels up in call chain. After that commit we do *NOT* hold fs-wide serialization on accesses to block pointers anymore. Moreover, lock_ufs() can become a normal mutex now - it's only used on statfs, remount and sync_fs and none of those uses are recursive. As the matter of fact, *now* it can be collapsed with ->s_lock, and be eventually replaced with saner per-cylinder-group spinlocks, but that's a separate story. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ufs/super.c')
-rw-r--r--fs/ufs/super.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 250579a80d90..15cd3338340c 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1429,6 +1429,8 @@ static struct inode *ufs_alloc_inode(struct super_block *sb)
return NULL;
ei->vfs_inode.i_version = 1;
+ seqlock_init(&ei->meta_lock);
+ mutex_init(&ei->truncate_mutex);
return &ei->vfs_inode;
}