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

Commit 567a45e9 authored by Chris Mason's avatar Chris Mason
Browse files

Merge branch 'for-chris' of...

Merge branch 'for-chris' of http://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-work

 into integration

Conflicts:
	fs/btrfs/inode.c

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parents e755d9ab e65cbb94
Loading
Loading
Loading
Loading
+54 −61
Original line number Original line Diff line number Diff line
@@ -64,6 +64,8 @@ struct btrfs_worker_thread {
	int idle;
	int idle;
};
};


static int __btrfs_start_workers(struct btrfs_workers *workers);

/*
/*
 * btrfs_start_workers uses kthread_run, which can block waiting for memory
 * btrfs_start_workers uses kthread_run, which can block waiting for memory
 * for a very long time.  It will actually throttle on page writeback,
 * for a very long time.  It will actually throttle on page writeback,
@@ -88,25 +90,8 @@ static void start_new_worker_func(struct btrfs_work *work)
{
{
	struct worker_start *start;
	struct worker_start *start;
	start = container_of(work, struct worker_start, work);
	start = container_of(work, struct worker_start, work);
	btrfs_start_workers(start->queue, 1);
	__btrfs_start_workers(start->queue);
	kfree(start);
}

static int start_new_worker(struct btrfs_workers *queue)
{
	struct worker_start *start;
	int ret;

	start = kzalloc(sizeof(*start), GFP_NOFS);
	if (!start)
		return -ENOMEM;

	start->work.func = start_new_worker_func;
	start->queue = queue;
	ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work);
	if (ret)
	kfree(start);
	kfree(start);
	return ret;
}
}


/*
/*
@@ -153,12 +138,20 @@ static void check_busy_worker(struct btrfs_worker_thread *worker)
static void check_pending_worker_creates(struct btrfs_worker_thread *worker)
static void check_pending_worker_creates(struct btrfs_worker_thread *worker)
{
{
	struct btrfs_workers *workers = worker->workers;
	struct btrfs_workers *workers = worker->workers;
	struct worker_start *start;
	unsigned long flags;
	unsigned long flags;


	rmb();
	rmb();
	if (!workers->atomic_start_pending)
	if (!workers->atomic_start_pending)
		return;
		return;


	start = kzalloc(sizeof(*start), GFP_NOFS);
	if (!start)
		return;

	start->work.func = start_new_worker_func;
	start->queue = workers;

	spin_lock_irqsave(&workers->lock, flags);
	spin_lock_irqsave(&workers->lock, flags);
	if (!workers->atomic_start_pending)
	if (!workers->atomic_start_pending)
		goto out;
		goto out;
@@ -170,10 +163,11 @@ static void check_pending_worker_creates(struct btrfs_worker_thread *worker)


	workers->num_workers_starting += 1;
	workers->num_workers_starting += 1;
	spin_unlock_irqrestore(&workers->lock, flags);
	spin_unlock_irqrestore(&workers->lock, flags);
	start_new_worker(workers);
	btrfs_queue_worker(workers->atomic_worker_start, &start->work);
	return;
	return;


out:
out:
	kfree(start);
	spin_unlock_irqrestore(&workers->lock, flags);
	spin_unlock_irqrestore(&workers->lock, flags);
}
}


@@ -462,14 +456,11 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
 * starts new worker threads.  This does not enforce the max worker
 * starts new worker threads.  This does not enforce the max worker
 * count in case you need to temporarily go past it.
 * count in case you need to temporarily go past it.
 */
 */
static int __btrfs_start_workers(struct btrfs_workers *workers,
static int __btrfs_start_workers(struct btrfs_workers *workers)
				 int num_workers)
{
{
	struct btrfs_worker_thread *worker;
	struct btrfs_worker_thread *worker;
	int ret = 0;
	int ret = 0;
	int i;


	for (i = 0; i < num_workers; i++) {
	worker = kzalloc(sizeof(*worker), GFP_NOFS);
	worker = kzalloc(sizeof(*worker), GFP_NOFS);
	if (!worker) {
	if (!worker) {
		ret = -ENOMEM;
		ret = -ENOMEM;
@@ -486,7 +477,7 @@ static int __btrfs_start_workers(struct btrfs_workers *workers,
	worker->workers = workers;
	worker->workers = workers;
	worker->task = kthread_run(worker_loop, worker,
	worker->task = kthread_run(worker_loop, worker,
				   "btrfs-%s-%d", workers->name,
				   "btrfs-%s-%d", workers->name,
					   workers->num_workers + i);
				   workers->num_workers + 1);
	if (IS_ERR(worker->task)) {
	if (IS_ERR(worker->task)) {
		ret = PTR_ERR(worker->task);
		ret = PTR_ERR(worker->task);
		kfree(worker);
		kfree(worker);
@@ -499,19 +490,21 @@ static int __btrfs_start_workers(struct btrfs_workers *workers,
	workers->num_workers_starting--;
	workers->num_workers_starting--;
	WARN_ON(workers->num_workers_starting < 0);
	WARN_ON(workers->num_workers_starting < 0);
	spin_unlock_irq(&workers->lock);
	spin_unlock_irq(&workers->lock);
	}

	return 0;
	return 0;
fail:
fail:
	btrfs_stop_workers(workers);
	spin_lock_irq(&workers->lock);
	workers->num_workers_starting--;
	spin_unlock_irq(&workers->lock);
	return ret;
	return ret;
}
}


int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
int btrfs_start_workers(struct btrfs_workers *workers)
{
{
	spin_lock_irq(&workers->lock);
	spin_lock_irq(&workers->lock);
	workers->num_workers_starting += num_workers;
	workers->num_workers_starting++;
	spin_unlock_irq(&workers->lock);
	spin_unlock_irq(&workers->lock);
	return __btrfs_start_workers(workers, num_workers);
	return __btrfs_start_workers(workers);
}
}


/*
/*
@@ -568,6 +561,7 @@ static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers)
	struct btrfs_worker_thread *worker;
	struct btrfs_worker_thread *worker;
	unsigned long flags;
	unsigned long flags;
	struct list_head *fallback;
	struct list_head *fallback;
	int ret;


again:
again:
	spin_lock_irqsave(&workers->lock, flags);
	spin_lock_irqsave(&workers->lock, flags);
@@ -584,7 +578,9 @@ again:
			workers->num_workers_starting++;
			workers->num_workers_starting++;
			spin_unlock_irqrestore(&workers->lock, flags);
			spin_unlock_irqrestore(&workers->lock, flags);
			/* we're below the limit, start another worker */
			/* we're below the limit, start another worker */
			__btrfs_start_workers(workers, 1);
			ret = __btrfs_start_workers(workers);
			if (ret)
				goto fallback;
			goto again;
			goto again;
		}
		}
	}
	}
@@ -665,7 +661,7 @@ void btrfs_set_work_high_prio(struct btrfs_work *work)
/*
/*
 * places a struct btrfs_work into the pending queue of one of the kthreads
 * places a struct btrfs_work into the pending queue of one of the kthreads
 */
 */
int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
{
{
	struct btrfs_worker_thread *worker;
	struct btrfs_worker_thread *worker;
	unsigned long flags;
	unsigned long flags;
@@ -673,7 +669,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)


	/* don't requeue something already on a list */
	/* don't requeue something already on a list */
	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
		goto out;
		return;


	worker = find_worker(workers);
	worker = find_worker(workers);
	if (workers->ordered) {
	if (workers->ordered) {
@@ -712,7 +708,4 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
	if (wake)
	if (wake)
		wake_up_process(worker->task);
		wake_up_process(worker->task);
	spin_unlock_irqrestore(&worker->lock, flags);
	spin_unlock_irqrestore(&worker->lock, flags);

out:
	return 0;
}
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -109,8 +109,8 @@ struct btrfs_workers {
	char *name;
	char *name;
};
};


int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
int btrfs_start_workers(struct btrfs_workers *workers);
int btrfs_stop_workers(struct btrfs_workers *workers);
int btrfs_stop_workers(struct btrfs_workers *workers);
void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
			struct btrfs_workers *async_starter);
			struct btrfs_workers *async_starter);
+2 −1
Original line number Original line Diff line number Diff line
@@ -2692,7 +2692,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
int btrfs_readpage(struct file *file, struct page *page);
int btrfs_readpage(struct file *file, struct page *page);
void btrfs_evict_inode(struct inode *inode);
void btrfs_evict_inode(struct inode *inode);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
void btrfs_dirty_inode(struct inode *inode, int flags);
int btrfs_dirty_inode(struct inode *inode);
int btrfs_update_time(struct file *file);
struct inode *btrfs_alloc_inode(struct super_block *sb);
struct inode *btrfs_alloc_inode(struct super_block *sb);
void btrfs_destroy_inode(struct inode *inode);
void btrfs_destroy_inode(struct inode *inode);
int btrfs_drop_inode(struct inode *inode);
int btrfs_drop_inode(struct inode *inode);
+21 −13
Original line number Original line Diff line number Diff line
@@ -2194,19 +2194,27 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	fs_info->endio_meta_write_workers.idle_thresh = 2;
	fs_info->endio_meta_write_workers.idle_thresh = 2;
	fs_info->readahead_workers.idle_thresh = 2;
	fs_info->readahead_workers.idle_thresh = 2;


	btrfs_start_workers(&fs_info->workers, 1);
	/*
	btrfs_start_workers(&fs_info->generic_worker, 1);
	 * btrfs_start_workers can really only fail because of ENOMEM so just
	btrfs_start_workers(&fs_info->submit_workers, 1);
	 * return -ENOMEM if any of these fail.
	btrfs_start_workers(&fs_info->delalloc_workers, 1);
	 */
	btrfs_start_workers(&fs_info->fixup_workers, 1);
	ret = btrfs_start_workers(&fs_info->workers);
	btrfs_start_workers(&fs_info->endio_workers, 1);
	ret |= btrfs_start_workers(&fs_info->generic_worker);
	btrfs_start_workers(&fs_info->endio_meta_workers, 1);
	ret |= btrfs_start_workers(&fs_info->submit_workers);
	btrfs_start_workers(&fs_info->endio_meta_write_workers, 1);
	ret |= btrfs_start_workers(&fs_info->delalloc_workers);
	btrfs_start_workers(&fs_info->endio_write_workers, 1);
	ret |= btrfs_start_workers(&fs_info->fixup_workers);
	btrfs_start_workers(&fs_info->endio_freespace_worker, 1);
	ret |= btrfs_start_workers(&fs_info->endio_workers);
	btrfs_start_workers(&fs_info->delayed_workers, 1);
	ret |= btrfs_start_workers(&fs_info->endio_meta_workers);
	btrfs_start_workers(&fs_info->caching_workers, 1);
	ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers);
	btrfs_start_workers(&fs_info->readahead_workers, 1);
	ret |= btrfs_start_workers(&fs_info->endio_write_workers);
	ret |= btrfs_start_workers(&fs_info->endio_freespace_worker);
	ret |= btrfs_start_workers(&fs_info->delayed_workers);
	ret |= btrfs_start_workers(&fs_info->caching_workers);
	ret |= btrfs_start_workers(&fs_info->readahead_workers);
	if (ret) {
		ret = -ENOMEM;
		goto fail_sb_buffer;
	}


	fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
	fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
	fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
	fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
+31 −14
Original line number Original line Diff line number Diff line
@@ -2822,7 +2822,7 @@ out_free:
	btrfs_release_path(path);
	btrfs_release_path(path);
out:
out:
	spin_lock(&block_group->lock);
	spin_lock(&block_group->lock);
	if (!ret)
	if (!ret && dcs == BTRFS_DC_SETUP)
		block_group->cache_generation = trans->transid;
		block_group->cache_generation = trans->transid;
	block_group->disk_cache_state = dcs;
	block_group->disk_cache_state = dcs;
	spin_unlock(&block_group->lock);
	spin_unlock(&block_group->lock);
@@ -4203,12 +4203,17 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
	struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
	u64 to_reserve = 0;
	u64 to_reserve = 0;
	u64 csum_bytes;
	unsigned nr_extents = 0;
	unsigned nr_extents = 0;
	int extra_reserve = 0;
	int flush = 1;
	int flush = 1;
	int ret;
	int ret;


	/* Need to be holding the i_mutex here if we aren't free space cache */
	if (btrfs_is_free_space_inode(root, inode))
	if (btrfs_is_free_space_inode(root, inode))
		flush = 0;
		flush = 0;
	else
		WARN_ON(!mutex_is_locked(&inode->i_mutex));


	if (flush && btrfs_transaction_in_commit(root->fs_info))
	if (flush && btrfs_transaction_in_commit(root->fs_info))
		schedule_timeout(1);
		schedule_timeout(1);
@@ -4219,11 +4224,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
	BTRFS_I(inode)->outstanding_extents++;
	BTRFS_I(inode)->outstanding_extents++;


	if (BTRFS_I(inode)->outstanding_extents >
	if (BTRFS_I(inode)->outstanding_extents >
	    BTRFS_I(inode)->reserved_extents) {
	    BTRFS_I(inode)->reserved_extents)
		nr_extents = BTRFS_I(inode)->outstanding_extents -
		nr_extents = BTRFS_I(inode)->outstanding_extents -
			BTRFS_I(inode)->reserved_extents;
			BTRFS_I(inode)->reserved_extents;
		BTRFS_I(inode)->reserved_extents += nr_extents;
	}


	/*
	/*
	 * Add an item to reserve for updating the inode when we complete the
	 * Add an item to reserve for updating the inode when we complete the
@@ -4231,11 +4234,12 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
	 */
	 */
	if (!BTRFS_I(inode)->delalloc_meta_reserved) {
	if (!BTRFS_I(inode)->delalloc_meta_reserved) {
		nr_extents++;
		nr_extents++;
		BTRFS_I(inode)->delalloc_meta_reserved = 1;
		extra_reserve = 1;
	}
	}


	to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
	to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
	to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
	to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
	csum_bytes = BTRFS_I(inode)->csum_bytes;
	spin_unlock(&BTRFS_I(inode)->lock);
	spin_unlock(&BTRFS_I(inode)->lock);


	ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
	ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
@@ -4245,22 +4249,35 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)


		spin_lock(&BTRFS_I(inode)->lock);
		spin_lock(&BTRFS_I(inode)->lock);
		dropped = drop_outstanding_extent(inode);
		dropped = drop_outstanding_extent(inode);
		/*
		 * If the inodes csum_bytes is the same as the original
		 * csum_bytes then we know we haven't raced with any free()ers
		 * so we can just reduce our inodes csum bytes and carry on.
		 * Otherwise we have to do the normal free thing to account for
		 * the case that the free side didn't free up its reserve
		 * because of this outstanding reservation.
		 */
		if (BTRFS_I(inode)->csum_bytes == csum_bytes)
			calc_csum_metadata_size(inode, num_bytes, 0);
		else
			to_free = calc_csum_metadata_size(inode, num_bytes, 0);
			to_free = calc_csum_metadata_size(inode, num_bytes, 0);
		spin_unlock(&BTRFS_I(inode)->lock);
		spin_unlock(&BTRFS_I(inode)->lock);
		if (dropped)
			to_free += btrfs_calc_trans_metadata_size(root, dropped);
			to_free += btrfs_calc_trans_metadata_size(root, dropped);


		/*
		 * Somebody could have come in and twiddled with the
		 * reservation, so if we have to free more than we would have
		 * reserved from this reservation go ahead and release those
		 * bytes.
		 */
		to_free -= to_reserve;
		if (to_free)
		if (to_free)
			btrfs_block_rsv_release(root, block_rsv, to_free);
			btrfs_block_rsv_release(root, block_rsv, to_free);
		return ret;
		return ret;
	}
	}


	spin_lock(&BTRFS_I(inode)->lock);
	if (extra_reserve) {
		BTRFS_I(inode)->delalloc_meta_reserved = 1;
		nr_extents--;
	}
	BTRFS_I(inode)->reserved_extents += nr_extents;
	spin_unlock(&BTRFS_I(inode)->lock);

	block_rsv_add_bytes(block_rsv, to_reserve, 1);
	block_rsv_add_bytes(block_rsv, to_reserve, 1);


	return 0;
	return 0;
Loading