Unverified Commit 02f95e7a authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11919 btrfs: fix race between direct IO write and fsync when using same fd

parents 71c81e62 b8eccdd4
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -445,7 +445,6 @@ struct btrfs_file_private {
	void *filldir_buf;
	u64 last_index;
	struct extent_state *llseek_cached_state;
	bool fsync_skip_inode_lock;
};

static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info)
+10 −15
Original line number Diff line number Diff line
@@ -1543,13 +1543,6 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
	if (IS_ERR_OR_NULL(dio)) {
		err = PTR_ERR_OR_ZERO(dio);
	} else {
		struct btrfs_file_private stack_private = { 0 };
		struct btrfs_file_private *private;
		const bool have_private = (file->private_data != NULL);

		if (!have_private)
			file->private_data = &stack_private;

		/*
		 * If we have a synchoronous write, we must make sure the fsync
		 * triggered by the iomap_dio_complete() call below doesn't
@@ -1558,13 +1551,10 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
		 * partial writes due to the input buffer (or parts of it) not
		 * being already faulted in.
		 */
		private = file->private_data;
		private->fsync_skip_inode_lock = true;
		ASSERT(current->journal_info == NULL);
		current->journal_info = BTRFS_TRANS_DIO_WRITE_STUB;
		err = iomap_dio_complete(dio);
		private->fsync_skip_inode_lock = false;

		if (!have_private)
			file->private_data = NULL;
		current->journal_info = NULL;
	}

	/* No increment (+=) because iomap returns a cumulative value. */
@@ -1796,7 +1786,6 @@ static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx)
 */
int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
{
	struct btrfs_file_private *private = file->private_data;
	struct dentry *dentry = file_dentry(file);
	struct inode *inode = d_inode(dentry);
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@@ -1806,7 +1795,13 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
	int ret = 0, err;
	u64 len;
	bool full_sync;
	const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false);
	bool skip_ilock = false;

	if (current->journal_info == BTRFS_TRANS_DIO_WRITE_STUB) {
		skip_ilock = true;
		current->journal_info = NULL;
		lockdep_assert_held(&inode->i_rwsem);
	}

	trace_btrfs_sync_file(file, datasync);

+6 −0
Original line number Diff line number Diff line
@@ -12,6 +12,12 @@
#include "ctree.h"
#include "misc.h"

/*
 * Signal that a direct IO write is in progress, to avoid deadlock for sync
 * direct IO writes when fsync is called during the direct IO write path.
 */
#define BTRFS_TRANS_DIO_WRITE_STUB	((void *) 1)

/* Radix-tree tag for roots that are part of the trasaction. */
#define BTRFS_ROOT_TRANS_TAG			0