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

Commit 31b7a57c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from Chris Mason:
 "This is an assortment of fixes.  Most of the commits are from Filipe
  (fsync, the inode allocation cache and a few others).  Mark kicked in
  a series fixing corners in the extent sharing ioctls, and everyone
  else fixed up on assorted other problems"

* 'for-linus-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: fix wrong check for btrfs_force_chunk_alloc()
  Btrfs: fix warning of bytes_may_use
  Btrfs: fix hang when failing to submit bio of directIO
  Btrfs: fix a comment in inode.c:evict_inode_truncate_pages()
  Btrfs: fix memory corruption on failure to submit bio for direct IO
  btrfs: don't update mtime/ctime on deduped inodes
  btrfs: allow dedupe of same inode
  btrfs: fix deadlock with extent-same and readpage
  btrfs: pass unaligned length to btrfs_cmp_data()
  Btrfs: fix fsync after truncate when no_holes feature is enabled
  Btrfs: fix fsync xattr loss in the fast fsync path
  Btrfs: fix fsync data loss after append write
  Btrfs: fix crash on close_ctree() if cleaner starts new transaction
  Btrfs: fix race between caching kthread and returning inode to inode cache
  Btrfs: use kmem_cache_free when freeing entry in inode cache
  Btrfs: fix race between balance and unused block group deletion
  btrfs: add error handling for scrub_workers_get()
  btrfs: cleanup noused initialization of dev in btrfs_end_bio()
  btrfs: qgroup: allow user to clear the limitation on qgroup
parents 84e3e9d0 9689457b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@
#define BTRFS_INODE_IN_DELALLOC_LIST		9
#define BTRFS_INODE_READDIO_NEED_LOCK		10
#define BTRFS_INODE_HAS_PROPS		        11
/* DIO is ready to submit */
#define BTRFS_INODE_DIO_READY		        12
/*
 * The following 3 bits are meant only for the btree inode.
 * When any of them is set, it means an error happened while writing an
+1 −0
Original line number Diff line number Diff line
@@ -1778,6 +1778,7 @@ struct btrfs_fs_info {
	spinlock_t unused_bgs_lock;
	struct list_head unused_bgs;
	struct mutex unused_bg_unpin_mutex;
	struct mutex delete_unused_bgs_mutex;

	/* For btrfs to record security options */
	struct security_mnt_opts security_opts;
+40 −1
Original line number Diff line number Diff line
@@ -1751,6 +1751,7 @@ static int cleaner_kthread(void *arg)
{
	struct btrfs_root *root = arg;
	int again;
	struct btrfs_trans_handle *trans;

	do {
		again = 0;
@@ -1772,7 +1773,6 @@ static int cleaner_kthread(void *arg)
		}

		btrfs_run_delayed_iputs(root);
		btrfs_delete_unused_bgs(root->fs_info);
		again = btrfs_clean_one_deleted_snapshot(root);
		mutex_unlock(&root->fs_info->cleaner_mutex);

@@ -1781,6 +1781,16 @@ static int cleaner_kthread(void *arg)
		 * needn't do anything special here.
		 */
		btrfs_run_defrag_inodes(root->fs_info);

		/*
		 * Acquires fs_info->delete_unused_bgs_mutex to avoid racing
		 * with relocation (btrfs_relocate_chunk) and relocation
		 * acquires fs_info->cleaner_mutex (btrfs_relocate_block_group)
		 * after acquiring fs_info->delete_unused_bgs_mutex. So we
		 * can't hold, nor need to, fs_info->cleaner_mutex when deleting
		 * unused block groups.
		 */
		btrfs_delete_unused_bgs(root->fs_info);
sleep:
		if (!try_to_freeze() && !again) {
			set_current_state(TASK_INTERRUPTIBLE);
@@ -1789,6 +1799,34 @@ static int cleaner_kthread(void *arg)
			__set_current_state(TASK_RUNNING);
		}
	} while (!kthread_should_stop());

	/*
	 * Transaction kthread is stopped before us and wakes us up.
	 * However we might have started a new transaction and COWed some
	 * tree blocks when deleting unused block groups for example. So
	 * make sure we commit the transaction we started to have a clean
	 * shutdown when evicting the btree inode - if it has dirty pages
	 * when we do the final iput() on it, eviction will trigger a
	 * writeback for it which will fail with null pointer dereferences
	 * since work queues and other resources were already released and
	 * destroyed by the time the iput/eviction/writeback is made.
	 */
	trans = btrfs_attach_transaction(root);
	if (IS_ERR(trans)) {
		if (PTR_ERR(trans) != -ENOENT)
			btrfs_err(root->fs_info,
				  "cleaner transaction attach returned %ld",
				  PTR_ERR(trans));
	} else {
		int ret;

		ret = btrfs_commit_transaction(trans, root);
		if (ret)
			btrfs_err(root->fs_info,
				  "cleaner open transaction commit returned %d",
				  ret);
	}

	return 0;
}

@@ -2492,6 +2530,7 @@ int open_ctree(struct super_block *sb,
	spin_lock_init(&fs_info->unused_bgs_lock);
	rwlock_init(&fs_info->tree_mod_log_lock);
	mutex_init(&fs_info->unused_bg_unpin_mutex);
	mutex_init(&fs_info->delete_unused_bgs_mutex);
	mutex_init(&fs_info->reloc_mutex);
	mutex_init(&fs_info->delalloc_root_mutex);
	seqlock_init(&fs_info->profiles_lock);
+3 −0
Original line number Diff line number Diff line
@@ -9889,6 +9889,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
		}
		spin_unlock(&fs_info->unused_bgs_lock);

		mutex_lock(&root->fs_info->delete_unused_bgs_mutex);

		/* Don't want to race with allocators so take the groups_sem */
		down_write(&space_info->groups_sem);
		spin_lock(&block_group->lock);
@@ -9983,6 +9985,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
end_trans:
		btrfs_end_transaction(trans, root);
next:
		mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
		btrfs_put_block_group(block_group);
		spin_lock(&fs_info->unused_bgs_lock);
	}
+12 −5
Original line number Diff line number Diff line
@@ -246,6 +246,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
{
	struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
	struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset;
	spinlock_t *rbroot_lock = &root->free_ino_pinned->tree_lock;
	struct btrfs_free_space *info;
	struct rb_node *n;
	u64 count;
@@ -254,24 +255,30 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
		return;

	while (1) {
		bool add_to_ctl = true;

		spin_lock(rbroot_lock);
		n = rb_first(rbroot);
		if (!n)
		if (!n) {
			spin_unlock(rbroot_lock);
			break;
		}

		info = rb_entry(n, struct btrfs_free_space, offset_index);
		BUG_ON(info->bitmap); /* Logic error */

		if (info->offset > root->ino_cache_progress)
			goto free;
			add_to_ctl = false;
		else if (info->offset + info->bytes > root->ino_cache_progress)
			count = root->ino_cache_progress - info->offset + 1;
		else
			count = info->bytes;

		__btrfs_add_free_space(ctl, info->offset, count);
free:
		rb_erase(&info->offset_index, rbroot);
		kfree(info);
		spin_unlock(rbroot_lock);
		if (add_to_ctl)
			__btrfs_add_free_space(ctl, info->offset, count);
		kmem_cache_free(btrfs_free_space_cachep, info);
	}
}

Loading