diff options
| author | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
| commit | bb272221e9db79f13d454e1f3fb6b05013be985e (patch) | |
| tree | 36f4acc50e3fabac71fadd34c720c0a6011db470 /include/linux/bvec.h | |
| parent | 253fd51e2f533552ae35a0c661705da6c4842c1b (diff) | |
| parent | 5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff) | |
Merge tag 'v4.13-rc1' into fixes
The fixes branch is based off a random pre-rc1 commit, because we had
some fixes that needed to go in before rc1 was released.
However we now need to fix some code that went in after that point, but
before rc1, so merge rc1 to get that code into fixes so we can fix it!
Diffstat (limited to 'include/linux/bvec.h')
| -rw-r--r-- | include/linux/bvec.h | 41 | 
1 files changed, 36 insertions, 5 deletions
diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 89b65b82d98f..ec8a4d7af6bd 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -22,6 +22,7 @@  #include <linux/kernel.h>  #include <linux/bug.h> +#include <linux/errno.h>  /*   * was unsigned short, but we might as well be ready for > 64kB I/O pages @@ -39,6 +40,8 @@ struct bvec_iter {  	unsigned int		bi_idx;		/* current index into bvl_vec */ +	unsigned int            bi_done;	/* number of bytes completed */ +  	unsigned int            bi_bvec_done;	/* number of bytes completed in  						   current bvec */  }; @@ -66,12 +69,14 @@ struct bvec_iter {  	.bv_offset	= bvec_iter_offset((bvec), (iter)),	\  }) -static inline void bvec_iter_advance(const struct bio_vec *bv, -				     struct bvec_iter *iter, -				     unsigned bytes) +static inline bool bvec_iter_advance(const struct bio_vec *bv, +		struct bvec_iter *iter, unsigned bytes)  { -	WARN_ONCE(bytes > iter->bi_size, -		  "Attempted to advance past end of bvec iter\n"); +	if (WARN_ONCE(bytes > iter->bi_size, +		     "Attempted to advance past end of bvec iter\n")) { +		iter->bi_size = 0; +		return false; +	}  	while (bytes) {  		unsigned iter_len = bvec_iter_len(bv, *iter); @@ -80,12 +85,38 @@ static inline void bvec_iter_advance(const struct bio_vec *bv,  		bytes -= len;  		iter->bi_size -= len;  		iter->bi_bvec_done += len; +		iter->bi_done += len;  		if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {  			iter->bi_bvec_done = 0;  			iter->bi_idx++;  		}  	} +	return true; +} + +static inline bool bvec_iter_rewind(const struct bio_vec *bv, +				     struct bvec_iter *iter, +				     unsigned int bytes) +{ +	while (bytes) { +		unsigned len = min(bytes, iter->bi_bvec_done); + +		if (iter->bi_bvec_done == 0) { +			if (WARN_ONCE(iter->bi_idx == 0, +				      "Attempted to rewind iter beyond " +				      "bvec's boundaries\n")) { +				return false; +			} +			iter->bi_idx--; +			iter->bi_bvec_done = __bvec_iter_bvec(bv, *iter)->bv_len; +			continue; +		} +		bytes -= len; +		iter->bi_size += len; +		iter->bi_bvec_done -= len; +	} +	return true;  }  #define for_each_bvec(bvl, bio_vec, iter, start)			\  | 
