diff options
Diffstat (limited to 'fs/reiserfs/super.c')
| -rw-r--r-- | fs/reiserfs/super.c | 65 | 
1 files changed, 51 insertions, 14 deletions
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 7a37dabf5a9..418bdc3a57d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)  			retval = remove_save_link_only(s, &save_link_key, 0);  			continue;  		} +		reiserfs_write_unlock(s);  		dquot_initialize(inode); +		reiserfs_write_lock(s);  		if (truncate && S_ISDIR(inode->i_mode)) {  			/* We got a truncate request for a dir which is impossible. @@ -608,6 +610,11 @@ static int init_inodecache(void)  static void destroy_inodecache(void)  { +	/* +	 * Make sure all delayed rcu free inodes are flushed before we +	 * destroy cache. +	 */ +	rcu_barrier();  	kmem_cache_destroy(reiserfs_inode_cachep);  } @@ -1330,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  				kfree(qf_names[i]);  #endif  		err = -EINVAL; -		goto out_err; +		goto out_unlock;  	}  #ifdef CONFIG_QUOTA  	handle_quota_files(s, qf_names, &qfmt); @@ -1374,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  	if (blocks) {  		err = reiserfs_resize(s, blocks);  		if (err != 0) -			goto out_err; +			goto out_unlock;  	}  	if (*mount_flags & MS_RDONLY) { @@ -1384,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  			/* it is read-only already */  			goto out_ok; +		/* +		 * Drop write lock. Quota will retake it when needed and lock +		 * ordering requires calling dquot_suspend() without it. +		 */ +		reiserfs_write_unlock(s);  		err = dquot_suspend(s, -1);  		if (err < 0)  			goto out_err; +		reiserfs_write_lock(s);  		/* try to remount file system with read-only permissions */  		if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1396,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  		err = journal_begin(&th, s, 10);  		if (err) -			goto out_err; +			goto out_unlock;  		/* Mounting a rw partition read-only. */  		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1411,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  		if (reiserfs_is_journal_aborted(journal)) {  			err = journal->j_errno; -			goto out_err; +			goto out_unlock;  		}  		handle_data_mode(s, mount_options); @@ -1420,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  		s->s_flags &= ~MS_RDONLY;	/* now it is safe to call journal_begin */  		err = journal_begin(&th, s, 10);  		if (err) -			goto out_err; +			goto out_unlock;  		/* Mount a partition which is read-only, read-write */  		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1437,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)  	SB_JOURNAL(s)->j_must_wait = 1;  	err = journal_end(&th, s, 10);  	if (err) -		goto out_err; +		goto out_unlock;  	if (!(*mount_flags & MS_RDONLY)) { +		/* +		 * Drop write lock. Quota will retake it when needed and lock +		 * ordering requires calling dquot_resume() without it. +		 */ +		reiserfs_write_unlock(s);  		dquot_resume(s, -1); +		reiserfs_write_lock(s);  		finish_unfinished(s);  		reiserfs_xattr_init(s, *mount_flags);  	} @@ -1450,9 +1469,10 @@ out_ok:  	reiserfs_write_unlock(s);  	return 0; +out_unlock: +	reiserfs_write_unlock(s);  out_err:  	kfree(new_opts); -	reiserfs_write_unlock(s);  	return err;  } @@ -2090,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)  			  REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));  	if (ret)  		goto out; +	reiserfs_write_unlock(dquot->dq_sb);  	ret = dquot_commit(dquot); +	reiserfs_write_lock(dquot->dq_sb);  	err =  	    journal_end(&th, dquot->dq_sb,  			REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));  	if (!ret && err)  		ret = err; -      out: +out:  	reiserfs_write_unlock(dquot->dq_sb);  	return ret;  } @@ -2112,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)  			  REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));  	if (ret)  		goto out; +	reiserfs_write_unlock(dquot->dq_sb);  	ret = dquot_acquire(dquot); +	reiserfs_write_lock(dquot->dq_sb);  	err =  	    journal_end(&th, dquot->dq_sb,  			REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));  	if (!ret && err)  		ret = err; -      out: +out:  	reiserfs_write_unlock(dquot->dq_sb);  	return ret;  } @@ -2132,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)  	ret =  	    journal_begin(&th, dquot->dq_sb,  			  REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); +	reiserfs_write_unlock(dquot->dq_sb);  	if (ret) {  		/* Release dquot anyway to avoid endless cycle in dqput() */  		dquot_release(dquot);  		goto out;  	}  	ret = dquot_release(dquot); +	reiserfs_write_lock(dquot->dq_sb);  	err =  	    journal_end(&th, dquot->dq_sb,  			REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));  	if (!ret && err)  		ret = err; -      out:  	reiserfs_write_unlock(dquot->dq_sb); +out:  	return ret;  } @@ -2169,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)  	ret = journal_begin(&th, sb, 2);  	if (ret)  		goto out; +	reiserfs_write_unlock(sb);  	ret = dquot_commit_info(sb, type); +	reiserfs_write_lock(sb);  	err = journal_end(&th, sb, 2);  	if (!ret && err)  		ret = err; -      out: +out:  	reiserfs_write_unlock(sb);  	return ret;  } @@ -2198,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,  	struct reiserfs_transaction_handle th;  	int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; -	if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) -		return -EINVAL; +	reiserfs_write_lock(sb); +	if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { +		err = -EINVAL; +		goto out; +	}  	/* Quotafile not on the same filesystem? */  	if (path->dentry->d_sb != sb) { @@ -2241,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,  		if (err)  			goto out;  	} -	err = dquot_quota_on(sb, type, format_id, path); +	reiserfs_write_unlock(sb); +	return dquot_quota_on(sb, type, format_id, path);  out: +	reiserfs_write_unlock(sb);  	return err;  } @@ -2315,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,  		tocopy = sb->s_blocksize - offset < towrite ?  		    sb->s_blocksize - offset : towrite;  		tmp_bh.b_state = 0; +		reiserfs_write_lock(sb);  		err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); +		reiserfs_write_unlock(sb);  		if (err)  			goto out;  		if (offset || tocopy != sb->s_blocksize) @@ -2331,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,  		flush_dcache_page(bh->b_page);  		set_buffer_uptodate(bh);  		unlock_buffer(bh); +		reiserfs_write_lock(sb);  		reiserfs_prepare_for_journal(sb, bh, 1);  		journal_mark_dirty(current->journal_info, sb, bh);  		if (!journal_quota)  			reiserfs_add_ordered_list(inode, bh); +		reiserfs_write_unlock(sb);  		brelse(bh);  		offset = 0;  		towrite -= tocopy;  |