Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9902af79 authored by Al Viro's avatar Al Viro
Browse files

parallel lookups: actual switch to rwsem



ta-da!

The main issue is the lack of down_write_killable(), so the places
like readdir.c switched to plain inode_lock(); once killable
variants of rwsem primitives appear, that'll be dealt with.

lockdep side also might need more work

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d9171b93
Loading
Loading
Loading
Loading
+18 −0
Original line number Original line Diff line number Diff line
@@ -539,3 +539,21 @@ in your dentry operations instead.
	it's a symlink.  Checking ->i_mode is really needed now.  In-tree we had
	it's a symlink.  Checking ->i_mode is really needed now.  In-tree we had
	to fix shmem_destroy_callback() that used to take that kind of shortcut;
	to fix shmem_destroy_callback() that used to take that kind of shortcut;
	watch out, since that shortcut is no longer valid.
	watch out, since that shortcut is no longer valid.
--
[mandatory]
	->i_mutex is replaced with ->i_rwsem now.  inode_lock() et.al. work as
	they used to - they just take it exclusive.  However, ->lookup() may be
	called with parent locked shared.  Its instances must not
		* use d_instantiate) and d_rehash() separately - use d_add() or
		  d_splice_alias() instead.
		* use d_rehash() alone - call d_add(new_dentry, NULL) instead.
		* in the unlikely case when (read-only) access to filesystem
		  data structures needs exclusion for some reason, arrange it
		  yourself.  None of the in-tree filesystems needed that.
		* rely on ->d_parent and ->d_name not changing after dentry has
		  been fed to d_add() or d_splice_alias().  Again, none of the
		  in-tree instances relied upon that.
	We are guaranteed that lookups of the same name in the same directory
	will not happen in parallel ("same" in the sense of your ->d_compare()).
	Lookups on different names in the same directory can and do happen in
	parallel now.
+11 −7
Original line number Original line Diff line number Diff line
@@ -837,9 +837,11 @@ static noinline int btrfs_mksubvol(struct path *parent,
	struct dentry *dentry;
	struct dentry *dentry;
	int error;
	int error;


	error = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
	inode_lock_nested(dir, I_MUTEX_PARENT);
	if (error == -EINTR)
	// XXX: should've been
		return error;
	// mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
	// if (error == -EINTR)
	//	return error;


	dentry = lookup_one_len(name, parent->dentry, namelen);
	dentry = lookup_one_len(name, parent->dentry, namelen);
	error = PTR_ERR(dentry);
	error = PTR_ERR(dentry);
@@ -2366,9 +2368,11 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
		goto out;
		goto out;




	err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
	inode_lock_nested(dir, I_MUTEX_PARENT);
	if (err == -EINTR)
	// XXX: should've been
		goto out_drop_write;
	// err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
	// if (err == -EINTR)
	//	goto out_drop_write;
	dentry = lookup_one_len(vol_args->name, parent, namelen);
	dentry = lookup_one_len(vol_args->name, parent, namelen);
	if (IS_ERR(dentry)) {
	if (IS_ERR(dentry)) {
		err = PTR_ERR(dentry);
		err = PTR_ERR(dentry);
@@ -2558,7 +2562,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
	dput(dentry);
	dput(dentry);
out_unlock_dir:
out_unlock_dir:
	inode_unlock(dir);
	inode_unlock(dir);
out_drop_write:
//out_drop_write:
	mnt_drop_write_file(file);
	mnt_drop_write_file(file);
out:
out:
	kfree(vol_args);
	kfree(vol_args);
+1 −1
Original line number Original line Diff line number Diff line
@@ -156,7 +156,7 @@ static void configfs_set_inode_lock_class(struct configfs_dirent *sd,


	if (depth > 0) {
	if (depth > 0) {
		if (depth <= ARRAY_SIZE(default_group_class)) {
		if (depth <= ARRAY_SIZE(default_group_class)) {
			lockdep_set_class(&inode->i_mutex,
			lockdep_set_class(&inode->i_rwsem,
					  &default_group_class[depth - 1]);
					  &default_group_class[depth - 1]);
		} else {
		} else {
			/*
			/*
+5 −4
Original line number Original line Diff line number Diff line
@@ -2932,7 +2932,8 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
static int __d_unalias(struct inode *inode,
static int __d_unalias(struct inode *inode,
		struct dentry *dentry, struct dentry *alias)
		struct dentry *dentry, struct dentry *alias)
{
{
	struct mutex *m1 = NULL, *m2 = NULL;
	struct mutex *m1 = NULL;
	struct rw_semaphore *m2 = NULL;
	int ret = -ESTALE;
	int ret = -ESTALE;


	/* If alias and dentry share a parent, then no extra locks required */
	/* If alias and dentry share a parent, then no extra locks required */
@@ -2943,15 +2944,15 @@ static int __d_unalias(struct inode *inode,
	if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
	if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
		goto out_err;
		goto out_err;
	m1 = &dentry->d_sb->s_vfs_rename_mutex;
	m1 = &dentry->d_sb->s_vfs_rename_mutex;
	if (!inode_trylock(alias->d_parent->d_inode))
	if (!inode_trylock_shared(alias->d_parent->d_inode))
		goto out_err;
		goto out_err;
	m2 = &alias->d_parent->d_inode->i_mutex;
	m2 = &alias->d_parent->d_inode->i_rwsem;
out_unalias:
out_unalias:
	__d_move(alias, dentry, false);
	__d_move(alias, dentry, false);
	ret = 0;
	ret = 0;
out_err:
out_err:
	if (m2)
	if (m2)
		mutex_unlock(m2);
		up_read(m2);
	if (m1)
	if (m1)
		mutex_unlock(m1);
		mutex_unlock(m1);
	return ret;
	return ret;
+1 −1
Original line number Original line Diff line number Diff line
@@ -824,7 +824,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
	 * i_mutex on quota files is special. Since this inode is hidden system
	 * i_mutex on quota files is special. Since this inode is hidden system
	 * file, we are safe to define locking ourselves.
	 * file, we are safe to define locking ourselves.
	 */
	 */
	lockdep_set_class(&sdp->sd_quota_inode->i_mutex,
	lockdep_set_class(&sdp->sd_quota_inode->i_rwsem,
			  &gfs2_quota_imutex_key);
			  &gfs2_quota_imutex_key);


	error = gfs2_rindex_update(sdp);
	error = gfs2_rindex_update(sdp);
Loading