lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Tue, 4 Jul 2017 09:44:55 +1000
From:   Stephen Rothwell <sfr@...b.auug.org.au>
To:     David Sterba <dsterba@...e.cz>
Cc:     Chris Mason <clm@...com>, Josef Bacik <jbacik@...com>,
        Jens Axboe <axboe@...nel.dk>, Christoph Hellwig <hch@....de>,
        Linux-Next Mailing List <linux-next@...r.kernel.org>,
        Linus Trovalds <torvalds@...ux-foundation.org>,
        LKML <linux-kernel@...r.kernel.org>
Subject: linux-next: btrfs merge resolution

Hi all,

Since the block tree has been merged into Linus' tree, here is the
merge resolution from my merge of the btrfs-kdave tree today:

36c639d65d6a6e596d73ccf285adf9fffc9097b8
diff --cc fs/btrfs/disk-io.c
index 6036d15b47b8,b6758892874f..7065201bedcf
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@@ -87,9 -87,8 +87,8 @@@ struct btrfs_end_io_wq 
  	bio_end_io_t *end_io;
  	void *private;
  	struct btrfs_fs_info *info;
 -	int error;
 +	blk_status_t status;
  	enum btrfs_wq_endio_type metadata;
- 	struct list_head list;
  	struct btrfs_work work;
  };
  
@@@ -868,10 -867,10 +867,10 @@@ unsigned long btrfs_async_submit_limit(
  static void run_one_async_start(struct btrfs_work *work)
  {
  	struct async_submit_bio *async;
 -	int ret;
 +	blk_status_t ret;
  
  	async = container_of(work, struct  async_submit_bio, work);
- 	ret = async->submit_bio_start(async->inode, async->bio,
+ 	ret = async->submit_bio_start(async->private_data, async->bio,
  				      async->mirror_num, async->bio_flags,
  				      async->bio_offset);
  	if (ret)
@@@ -916,19 -915,20 +915,20 @@@ static void run_one_async_free(struct b
  	kfree(async);
  }
  
- blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info,
- 		struct inode *inode, struct bio *bio, int mirror_num,
- 		unsigned long bio_flags, u64 bio_offset,
- 		extent_submit_bio_hook_t *submit_bio_start,
- 		extent_submit_bio_hook_t *submit_bio_done)
 -int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
++blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ 			int mirror_num, unsigned long bio_flags,
+ 			u64 bio_offset, void *private_data,
+ 			extent_submit_bio_hook_t *submit_bio_start,
+ 			extent_submit_bio_hook_t *submit_bio_done)
  {
  	struct async_submit_bio *async;
  
  	async = kmalloc(sizeof(*async), GFP_NOFS);
  	if (!async)
 -		return -ENOMEM;
 +		return BLK_STS_RESOURCE;
  
- 	async->inode = inode;
+ 	async->private_data = private_data;
+ 	async->fs_info = fs_info;
  	async->bio = bio;
  	async->mirror_num = mirror_num;
  	async->submit_bio_start = submit_bio_start;
@@@ -971,12 -971,12 +971,12 @@@ static blk_status_t btree_csum_one_bio(
  			break;
  	}
  
 -	return ret;
 +	return errno_to_blk_status(ret);
  }
  
- static blk_status_t __btree_submit_bio_start(struct inode *inode,
- 		struct bio *bio, int mirror_num, unsigned long bio_flags,
- 		u64 bio_offset)
 -static int __btree_submit_bio_start(void *private_data, struct bio *bio,
++static blk_status_t __btree_submit_bio_start(void *private_data, struct bio *bio,
+ 				    int mirror_num, unsigned long bio_flags,
+ 				    u64 bio_offset)
  {
  	/*
  	 * when we're called for a write, we're already in the async
@@@ -985,11 -985,12 +985,12 @@@
  	return btree_csum_one_bio(bio);
  }
  
- static blk_status_t __btree_submit_bio_done(struct inode *inode,
- 		struct bio *bio, int mirror_num, unsigned long bio_flags,
- 		u64 bio_offset)
 -static int __btree_submit_bio_done(void *private_data, struct bio *bio,
++static blk_status_t __btree_submit_bio_done(void *private_data, struct bio *bio,
+ 				 int mirror_num, unsigned long bio_flags,
+ 				 u64 bio_offset)
  {
+ 	struct inode *inode = private_data;
 -	int ret;
 +	blk_status_t ret;
  
  	/*
  	 * when we're called for a write, we're already in the async
@@@ -1014,13 -1015,14 +1015,14 @@@ static int check_async_write(unsigned l
  	return 1;
  }
  
- static blk_status_t btree_submit_bio_hook(struct inode *inode, struct bio *bio,
 -static int btree_submit_bio_hook(void *private_data, struct bio *bio,
++static blk_status_t btree_submit_bio_hook(void *private_data, struct bio *bio,
  				 int mirror_num, unsigned long bio_flags,
  				 u64 bio_offset)
  {
+ 	struct inode *inode = private_data;
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	int async = check_async_write(bio_flags);
 -	int ret;
 +	blk_status_t ret;
  
  	if (bio_op(bio) != REQ_OP_WRITE) {
  		/*
@@@ -3490,59 -3485,57 +3485,57 @@@ static void btrfs_end_empty_barrier(str
  }
  
  /*
-  * trigger flushes for one the devices.  If you pass wait == 0, the flushes are
-  * sent down.  With wait == 1, it waits for the previous flush.
-  *
-  * any device where the flush fails with eopnotsupp are flagged as not-barrier
-  * capable
+  * Submit a flush request to the device if it supports it. Error handling is
+  * done in the waiting counterpart.
   */
- static blk_status_t write_dev_flush(struct btrfs_device *device, int wait)
+ static void write_dev_flush(struct btrfs_device *device)
  {
  	struct request_queue *q = bdev_get_queue(device->bdev);
- 	struct bio *bio;
- 	blk_status_t ret = 0;
+ 	struct bio *bio = device->flush_bio;
  
  	if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags))
- 		return 0;
+ 		return;
  
- 	if (wait) {
- 		bio = device->flush_bio;
- 		if (!bio)
- 			return 0;
+ 	bio_reset(bio);
+ 	bio->bi_end_io = btrfs_end_empty_barrier;
+ 	bio->bi_bdev = device->bdev;
+ 	bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH;
+ 	init_completion(&device->flush_wait);
+ 	bio->bi_private = &device->flush_wait;
  
- 		wait_for_completion(&device->flush_wait);
+ 	submit_bio(bio);
+ 	device->flush_bio_sent = 1;
+ }
  
- 		if (bio->bi_status) {
- 			ret = bio->bi_status;
- 			btrfs_dev_stat_inc_and_print(device,
- 				BTRFS_DEV_STAT_FLUSH_ERRS);
- 		}
+ /*
+  * If the flush bio has been submitted by write_dev_flush, wait for it.
+  */
 -static int wait_dev_flush(struct btrfs_device *device)
++static blk_status_t wait_dev_flush(struct btrfs_device *device)
+ {
+ 	struct bio *bio = device->flush_bio;
  
- 		/* drop the reference from the wait == 0 run */
- 		bio_put(bio);
- 		device->flush_bio = NULL;
+ 	if (!device->flush_bio_sent)
+ 		return 0;
  
- 		return ret;
- 	}
+ 	device->flush_bio_sent = 0;
+ 	wait_for_completion_io(&device->flush_wait);
  
- 	/*
- 	 * one reference for us, and we leave it for the
- 	 * caller
- 	 */
- 	device->flush_bio = NULL;
- 	bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
- 	if (!bio)
- 		return BLK_STS_RESOURCE;
 -	return bio->bi_error;
++	return bio->bi_status;
+ }
  
- 	bio->bi_end_io = btrfs_end_empty_barrier;
- 	bio->bi_bdev = device->bdev;
- 	bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH;
- 	init_completion(&device->flush_wait);
- 	bio->bi_private = &device->flush_wait;
- 	device->flush_bio = bio;
+ static int check_barrier_error(struct btrfs_fs_devices *fsdevs)
+ {
+ 	int dev_flush_error = 0;
+ 	struct btrfs_device *dev;
  
- 	bio_get(bio);
- 	btrfsic_submit_bio(bio);
+ 	list_for_each_entry_rcu(dev, &fsdevs->devices, dev_list) {
+ 		if (!dev->bdev || dev->last_flush_error)
+ 			dev_flush_error++;
+ 	}
+ 
+ 	if (dev_flush_error >
+ 	    fsdevs->fs_info->num_tolerated_disk_barrier_failures)
+ 		return -EIO;
  
  	return 0;
  }
@@@ -3555,9 -3548,8 +3548,8 @@@ static int barrier_all_devices(struct b
  {
  	struct list_head *head;
  	struct btrfs_device *dev;
- 	int errors_send = 0;
  	int errors_wait = 0;
 -	int ret;
 +	blk_status_t ret;
  
  	/* send down all the barriers */
  	head = &info->fs_devices->devices;
diff --cc fs/btrfs/disk-io.h
index c581927555f3,4654d129aa76..0a634d3ffc16
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@@ -118,16 -118,16 +118,16 @@@ int btrfs_buffer_uptodate(struct extent
  int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
  u32 btrfs_csum_data(const char *data, u32 seed, size_t len);
  void btrfs_csum_final(u32 crc, u8 *result);
 -int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
 +blk_status_t btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
  			enum btrfs_wq_endio_type metadata);
- blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info,
- 		struct inode *inode, struct bio *bio, int mirror_num,
- 		unsigned long bio_flags, u64 bio_offset,
- 		extent_submit_bio_hook_t *submit_bio_start,
- 		extent_submit_bio_hook_t *submit_bio_done);
 -int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
++blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ 			int mirror_num, unsigned long bio_flags,
+ 			u64 bio_offset, void *private_data,
+ 			extent_submit_bio_hook_t *submit_bio_start,
+ 			extent_submit_bio_hook_t *submit_bio_done);
  unsigned long btrfs_async_submit_limit(struct btrfs_fs_info *info);
  int btrfs_write_tree_block(struct extent_buffer *buf);
- int btrfs_wait_tree_block_writeback(struct extent_buffer *buf);
+ void btrfs_wait_tree_block_writeback(struct extent_buffer *buf);
  int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
  			     struct btrfs_fs_info *fs_info);
  int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
diff --cc fs/btrfs/extent_io.c
index d1cd60140817,2e6f69908303..7a18b5762ac9
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@@ -2398,9 -2369,9 +2370,10 @@@ static int bio_readpage_error(struct bi
  	struct io_failure_record *failrec;
  	struct inode *inode = page->mapping->host;
  	struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+ 	struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
  	struct bio *bio;
  	int read_mode = 0;
 +	blk_status_t status;
  	int ret;
  
  	BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
@@@ -2433,12 -2404,11 +2406,12 @@@
  		"Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d",
  		read_mode, failrec->this_mirror, failrec->in_validation);
  
- 	status = tree->ops->submit_bio_hook(inode, bio, failrec->this_mirror,
 -	ret = tree->ops->submit_bio_hook(tree->private_data, bio, failrec->this_mirror,
++	status = tree->ops->submit_bio_hook(tree->private_data, bio, failrec->this_mirror,
  					 failrec->bio_flags, 0);
 -	if (ret) {
 +	if (status) {
- 		free_io_failure(BTRFS_I(inode), failrec);
+ 		free_io_failure(failure_tree, tree, failrec);
  		bio_put(bio);
 +		ret = blk_status_to_errno(status);
  	}
  
  	return ret;
@@@ -2540,9 -2509,9 +2513,9 @@@ endio_readpage_release_extent(struct ex
  static void end_bio_extent_readpage(struct bio *bio)
  {
  	struct bio_vec *bvec;
 -	int uptodate = !bio->bi_error;
 +	int uptodate = !bio->bi_status;
  	struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
- 	struct extent_io_tree *tree;
+ 	struct extent_io_tree *tree, *failure_tree;
  	u64 offset = 0;
  	u64 start;
  	u64 end;
@@@ -2560,9 -2529,10 +2533,10 @@@
  
  		btrfs_debug(fs_info,
  			"end_bio_extent_readpage: bi_sector=%llu, err=%d, mirror=%u",
 -			(u64)bio->bi_iter.bi_sector, bio->bi_error,
 +			(u64)bio->bi_iter.bi_sector, bio->bi_status,
  			io_bio->mirror_num);
  		tree = &BTRFS_I(inode)->io_tree;
+ 		failure_tree = &BTRFS_I(inode)->io_failure_tree;
  
  		/* We always issue full-page reads, but if some block
  		 * in a page fails to read, blk_update_request() will
diff --cc fs/btrfs/extent_io.h
index 487ca0207cb6,aeafdb35d90b..d4942d94a16b
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@@ -92,9 -92,9 +92,9 @@@ struct btrfs_inode
  struct btrfs_io_bio;
  struct io_failure_record;
  
- typedef	blk_status_t (extent_submit_bio_hook_t)(struct inode *inode,
 -typedef	int (extent_submit_bio_hook_t)(void *private_data, struct bio *bio,
 -				       int mirror_num, unsigned long bio_flags,
 -				       u64 bio_offset);
++typedef	blk_status_t (extent_submit_bio_hook_t)(void *private_data,
 +		struct bio *bio, int mirror_num, unsigned long bio_flags,
 +		u64 bio_offset);
  struct extent_io_ops {
  	/*
  	 * The following callbacks must be allways defined, the function
diff --cc fs/btrfs/inode.c
index 556c93060606,5d3c6ac960fd..8d050314591c
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@@ -1900,11 -1900,12 +1899,12 @@@ int btrfs_merge_bio_hook(struct page *p
   * At IO completion time the cums attached on the ordered extent record
   * are inserted into the btree
   */
- static blk_status_t __btrfs_submit_bio_start(struct inode *inode,
- 		struct bio *bio, int mirror_num, unsigned long bio_flags,
- 		u64 bio_offset)
 -static int __btrfs_submit_bio_start(void *private_data, struct bio *bio,
++static blk_status_t __btrfs_submit_bio_start(void *private_data, struct bio *bio,
+ 				    int mirror_num, unsigned long bio_flags,
+ 				    u64 bio_offset)
  {
+ 	struct inode *inode = private_data;
 -	int ret = 0;
 +	blk_status_t ret = 0;
  
  	ret = btrfs_csum_one_bio(inode, bio, 0, 0);
  	BUG_ON(ret); /* -ENOMEM */
@@@ -1919,12 -1920,13 +1919,13 @@@
   * At IO completion time the cums attached on the ordered extent record
   * are inserted into the btree
   */
- static blk_status_t __btrfs_submit_bio_done(struct inode *inode,
- 		struct bio *bio, int mirror_num, unsigned long bio_flags,
- 		u64 bio_offset)
 -static int __btrfs_submit_bio_done(void *private_data, struct bio *bio,
++static blk_status_t __btrfs_submit_bio_done(void *private_data, struct bio *bio,
+ 			  int mirror_num, unsigned long bio_flags,
+ 			  u64 bio_offset)
  {
+ 	struct inode *inode = private_data;
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 -	int ret;
 +	blk_status_t ret;
  
  	ret = btrfs_map_bio(fs_info, bio, mirror_num, 1);
  	if (ret) {
@@@ -1938,10 -1940,11 +1939,11 @@@
   * extent_io.c submission hook. This does the right thing for csum calculation
   * on write, or reading the csums from the tree before a read
   */
- static blk_status_t btrfs_submit_bio_hook(struct inode *inode, struct bio *bio,
- 			  int mirror_num, unsigned long bio_flags,
- 			  u64 bio_offset)
 -static int btrfs_submit_bio_hook(void *private_data, struct bio *bio,
++static blk_status_t btrfs_submit_bio_hook(void *private_data, struct bio *bio,
+ 				 int mirror_num, unsigned long bio_flags,
+ 				 u64 bio_offset)
  {
+ 	struct inode *inode = private_data;
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	enum btrfs_wq_endio_type metadata = BTRFS_WQ_ENDIO_DATA;
@@@ -8033,10 -8046,12 +8045,12 @@@ struct btrfs_retry_complete 
  static void btrfs_retry_endio_nocsum(struct bio *bio)
  {
  	struct btrfs_retry_complete *done = bio->bi_private;
+ 	struct inode *inode = done->inode;
  	struct bio_vec *bvec;
+ 	struct extent_io_tree *io_tree, *failure_tree;
  	int i;
  
 -	if (bio->bi_error)
 +	if (bio->bi_status)
  		goto end;
  
  	ASSERT(bio->bi_vcnt == 1);
@@@ -8140,11 -8171,12 +8170,12 @@@ end
  	bio_put(bio);
  }
  
 -static int __btrfs_subio_endio_read(struct inode *inode,
 -				    struct btrfs_io_bio *io_bio, int err)
 +static blk_status_t __btrfs_subio_endio_read(struct inode *inode,
 +		struct btrfs_io_bio *io_bio, blk_status_t err)
  {
  	struct btrfs_fs_info *fs_info;
- 	struct bio_vec *bvec;
+ 	struct bio_vec bvec;
+ 	struct bvec_iter iter;
  	struct btrfs_retry_complete done;
  	u64 start;
  	u64 offset = 0;
@@@ -8231,10 -8265,13 +8264,13 @@@ static void btrfs_endio_direct_read(str
  	struct inode *inode = dip->inode;
  	struct bio *dio_bio;
  	struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
 -	int err = bio->bi_error;
 +	blk_status_t err = bio->bi_status;
  
- 	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
+ 	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) {
  		err = btrfs_subio_endio_read(inode, io_bio, err);
+ 		if (!err)
 -			bio->bi_error = 0;
++			bio->bi_status = 0;
+ 	}
  
  	unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
  		      dip->logical_offset + dip->bytes - 1);
@@@ -8307,11 -8344,12 +8343,12 @@@ static void btrfs_endio_direct_write(st
  	bio_put(bio);
  }
  
- static blk_status_t __btrfs_submit_bio_start_direct_io(struct inode *inode,
 -static int __btrfs_submit_bio_start_direct_io(void *private_data,
++static blk_status_t __btrfs_submit_bio_start_direct_io(void *private_data,
  				    struct bio *bio, int mirror_num,
  				    unsigned long bio_flags, u64 offset)
  {
+ 	struct inode *inode = private_data;
 -	int ret;
 +	blk_status_t ret;
  	ret = btrfs_csum_one_bio(inode, bio, offset, 1);
  	BUG_ON(ret); /* -ENOMEM */
  	return 0;
@@@ -8357,17 -8395,7 +8394,7 @@@ out
  	bio_put(bio);
  }
  
- static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
- 				       u64 first_sector, gfp_t gfp_flags)
- {
- 	struct bio *bio;
- 	bio = btrfs_bio_alloc(bdev, first_sector, BIO_MAX_PAGES, gfp_flags);
- 	if (bio)
- 		bio_associate_current(bio);
- 	return bio;
- }
- 
 -static inline int btrfs_lookup_and_bind_dio_csum(struct inode *inode,
 +static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode,
  						 struct btrfs_dio_private *dip,
  						 struct bio *bio,
  						 u64 file_offset)
@@@ -8672,10 -8675,10 +8674,10 @@@ free_ordered
  		 * Releases and cleans up our dio_bio, no need to bio_put()
  		 * nor bio_endio()/bio_io_error() against dio_bio.
  		 */
 -		dio_end_io(dio_bio, ret);
 +		dio_end_io(dio_bio);
  	}
- 	if (io_bio)
- 		bio_put(io_bio);
+ 	if (bio)
+ 		bio_put(bio);
  	kfree(dip);
  }
  
@@@ -8754,11 -8758,9 +8757,12 @@@ static ssize_t btrfs_direct_IO(struct k
  			dio_data.overwrite = 1;
  			inode_unlock(inode);
  			relock = true;
 +		} else if (iocb->ki_flags & IOCB_NOWAIT) {
 +			ret = -EAGAIN;
 +			goto out;
  		}
- 		ret = btrfs_delalloc_reserve_space(inode, offset, count);
+ 		ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
+ 						   offset, count);
  		if (ret)
  			goto out;
  		dio_data.outstanding_extents = count_max_extents(count);

-- 
Cheers,
Stephen Rothwell

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ