mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2026-10-13 17:00 Mark Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Brown @ 2026-10-13 17:00 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, David Howells, Linux Kernel Mailing List,
	Linux Next Mailing List, Pavel Begunkov

[-- Attachment #1: Type: text/plain, Size: 23302 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  lib/iov_iter.c

between commit:

  58194689921d8 ("iov_iter: Remove ITER_FOLIOQ")

from the vfs-brauner tree and commit:

  f41f84796a112 ("iov_iter: add iterator type for dmabuf maps")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --combined lib/iov_iter.c
index 72cef6a79c3eb,6831a5d9396e1..0000000000000
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@@ -538,45 -538,45 +538,46 @@@ static void iov_iter_iovec_advance(stru
  	i->__iov = iov;
  }
  
 -static void iov_iter_folioq_advance(struct iov_iter *i, size_t size)
 +static void iov_iter_bvecq_advance(struct iov_iter *i, size_t by)
  {
 -	const struct folio_queue *folioq = i->folioq;
 -	unsigned int slot = i->folioq_slot;
 +	const struct bvecq *bq = i->bvecq;
 +	unsigned int slot = i->bvecq_slot;
  
  	if (!i->count)
  		return;
 -	i->count -= size;
 +	i->count -= by;
  
 -	if (slot >= folioq_nr_slots(folioq)) {
 -		folioq = folioq->next;
 -		slot = 0;
 -	}
 -
 -	size += i->iov_offset; /* From beginning of current segment. */
 +	by += i->iov_offset; /* From beginning of current segment. */
  	do {
 -		size_t fsize = folioq_folio_size(folioq, slot);
 +		size_t len;
  
 -		if (likely(size < fsize))
 -			break;
 -		size -= fsize;
 -		slot++;
 -		if (slot >= folioq_nr_slots(folioq) && folioq->next) {
 -			folioq = folioq->next;
 +		if (slot >= bq->nr_slots) {
 +			if (!bq->next)
 +				break;
 +			bq = bq->next;
  			slot = 0;
 +			continue;
  		}
 -	} while (size);
  
 -	i->iov_offset = size;
 -	i->folioq_slot = slot;
 -	i->folioq = folioq;
 +		len = bq->bv[slot].bv_len;
 +
 +		if (likely(by < len))
 +			break;
 +		by -= len;
 +		slot++;
 +	} while (by);
 +
 +	i->iov_offset = by;
 +	i->bvecq_slot = slot;
 +	i->bvecq = bq;
  }
  
  void iov_iter_advance(struct iov_iter *i, size_t size)
  {
  	if (unlikely(i->count < size))
  		size = i->count;
- 	if (likely(iter_is_ubuf(i)) || unlikely(iov_iter_is_xarray(i))) {
+ 	if (likely(iter_is_ubuf(i)) || unlikely(iov_iter_is_xarray(i)) ||
+ 	    unlikely(iov_iter_is_dmabuf_map(i))) {
  		i->iov_offset += size;
  		i->count -= size;
  	} else if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i))) {
@@@ -584,39 -584,38 +585,39 @@@
  		iov_iter_iovec_advance(i, size);
  	} else if (iov_iter_is_bvec(i)) {
  		iov_iter_bvec_advance(i, size);
 -	} else if (iov_iter_is_folioq(i)) {
 -		iov_iter_folioq_advance(i, size);
 +	} else if (iov_iter_is_bvecq(i)) {
 +		iov_iter_bvecq_advance(i, size);
  	} else if (iov_iter_is_discard(i)) {
  		i->count -= size;
  	}
  }
  EXPORT_SYMBOL(iov_iter_advance);
  
 -static void iov_iter_folioq_revert(struct iov_iter *i, size_t unroll)
 +static void iov_iter_bvecq_revert(struct iov_iter *i, size_t unroll)
  {
 -	const struct folio_queue *folioq = i->folioq;
 -	unsigned int slot = i->folioq_slot;
 +	const struct bvecq *bq = i->bvecq;
 +	unsigned int slot = i->bvecq_slot;
  
  	for (;;) {
 -		size_t fsize;
 +		size_t len;
  
  		if (slot == 0) {
 -			folioq = folioq->prev;
 -			slot = folioq_nr_slots(folioq);
 +			bq = bq->prev;
 +			slot = bq->nr_slots;
 +			continue;
  		}
  		slot--;
  
 -		fsize = folioq_folio_size(folioq, slot);
 -		if (unroll <= fsize) {
 -			i->iov_offset = fsize - unroll;
 +		len = bq->bv[slot].bv_len;
 +		if (unroll <= len) {
 +			i->iov_offset = len - unroll;
  			break;
  		}
 -		unroll -= fsize;
 +		unroll -= len;
  	}
  
 -	i->folioq_slot = slot;
 -	i->folioq = folioq;
 +	i->bvecq_slot = slot;
 +	i->bvecq = bq;
  }
  
  void iov_iter_revert(struct iov_iter *i, size_t unroll)
@@@ -633,7 -632,8 +634,8 @@@
  		return;
  	}
  	unroll -= i->iov_offset;
- 	if (iov_iter_is_xarray(i) || iter_is_ubuf(i)) {
+ 	if (iov_iter_is_xarray(i) || iter_is_ubuf(i) ||
+ 	    iov_iter_is_dmabuf_map(i)) {
  		BUG(); /* We should never go beyond the start of the specified
  			* range since we might then be straying into pages that
  			* aren't pinned.
@@@ -650,9 -650,9 +652,9 @@@
  			}
  			unroll -= n;
  		}
 -	} else if (iov_iter_is_folioq(i)) {
 +	} else if (iov_iter_is_bvecq(i)) {
  		i->iov_offset = 0;
 -		iov_iter_folioq_revert(i, unroll);
 +		iov_iter_bvecq_revert(i, unroll);
  	} else { /* same logics for iovec and kvec */
  		const struct iovec *iov = iter_iov(i);
  		while (1) {
@@@ -680,28 -680,9 +682,28 @@@ size_t iov_iter_single_seg_count(const 
  		if (iov_iter_is_bvec(i))
  			return min(i->count, i->bvec->bv_len - i->iov_offset);
  	}
 -	if (unlikely(iov_iter_is_folioq(i)))
 -		return !i->count ? 0 :
 -			umin(folioq_folio_size(i->folioq, i->folioq_slot), i->count);
 +	if (!i->count)
 +		return 0;
 +	if (unlikely(iov_iter_is_bvecq(i))) {
 +		const struct bvecq *bq = i->bvecq;
 +		unsigned int slot = i->bvecq_slot;
 +		size_t offset = i->iov_offset;
 +
 +		for (;;) {
 +			while (slot >= bq->nr_slots) {
 +				bq = bq->next;
 +				if (!bq)
 +					return 0;
 +				slot = 0;
 +				offset = 0;
 +			}
 +			if (bq->bv[slot].bv_len > offset)
 +				break;
 +			slot++;
 +			offset = 0;
 +		}
 +		return min(i->count, bq->bv[slot].bv_len - offset);
 +	}
  	return i->count;
  }
  EXPORT_SYMBOL(iov_iter_single_seg_count);
@@@ -739,33 -720,34 +741,33 @@@ void iov_iter_bvec(struct iov_iter *i, 
  EXPORT_SYMBOL(iov_iter_bvec);
  
  /**
 - * iov_iter_folio_queue - Initialise an I/O iterator to use the folios in a folio queue
 + * iov_iter_bvec_queue - Initialise an I/O iterator to use a segmented bvec queue
   * @i: The iterator to initialise.
   * @direction: The direction of the transfer.
 - * @folioq: The starting point in the folio queue.
 - * @first_slot: The first slot in the folio queue to use
 - * @offset: The offset into the folio in the first slot to start at
 + * @bvecq: The starting point in the bvec queue.
 + * @first_slot: The first slot in the bvec queue to use
 + * @offset: The offset into the bvec in the first slot to start at
   * @count: The size of the I/O buffer in bytes.
   *
 - * Set up an I/O iterator to either draw data out of the pages attached to an
 - * inode or to inject data into those pages.  The pages *must* be prevented
 - * from evaporation, either by taking a ref on them or locking them by the
 - * caller.
 + * Set up an I/O iterator to either draw data out of the buffers attached to an
 + * inode or to inject data into those buffers.  The pages *must* be prevented
 + * from evaporation, either by the caller.
   */
 -void iov_iter_folio_queue(struct iov_iter *i, unsigned int direction,
 -			  const struct folio_queue *folioq, unsigned int first_slot,
 -			  unsigned int offset, size_t count)
 +void iov_iter_bvec_queue(struct iov_iter *i, unsigned int direction,
 +			 const struct bvecq *bvecq, unsigned int first_slot,
 +			 unsigned int offset, size_t count)
  {
 -	BUG_ON(direction & ~1);
 +	WARN_ON(direction & ~(READ | WRITE));
  	*i = (struct iov_iter) {
 -		.iter_type = ITER_FOLIOQ,
 -		.data_source = direction,
 -		.folioq = folioq,
 -		.folioq_slot = first_slot,
 -		.count = count,
 -		.iov_offset = offset,
 +		.iter_type	= ITER_BVECQ,
 +		.data_source	= direction,
 +		.bvecq		= bvecq,
 +		.bvecq_slot	= first_slot,
 +		.count		= count,
 +		.iov_offset	= offset,
  	};
  }
 -EXPORT_SYMBOL(iov_iter_folio_queue);
 +EXPORT_SYMBOL(iov_iter_bvec_queue);
  
  /**
   * iov_iter_xarray - Initialise an I/O iterator to use the pages in an xarray
@@@ -795,6 -777,20 +797,20 @@@ void iov_iter_xarray(struct iov_iter *i
  }
  EXPORT_SYMBOL(iov_iter_xarray);
  
+ void iov_iter_dmabuf_map(struct iov_iter *i, unsigned int direction,
+ 			 struct dma_buf_io_map *map,
+ 			 loff_t off, size_t count)
+ {
+ 	WARN_ON(direction & ~(READ | WRITE));
+ 	*i = (struct iov_iter){
+ 		.iter_type = ITER_DMABUF_MAP,
+ 		.data_source = direction,
+ 		.dmabuf_map = map,
+ 		.count = count,
+ 		.iov_offset = off,
+ 	};
+ }
+ 
  /**
   * iov_iter_discard - Initialise an I/O iterator that discards data
   * @i: The iterator to initialise.
@@@ -859,39 -855,6 +875,39 @@@ static unsigned long iov_iter_alignment
  	return res;
  }
  
 +static unsigned long iov_iter_alignment_bvecq(const struct iov_iter *iter)
 +{
 +	const struct bvecq *bq;
 +	unsigned long res = 0;
 +	unsigned int slot = iter->bvecq_slot;
 +	size_t skip = iter->iov_offset;
 +	size_t size = iter->count;
 +
 +	if (!size)
 +		return res;
 +
 +	for (bq = iter->bvecq; bq; bq = bq->next) {
 +		for (; slot < bq->nr_slots; slot++) {
 +			const struct bio_vec *bvec = &bq->bv[slot];
 +			size_t part = min(bvec->bv_len - skip, size);
 +
 +			if (part) {
 +				res |= bvec->bv_offset + skip;
 +				res |= part;
 +			}
 +
 +			size -= part;
 +			if (size == 0)
 +				return res;
 +			skip = 0;
 +		}
 +
 +		slot = 0;
 +	}
 +
 +	return res;
 +}
 +
  unsigned long iov_iter_alignment(const struct iov_iter *i)
  {
  	if (likely(iter_is_ubuf(i))) {
@@@ -907,10 -870,10 +923,10 @@@
  
  	if (iov_iter_is_bvec(i))
  		return iov_iter_alignment_bvec(i);
 +	if (iov_iter_is_bvecq(i))
 +		return iov_iter_alignment_bvecq(i);
  
 -	/* With both xarray and folioq types, we're dealing with whole folios. */
 -	if (iov_iter_is_folioq(i) || iov_iter_is_dmabuf_map(i))
 -		return i->iov_offset | i->count;
 +	/* With the xarray type, we're dealing with whole folios. */
  	if (iov_iter_is_xarray(i))
  		return (i->xarray_start + i->iov_offset) | i->count;
  
@@@ -925,7 -888,7 +941,7 @@@ unsigned long iov_iter_gap_alignment(co
  	size_t size = i->count;
  	unsigned k;
  
- 	if (iter_is_ubuf(i))
+ 	if (iter_is_ubuf(i) || iov_iter_is_dmabuf_map(i))
  		return 0;
  
  	if (WARN_ON(!iter_is_iovec(i)))
@@@ -963,158 -926,62 +979,158 @@@ static int want_pages_array(struct pag
  	return count;
  }
  
 -static ssize_t iter_folioq_get_pages(struct iov_iter *iter,
 -				     struct page ***ppages, size_t maxsize,
 -				     unsigned maxpages, size_t *_start_offset)
 +/*
 + * Count the number of virtually contiguous pages coming up next in an
 + * ITER_BVECQ iterator, up to the specified maxima.
 + */
 +static unsigned int iter_count_bvecq_pages(const struct iov_iter *iter,
 +					   size_t maxsize,
 +					   unsigned int maxpages)
  {
 -	const struct folio_queue *folioq = iter->folioq;
 -	struct page **pages;
 -	unsigned int slot = iter->folioq_slot;
 -	size_t extracted = 0, count = iter->count, iov_offset = iter->iov_offset;
 +	const struct bvecq *bvecq = iter->bvecq;
 +	unsigned int slot = iter->bvecq_slot;
 +	ssize_t remain = umin(maxsize, iter->count);
 +	size_t count = 0, offset = iter->iov_offset;
  
 -	if (slot >= folioq_nr_slots(folioq)) {
 -		folioq = folioq->next;
 -		slot = 0;
 -		if (WARN_ON(iov_offset != 0))
 -			return -EIO;
 -	}
 +	do {
 +		const struct bio_vec *bv;
 +		size_t boff, blen;
  
 -	maxpages = want_pages_array(ppages, maxsize, iov_offset & ~PAGE_MASK, maxpages);
 -	if (!maxpages)
 -		return -ENOMEM;
 -	*_start_offset = iov_offset & ~PAGE_MASK;
 -	pages = *ppages;
 -
 -	for (;;) {
 -		struct folio *folio = folioq_folio(folioq, slot);
 -		size_t offset = iov_offset, fsize = folioq_folio_size(folioq, slot);
 -		size_t part = PAGE_SIZE - offset % PAGE_SIZE;
 -
 -		if (offset < fsize) {
 -			part = umin(part, umin(maxsize - extracted, fsize - offset));
 -			count -= part;
 -			iov_offset += part;
 -			extracted += part;
 -
 -			*pages = folio_page(folio, offset / PAGE_SIZE);
 -			get_page(*pages);
 -			pages++;
 -			maxpages--;
 +		if (slot >= bvecq->nr_slots) {
 +			if (!bvecq->next) {
 +				WARN_ON_ONCE(remain > 0);
 +				break;
 +			}
 +			bvecq = bvecq->next;
 +			slot = 0;
 +			offset = 0;
 +			continue;
  		}
  
 -		if (maxpages == 0 || extracted >= maxsize)
 +		bv = &bvecq->bv[slot++];
 +		boff = bv->bv_offset;
 +		blen = bv->bv_len;
 +
 +		/* bv_page is not allowed to be NULL unless bv_len == 0. */
 +		if (WARN_ON_ONCE(!bv->bv_page && blen > 0))
 +			break;
 +		if (!PAGE_ALIGNED(boff) && count > 0)
  			break;
  
 -		if (iov_offset >= fsize) {
 -			iov_offset = 0;
 -			slot++;
 -			if (slot == folioq_nr_slots(folioq) && folioq->next) {
 -				folioq = folioq->next;
 -				slot = 0;
 -			}
 +		boff += offset;
 +		blen -= offset;
 +		offset = 0;
 +		if (!blen)
 +			continue;
 +
 +		blen = umin(blen, remain);
 +		remain -= blen;
 +		blen += offset_in_page(boff);
 +		count += DIV_ROUND_UP(blen, PAGE_SIZE);
 +
 +		if (!PAGE_ALIGNED(blen))
 +			break;
 +	} while (remain > 0 && count < maxpages);
 +
 +	return min(count, maxpages);
 +}
 +
 +/*
 + * Get a list of virtually contiguous pages from an ITER_BVECQ iterator and pin
 + * them.
 + */
 +static ssize_t iter_bvecq_get_pages(struct iov_iter *iter,
 +				    struct page ***ppages, size_t maxsize,
 +				    unsigned int maxpages, size_t *_start_offset)
 +{
 +	const struct bvecq *bvecq = iter->bvecq;
 +	struct page **pages;
 +	unsigned int slot = iter->bvecq_slot, nr = 0;
 +	size_t extracted = 0, offset = iter->iov_offset;
 +
 +	for (;;) {
 +		if (slot >= bvecq->nr_slots) {
 +			if (!bvecq->next)
 +				return 0;
 +			bvecq = bvecq->next;
 +			slot = 0;
 +			offset = 0;
 +			continue;
  		}
 +		if (offset >= bvecq->bv[slot].bv_len) {
 +			slot++;
 +			offset = 0;
 +			continue;
 +		}
 +		break;
  	}
  
 -	iter->count = count;
 -	iter->iov_offset = iov_offset;
 -	iter->folioq = folioq;
 -	iter->folioq_slot = slot;
 +	/* Count the next run of virtually contiguous pages. */
 +	maxpages = iter_count_bvecq_pages(iter, maxsize, maxpages);
 +	if (!maxpages)
 +		return 0;
 +
 +	maxpages = want_pages_array(ppages, maxsize,
 +				    (bvecq->bv[slot].bv_offset + offset) & ~PAGE_MASK,
 +				    maxpages);
 +	if (!maxpages)
 +		return -ENOMEM;
 +	pages = *ppages;
 +
 +	/* Now transcribe the page pointers. */
 +	do {
 +		const struct bio_vec *bv;
 +		size_t boff, blen;
 +
 +		if (slot >= bvecq->nr_slots) {
 +			if (!bvecq->next) {
 +				WARN_ON_ONCE(extracted < iter->count);
 +				break;
 +			}
 +			bvecq = bvecq->next;
 +			slot = 0;
 +			offset = 0;
 +			continue;
 +		}
 +
 +		bv = &bvecq->bv[slot];
 +		boff = bv->bv_offset;
 +		blen = bv->bv_len;
 +
 +		/* bv_page is not allowed to be NULL unless bv_len == 0. */
 +
 +		if (offset < blen) {
 +			struct folio *folio;
 +			size_t poff = (boff + offset) % PAGE_SIZE;
 +			size_t part = min(maxsize - extracted, blen - offset);
 +			size_t pix = (boff + offset) / PAGE_SIZE;
 +
 +			if (poff + part > PAGE_SIZE)
 +				part = PAGE_SIZE - poff;
 +
 +			if (!extracted)
 +				*_start_offset = poff;
 +
 +			/* Get a ref on the page if it's not a slab page. */
 +			folio = page_folio(bv->bv_page + pix);
 +			if (!folio_test_slab(folio))
 +				folio_get(folio);
 +
 +			pages[nr++] = bv->bv_page + pix;
 +			offset += part;
 +			extracted += part;
 +		}
 +
 +		if (offset >= blen) {
 +			offset = 0;
 +			slot++;
 +		}
 +	} while (nr < maxpages && extracted < maxsize);
 +
 +	iter->bvecq = bvecq;
 +	iter->bvecq_slot = slot;
 +	iter->iov_offset = offset;
 +	iter->count -= extracted;
  	return extracted;
  }
  
@@@ -1269,8 -1136,8 +1285,8 @@@ static ssize_t __iov_iter_get_pages_all
  		}
  		return maxsize;
  	}
 -	if (iov_iter_is_folioq(i))
 -		return iter_folioq_get_pages(i, pages, maxsize, maxpages, start);
 +	if (iov_iter_is_bvecq(i))
 +		return iter_bvecq_get_pages(i, pages, maxsize, maxpages, start);
  	if (iov_iter_is_xarray(i))
  		return iter_xarray_get_pages(i, pages, maxsize, maxpages, start);
  	return -EFAULT;
@@@ -1341,38 -1208,6 +1357,38 @@@ static int bvec_npages(const struct iov
  	return npages;
  }
  
 +static size_t iov_npages_bvecq(const struct iov_iter *iter, size_t maxpages)
 +{
 +	const struct bvecq *bq;
 +	unsigned int slot = iter->bvecq_slot;
 +	size_t npages = 0;
 +	size_t skip = iter->iov_offset;
 +	size_t size = iter->count;
 +
 +	for (bq = iter->bvecq; bq; bq = bq->next) {
 +		for (; slot < bq->nr_slots; slot++) {
 +			const struct bio_vec *bvec = &bq->bv[slot];
 +			size_t offs = (bvec->bv_offset + skip) % PAGE_SIZE;
 +			size_t part = min(bvec->bv_len - skip, size);
 +
 +			if (part) {
 +				npages += DIV_ROUND_UP(offs + part, PAGE_SIZE);
 +				if (npages >= maxpages)
 +					goto out;
 +			}
 +
 +			size -= part;
 +			if (!size)
 +				goto out;
 +			skip = 0;
 +		}
 +
 +		slot = 0;
 +	}
 +out:
 +	return umin(npages, maxpages);
 +}
 +
  int iov_iter_npages(const struct iov_iter *i, int maxpages)
  {
  	if (unlikely(!i->count))
@@@ -1387,8 -1222,11 +1403,8 @@@
  		return iov_npages(i, maxpages);
  	if (iov_iter_is_bvec(i))
  		return bvec_npages(i, maxpages);
 -	if (iov_iter_is_folioq(i)) {
 -		unsigned offset = i->iov_offset % PAGE_SIZE;
 -		int npages = DIV_ROUND_UP(offset + i->count, PAGE_SIZE);
 -		return min(npages, maxpages);
 -	}
 +	if (iov_iter_is_bvecq(i))
 +		return iov_npages_bvecq(i, maxpages);
  	if (iov_iter_is_xarray(i)) {
  		unsigned offset = (i->xarray_start + i->iov_offset) % PAGE_SIZE;
  		int npages = DIV_ROUND_UP(offset + i->count, PAGE_SIZE);
@@@ -1647,11 -1485,12 +1663,12 @@@ EXPORT_SYMBOL_GPL(import_ubuf)
  void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
  {
  	if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i) &&
- 			 !iter_is_ubuf(i)) && !iov_iter_is_kvec(i))
+ 			 !iter_is_ubuf(i) && !iov_iter_is_kvec(i) &&
+ 			 !iov_iter_is_dmabuf_map(i)))
  		return;
  	i->iov_offset = state->iov_offset;
  	i->count = state->count;
- 	if (iter_is_ubuf(i))
+ 	if (iter_is_ubuf(i) || iov_iter_is_dmabuf_map(i))
  		return;
  	/*
  	 * For the *vec iters, nr_segs + iov is constant - if we increment
@@@ -1672,86 -1511,64 +1689,86 @@@
  EXPORT_SYMBOL_FOR_MODULES(iov_iter_restore, "vmw_vsock_virtio_transport_common");
  
  /*
 - * Extract a list of contiguous pages from an ITER_FOLIOQ iterator.  This does
 - * not get references on the pages, nor does it get a pin on them.
 + * Extract a list of virtually contiguous pages from an ITER_BVECQ iterator.
 + * This does not get references on the pages, nor does it get a pin on them.
   */
 -static ssize_t iov_iter_extract_folioq_pages(struct iov_iter *i,
 -					     struct page ***pages, size_t maxsize,
 -					     unsigned int maxpages,
 -					     iov_iter_extraction_t extraction_flags,
 -					     size_t *offset0)
 +static ssize_t iov_iter_extract_bvecq_pages(struct iov_iter *iter,
 +					    struct page ***pages, size_t maxsize,
 +					    unsigned int maxpages,
 +					    iov_iter_extraction_t extraction_flags,
 +					    size_t *offset0)
  {
 -	const struct folio_queue *folioq = i->folioq;
 +	const struct bvecq *bvecq;
  	struct page **p;
 -	unsigned int nr = 0;
 -	size_t extracted = 0, offset, slot = i->folioq_slot;
 +	unsigned int slot, nr = 0;
 +	size_t extracted = 0, offset;
  
 -	if (slot >= folioq_nr_slots(folioq)) {
 -		folioq = folioq->next;
 -		slot = 0;
 -		if (WARN_ON(i->iov_offset != 0))
 -			return -EIO;
 +	/* Count the next run of virtually contiguous pages. */
 +	maxpages = iter_count_bvecq_pages(iter, maxsize, maxpages);
 +	if (!maxpages)
 +		return 0;
 +
 +	if (!*pages) {
 +		*pages = kvmalloc_array(maxpages, sizeof(struct page *), GFP_KERNEL);
 +		if (!*pages)
 +			return -ENOMEM;
  	}
  
 -	offset = i->iov_offset & ~PAGE_MASK;
 -	*offset0 = offset;
 -
 -	maxpages = want_pages_array(pages, maxsize, offset, maxpages);
 -	if (!maxpages)
 -		return -ENOMEM;
  	p = *pages;
  
 -	for (;;) {
 -		struct folio *folio = folioq_folio(folioq, slot);
 -		size_t offset = i->iov_offset, fsize = folioq_folio_size(folioq, slot);
 -		size_t part = PAGE_SIZE - offset % PAGE_SIZE;
 +	/* Now transcribe the page pointers. */
 +	extracted = 0;
 +	bvecq = iter->bvecq;
 +	offset = iter->iov_offset;
 +	slot = iter->bvecq_slot;
  
 -		if (offset < fsize) {
 -			part = umin(part, umin(maxsize - extracted, fsize - offset));
 -			i->count -= part;
 -			i->iov_offset += part;
 -			extracted += part;
 +	do {
 +		const struct bio_vec *bv;
 +		size_t boff, blen;
  
 -			p[nr++] = folio_page(folio, offset / PAGE_SIZE);
 -		}
 -
 -		if (nr >= maxpages || extracted >= maxsize)
 -			break;
 -
 -		if (i->iov_offset >= fsize) {
 -			i->iov_offset = 0;
 -			slot++;
 -			if (slot == folioq_nr_slots(folioq) && folioq->next) {
 -				folioq = folioq->next;
 -				slot = 0;
 +		if (slot >= bvecq->nr_slots) {
 +			if (!bvecq->next) {
 +				WARN_ON_ONCE(extracted < iter->count);
 +				break;
  			}
 +			bvecq = bvecq->next;
 +			slot = 0;
 +			offset = 0;
 +			continue;
  		}
 -	}
  
 -	i->folioq = folioq;
 -	i->folioq_slot = slot;
 +		bv = &bvecq->bv[slot];
 +		boff = bv->bv_offset;
 +		blen = bv->bv_len;
 +
 +		/* bv_page is not allowed to be NULL unless bv_len == 0. */
 +
 +		if (offset < blen) {
 +			size_t part = umin(maxsize - extracted, blen - offset);
 +			size_t poff = (boff + offset) % PAGE_SIZE;
 +			size_t pix = (boff + offset) / PAGE_SIZE;
 +
 +			if (poff + part > PAGE_SIZE)
 +				part = PAGE_SIZE - poff;
 +
 +			if (!extracted)
 +				*offset0 = poff;
 +
 +			p[nr++] = bv->bv_page + pix;
 +			offset += part;
 +			extracted += part;
 +		}
 +
 +		if (offset >= blen) {
 +			offset = 0;
 +			slot++;
 +		}
 +	} while (nr < maxpages && extracted < maxsize);
 +
 +	iter->bvecq = bvecq;
 +	iter->bvecq_slot = slot;
 +	iter->iov_offset = offset;
 +	iter->count -= extracted;
  	return extracted;
  }
  
@@@ -2017,8 -1834,8 +2034,8 @@@ static ssize_t iov_iter_extract_user_pa
   *      added to the pages, but refs will not be taken.
   *      iov_iter_extract_will_pin() will return true.
   *
 - *  (*) If the iterator is ITER_KVEC, ITER_BVEC, ITER_FOLIOQ or ITER_XARRAY, the
 - *      pages are merely listed; no extra refs or pins are obtained.
 + *  (*) If the iterator is ITER_KVEC, ITER_BVEC, ITER_XARRAY, the pages are
 + *      merely listed; no extra refs or pins are obtained.
   *      iov_iter_extract_will_pin() will return 0.
   *
   * Note also:
@@@ -2053,10 -1870,10 +2070,10 @@@ ssize_t iov_iter_extract_pages(struct i
  		return iov_iter_extract_bvec_pages(i, pages, maxsize,
  						   maxpages, extraction_flags,
  						   offset0);
 -	if (iov_iter_is_folioq(i))
 -		return iov_iter_extract_folioq_pages(i, pages, maxsize,
 -						     maxpages, extraction_flags,
 -						     offset0);
 +	if (iov_iter_is_bvecq(i))
 +		return iov_iter_extract_bvecq_pages(i, pages, maxsize,
 +						    maxpages, extraction_flags,
 +						    offset0);
  	if (iov_iter_is_xarray(i))
  		return iov_iter_extract_xarray_pages(i, pages, maxsize,
  						     maxpages, extraction_flags,

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2026-10-13 16:49 Mark Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Brown @ 2026-10-13 16:49 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, David Howells, Linux Kernel Mailing List,
	Linux Next Mailing List, Pavel Begunkov

[-- Attachment #1: Type: text/plain, Size: 2722 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  include/linux/uio.h

between commit:

  58194689921d8 ("iov_iter: Remove ITER_FOLIOQ")

from the vfs-brauner tree and commit:

  f41f84796a112 ("iov_iter: add iterator type for dmabuf maps")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --cc include/linux/uio.h
index 8d82a8258ef11,638c1116e912e..0000000000000
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@@ -11,6 -11,8 +11,7 @@@
  #include <uapi/linux/uio.h>
  
  struct page;
 -struct folio_queue;
+ struct dma_buf_io_map;
  
  typedef unsigned int __bitwise iov_iter_extraction_t;
  
@@@ -25,9 -27,10 +26,10 @@@ enum iter_type 
  	ITER_IOVEC,
  	ITER_BVEC,
  	ITER_KVEC,
 -	ITER_FOLIOQ,
 +	ITER_BVECQ,
  	ITER_XARRAY,
  	ITER_DISCARD,
+ 	ITER_DMABUF_MAP,
  };
  
  #define ITER_SOURCE	1	// == WRITE
@@@ -67,9 -70,10 +69,10 @@@ struct iov_iter 
  				const struct iovec *__iov;
  				const struct kvec *kvec;
  				const struct bio_vec *bvec;
 -				const struct folio_queue *folioq;
 +				const struct bvecq *bvecq;
  				struct xarray *xarray;
  				void __user *ubuf;
+ 				struct dma_buf_io_map *dmabuf_map;
  			};
  			size_t count;
  		};
@@@ -294,11 -303,14 +302,14 @@@ void iov_iter_kvec(struct iov_iter *i, 
  void iov_iter_bvec(struct iov_iter *i, unsigned int direction, const struct bio_vec *bvec,
  			unsigned long nr_segs, size_t count);
  void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count);
 -void iov_iter_folio_queue(struct iov_iter *i, unsigned int direction,
 -			  const struct folio_queue *folioq,
 -			  unsigned int first_slot, unsigned int offset, size_t count);
 +void iov_iter_bvec_queue(struct iov_iter *i, unsigned int direction,
 +			 const struct bvecq *bvecq,
 +			 unsigned int first_slot, unsigned int offset, size_t count);
  void iov_iter_xarray(struct iov_iter *i, unsigned int direction, struct xarray *xarray,
  		     loff_t start, size_t count);
+ void iov_iter_dmabuf_map(struct iov_iter *i, unsigned int direction,
+ 			struct dma_buf_io_map *map,
+ 			loff_t off, size_t count);
  ssize_t iov_iter_get_pages2(struct iov_iter *i, struct page **pages,
  			size_t maxsize, unsigned maxpages, size_t *start);
  ssize_t iov_iter_get_pages_alloc2(struct iov_iter *i, struct page ***pages,

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2026-03-05 13:44 Mark Brown
  2026-03-05 14:54 ` Christoph Hellwig
  0 siblings, 1 reply; 22+ messages in thread
From: Mark Brown @ 2026-03-05 13:44 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, Christoph Hellwig, Keith Busch,
	Linux Kernel Mailing List, Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 11346 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  block/t10-pi.c

between commit:

  179c2a24466b2 ("block: prepare generation / verification helpers for fs usage")

from the vfs-brauner tree and commit:

  7f0bc835bd428 ("blk-integrity: support arbitrary buffer alignment")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

I don't have a huge degree of confidence in this merge as the block
change was quite large and the code is entirely unfamiliar to me.

diff --cc block/t10-pi.c
index d27be6041fd31,3a564c0e2fe80..0000000000000
--- a/block/t10-pi.c
+++ b/block/t10-pi.c
@@@ -372,83 -267,283 +267,284 @@@ static void blk_integrity_set(struct bl
  	}
  }
  
+ static blk_status_t blk_integrity_interval(struct blk_integrity_iter *iter,
+ 					   bool verify)
+ {
+ 	blk_status_t ret = BLK_STS_OK;
+ 	union pi_tuple tuple;
+ 	void *ptuple = &tuple;
+ 	struct bio_vec pbv;
+ 
+ 	blk_integrity_csum_offset(iter);
+ 	pbv = bvec_iter_bvec(iter->bip->bip_vec, iter->prot_iter);
+ 	if (pbv.bv_len >= iter->bi->pi_tuple_size) {
+ 		ptuple = bvec_kmap_local(&pbv);
+ 		bvec_iter_advance_single(iter->bip->bip_vec, &iter->prot_iter,
+ 				iter->bi->metadata_size - iter->bi->pi_offset);
+ 	} else if (verify) {
+ 		blk_integrity_copy_to_tuple(iter->bip, &iter->prot_iter,
+ 				ptuple, iter->bi->pi_tuple_size);
+ 	}
+ 
+ 	if (verify)
+ 		ret = blk_integrity_verify(iter, ptuple);
+ 	else
+ 		blk_integrity_set(iter, ptuple);
+ 
+ 	if (likely(ptuple != &tuple)) {
+ 		kunmap_local(ptuple);
+ 	} else if (!verify) {
+ 		blk_integrity_copy_from_tuple(iter->bip, &iter->prot_iter,
+ 				ptuple, iter->bi->pi_tuple_size);
+ 	}
+ 
+ 	iter->interval_remaining = 1 << iter->bi->interval_exp;
+ 	iter->csum = 0;
+ 	iter->seed++;
+ 	return ret;
+ }
+ 
 -static void blk_integrity_iterate(struct bio *bio, struct bvec_iter *data_iter,
 -				  bool verify)
++static blk_status_t blk_integrity_iterate(struct bio *bio, struct bvec_iter *data_iter,
++					  bool verify)
+ {
+ 	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
+ 	struct bio_integrity_payload *bip = bio_integrity(bio);
+ 	struct blk_integrity_iter iter = {
+ 		.bio = bio,
+ 		.bip = bip,
+ 		.bi = bi,
+ 		.data_iter = *data_iter,
+ 		.prot_iter = bip->bip_iter,
+ 		.interval_remaining = 1 << bi->interval_exp,
+ 		.seed = data_iter->bi_sector,
+ 		.csum = 0,
+ 	};
+ 	blk_status_t ret = BLK_STS_OK;
+ 
+ 	while (iter.data_iter.bi_size && ret == BLK_STS_OK) {
+ 		struct bio_vec bv = bvec_iter_bvec(iter.bio->bi_io_vec,
+ 						   iter.data_iter);
+ 		void *kaddr = bvec_kmap_local(&bv);
+ 		void *data = kaddr;
+ 		unsigned int len;
+ 
+ 		bvec_iter_advance_single(iter.bio->bi_io_vec, &iter.data_iter,
+ 					 bv.bv_len);
+ 		while (bv.bv_len && ret == BLK_STS_OK) {
+ 			len = min(iter.interval_remaining, bv.bv_len);
+ 			blk_calculate_guard(&iter, data, len);
+ 			bv.bv_len -= len;
+ 			data += len;
+ 			iter.interval_remaining -= len;
+ 			if (!iter.interval_remaining)
+ 				ret = blk_integrity_interval(&iter, verify);
+ 		}
+ 		kunmap_local(kaddr);
+ 	}
+ 
 -	if (ret)
 -		bio->bi_status = ret;
++	return ret;
+ }
+ 
 -void blk_integrity_generate(struct bio *bio)
 +void bio_integrity_generate(struct bio *bio)
  {
  	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- 	struct bio_integrity_payload *bip = bio_integrity(bio);
- 	struct blk_integrity_iter iter;
- 	struct bvec_iter bviter;
- 	struct bio_vec bv;
  
- 	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
- 	iter.interval = 1 << bi->interval_exp;
- 	iter.seed = bio->bi_iter.bi_sector;
- 	iter.prot_buf = bvec_virt(bip->bip_vec);
- 	bio_for_each_segment(bv, bio, bviter) {
- 		void *kaddr = bvec_kmap_local(&bv);
- 
- 		iter.data_buf = kaddr;
- 		iter.data_size = bv.bv_len;
- 		switch (bi->csum_type) {
- 		case BLK_INTEGRITY_CSUM_CRC64:
- 			ext_pi_crc64_generate(&iter, bi);
- 			break;
- 		case BLK_INTEGRITY_CSUM_CRC:
- 		case BLK_INTEGRITY_CSUM_IP:
- 			t10_pi_generate(&iter, bi);
- 			break;
- 		default:
- 			break;
- 		}
- 		kunmap_local(kaddr);
+ 	switch (bi->csum_type) {
+ 	case BLK_INTEGRITY_CSUM_CRC64:
+ 	case BLK_INTEGRITY_CSUM_CRC:
+ 	case BLK_INTEGRITY_CSUM_IP:
+ 		blk_integrity_iterate(bio, &bio->bi_iter, false);
+ 		break;
+ 	default:
+ 		break;
  	}
  }
  
 -void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter)
 +blk_status_t bio_integrity_verify(struct bio *bio, struct bvec_iter *saved_iter)
  {
  	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- 	struct bio_integrity_payload *bip = bio_integrity(bio);
- 	struct blk_integrity_iter iter;
- 	struct bvec_iter bviter;
- 	struct bio_vec bv;
  
- 	/*
- 	 * At the moment verify is called bi_iter has been advanced during split
- 	 * and completion, so use the copy created during submission here.
- 	 */
- 	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
- 	iter.interval = 1 << bi->interval_exp;
- 	iter.seed = saved_iter->bi_sector;
- 	iter.prot_buf = bvec_virt(bip->bip_vec);
- 	__bio_for_each_segment(bv, bio, bviter, *saved_iter) {
- 		void *kaddr = bvec_kmap_local(&bv);
- 		blk_status_t ret = BLK_STS_OK;
- 
- 		iter.data_buf = kaddr;
- 		iter.data_size = bv.bv_len;
- 		switch (bi->csum_type) {
- 		case BLK_INTEGRITY_CSUM_CRC64:
- 			ret = ext_pi_crc64_verify(&iter, bi);
- 			break;
- 		case BLK_INTEGRITY_CSUM_CRC:
- 		case BLK_INTEGRITY_CSUM_IP:
- 			ret = t10_pi_verify(&iter, bi);
- 			break;
- 		default:
- 			break;
- 		}
- 		kunmap_local(kaddr);
- 
- 		if (ret)
- 			return ret;
+ 	switch (bi->csum_type) {
+ 	case BLK_INTEGRITY_CSUM_CRC64:
+ 	case BLK_INTEGRITY_CSUM_CRC:
+ 	case BLK_INTEGRITY_CSUM_IP:
 -		blk_integrity_iterate(bio, saved_iter, true);
++		return blk_integrity_iterate(bio, saved_iter, true);
+ 		break;
+ 	default:
+ 		break;
  	}
 +
 +	return BLK_STS_OK;
  }
  
- void blk_integrity_prepare(struct request *rq)
+ /*
+  * Advance @iter past the protection offset for protection formats that
+  * contain front padding on the metadata region.
+  */
+ static void blk_pi_advance_offset(struct blk_integrity *bi,
+ 				  struct bio_integrity_payload *bip,
+ 				  struct bvec_iter *iter)
+ {
+ 	unsigned int offset = bi->pi_offset;
+ 
+ 	while (offset > 0) {
+ 		struct bio_vec bv = mp_bvec_iter_bvec(bip->bip_vec, *iter);
+ 		unsigned int len = min(bv.bv_len, offset);
+ 
+ 		bvec_iter_advance_single(bip->bip_vec, iter, len);
+ 		offset -= len;
+ 	}
+ }
+ 
+ static void *blk_tuple_remap_begin(union pi_tuple *tuple,
+ 				   struct blk_integrity *bi,
+ 				   struct bio_integrity_payload *bip,
+ 				   struct bvec_iter *iter)
+ {
+ 	struct bvec_iter titer;
+ 	struct bio_vec pbv;
+ 
+ 	blk_pi_advance_offset(bi, bip, iter);
+ 	pbv = bvec_iter_bvec(bip->bip_vec, *iter);
+ 	if (likely(pbv.bv_len >= bi->pi_tuple_size))
+ 		return bvec_kmap_local(&pbv);
+ 
+ 	/*
+ 	 * We need to preserve the state of the original iter for the
+ 	 * copy_from_tuple at the end, so make a temp iter for here.
+ 	 */
+ 	titer = *iter;
+ 	blk_integrity_copy_to_tuple(bip, &titer, tuple, bi->pi_tuple_size);
+ 	return tuple;
+ }
+ 
+ static void blk_tuple_remap_end(union pi_tuple *tuple, void *ptuple,
+ 				struct blk_integrity *bi,
+ 				struct bio_integrity_payload *bip,
+ 				struct bvec_iter *iter)
+ {
+ 	unsigned int len = bi->metadata_size - bi->pi_offset;
+ 
+ 	if (likely(ptuple != tuple)) {
+ 		kunmap_local(ptuple);
+ 	} else {
+ 		blk_integrity_copy_from_tuple(bip, iter, ptuple,
+ 				bi->pi_tuple_size);
+ 		len -= bi->pi_tuple_size;
+ 	}
+ 
+ 	bvec_iter_advance(bip->bip_vec, iter, len);
+ }
+ 
+ static void blk_set_ext_unmap_ref(struct crc64_pi_tuple *pi, u64 virt,
+ 				  u64 ref_tag)
+ {
+ 	u64 ref = get_unaligned_be48(&pi->ref_tag);
+ 
+ 	if (ref == lower_48_bits(ref_tag) && ref != lower_48_bits(virt))
+ 		put_unaligned_be48(virt, pi->ref_tag);
+ }
+ 
+ static void blk_set_t10_unmap_ref(struct t10_pi_tuple *pi, u32 virt,
+ 				  u32 ref_tag)
+ {
+ 	u32 ref = get_unaligned_be32(&pi->ref_tag);
+ 
+ 	if (ref == ref_tag && ref != virt)
+ 		put_unaligned_be32(virt, &pi->ref_tag);
+ }
+ 
+ static void blk_reftag_remap_complete(struct blk_integrity *bi,
+ 				      union pi_tuple *tuple, u64 virt, u64 ref)
+ {
+ 	switch (bi->csum_type) {
+ 	case BLK_INTEGRITY_CSUM_CRC64:
+ 		blk_set_ext_unmap_ref(&tuple->crc64_pi, virt, ref);
+ 		break;
+ 	case BLK_INTEGRITY_CSUM_CRC:
+ 	case BLK_INTEGRITY_CSUM_IP:
+ 		blk_set_t10_unmap_ref(&tuple->t10_pi, virt, ref);
+ 		break;
+ 	default:
+ 		WARN_ON_ONCE(1);
+ 		break;
+ 	}
+ }
+ 
+ static void blk_set_ext_map_ref(struct crc64_pi_tuple *pi, u64 virt,
+ 				u64 ref_tag)
+ {
+ 	u64 ref = get_unaligned_be48(&pi->ref_tag);
+ 
+ 	if (ref == lower_48_bits(virt) && ref != ref_tag)
+ 		put_unaligned_be48(ref_tag, pi->ref_tag);
+ }
+ 
+ static void blk_set_t10_map_ref(struct t10_pi_tuple *pi, u32 virt, u32 ref_tag)
+ {
+ 	u32 ref = get_unaligned_be32(&pi->ref_tag);
+ 
+ 	if (ref == virt && ref != ref_tag)
+ 		put_unaligned_be32(ref_tag, &pi->ref_tag);
+ }
+ 
+ static void blk_reftag_remap_prepare(struct blk_integrity *bi,
+ 				     union pi_tuple *tuple,
+ 				     u64 virt, u64 ref)
+ {
+ 	switch (bi->csum_type) {
+ 	case BLK_INTEGRITY_CSUM_CRC64:
+ 		blk_set_ext_map_ref(&tuple->crc64_pi, virt, ref);
+ 		break;
+ 	case BLK_INTEGRITY_CSUM_CRC:
+ 	case BLK_INTEGRITY_CSUM_IP:
+ 		blk_set_t10_map_ref(&tuple->t10_pi, virt, ref);
+ 		break;
+ 	default:
+ 		WARN_ON_ONCE(1);
+ 		break;
+ 	}
+ }
+ 
+ static void __blk_reftag_remap(struct bio *bio, struct blk_integrity *bi,
+ 			       unsigned *intervals, u64 *ref, bool prep)
+ {
+ 	struct bio_integrity_payload *bip = bio_integrity(bio);
+ 	struct bvec_iter iter = bip->bip_iter;
+ 	u64 virt = bip_get_seed(bip);
+ 	union pi_tuple *ptuple;
+ 	union pi_tuple tuple;
+ 
+ 	if (prep && bip->bip_flags & BIP_MAPPED_INTEGRITY) {
+ 		*ref += bio->bi_iter.bi_size >> bi->interval_exp;
+ 		return;
+ 	}
+ 
+ 	while (iter.bi_size && *intervals) {
+ 		ptuple = blk_tuple_remap_begin(&tuple, bi, bip, &iter);
+ 
+ 		if (prep)
+ 			blk_reftag_remap_prepare(bi, ptuple, virt, *ref);
+ 		else
+ 			blk_reftag_remap_complete(bi, ptuple, virt, *ref);
+ 
+ 		blk_tuple_remap_end(&tuple, ptuple, bi, bip, &iter);
+ 		(*intervals)--;
+ 		(*ref)++;
+ 		virt++;
+ 	}
+ 
+ 	if (prep)
+ 		bip->bip_flags |= BIP_MAPPED_INTEGRITY;
+ }
+ 
+ static void blk_integrity_remap(struct request *rq, unsigned int nr_bytes,
+ 				bool prep)
  {
  	struct blk_integrity *bi = &rq->q->limits.integrity;
+ 	u64 ref = blk_rq_pos(rq) >> (bi->interval_exp - SECTOR_SHIFT);
+ 	unsigned intervals = nr_bytes >> bi->interval_exp;
+ 	struct bio *bio;
  
  	if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
  		return;

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2025-11-17  3:32 Stephen Rothwell
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Rothwell @ 2025-11-17  3:32 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner
  Cc: Caleb Sander Mateos, Christoph Hellwig,
	Linux Kernel Mailing List, Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 1511 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  io_uring/rw.c

between commit:

  56749ed317e2 ("fs, iomap: remove IOCB_DIO_CALLER_COMP")

from the vfs-brauner tree and commit:

  c33e779aba68 ("io_uring: add wrapper type for io_req_tw_func_t arg")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc io_uring/rw.c
index 6310a3d08409,a7b568c3dfe8..000000000000
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@@ -566,8 -567,18 +566,10 @@@ static inline int io_fixup_rw_res(struc
  	return res;
  }
  
- void io_req_rw_complete(struct io_kiocb *req, io_tw_token_t tw)
+ void io_req_rw_complete(struct io_tw_req tw_req, io_tw_token_t tw)
  {
+ 	struct io_kiocb *req = tw_req.req;
 -	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
 -	struct kiocb *kiocb = &rw->kiocb;
 -
 -	if ((kiocb->ki_flags & IOCB_DIO_CALLER_COMP) && kiocb->dio_complete) {
 -		long res = kiocb->dio_complete(rw->kiocb.private);
 -
 -		io_req_set_res(req, io_fixup_rw_res(req, res), 0);
 -	}
+ 
  	io_req_io_end(req);
  
  	if (req->flags & (REQ_F_BUFFER_SELECTED|REQ_F_BUFFER_RING))

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2024-06-28 17:59 Mark Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Brown @ 2024-06-28 17:59 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, John Garry, Linux Kernel Mailing List,
	Linux Next Mailing List, Prasad Singamsetty

[-- Attachment #1: Type: text/plain, Size: 1392 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  include/linux/fs.h

between commit:

  1bc6d4452d5c9 ("fs: new helper vfs_empty_path()")

from the vfs-brauner tree and commit:

  c34fc6f26ab86 ("fs: Initial atomic write support")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --cc include/linux/fs.h
index dc9f9c4b2572d,db26b4a70c628..0000000000000
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@@ -3626,21 -3627,6 +3640,23 @@@ extern int vfs_fadvise(struct file *fil
  extern int generic_fadvise(struct file *file, loff_t offset, loff_t len,
  			   int advice);
  
 +static inline bool vfs_empty_path(int dfd, const char __user *path)
 +{
 +	char c;
 +
 +	if (dfd < 0)
 +		return false;
 +
 +	/* We now allow NULL to be used for empty path. */
 +	if (!path)
 +		return true;
 +
 +	if (unlikely(get_user(c, path)))
 +		return false;
 +
 +	return !c;
 +}
 +
+ bool generic_atomic_write_valid(struct iov_iter *iter, loff_t pos);
+ 
  #endif /* _LINUX_FS_H */

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2024-06-28 17:59 Mark Brown
  2024-06-29 10:05 ` Christian Brauner
  0 siblings, 1 reply; 22+ messages in thread
From: Mark Brown @ 2024-06-28 17:59 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christian Brauner, John Garry, Linux Kernel Mailing List,
	Linux Next Mailing List, Mateusz Guzik, Prasad Singamsetty

[-- Attachment #1: Type: text/plain, Size: 2574 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  fs/stat.c

between commit:

  0ef625bba6fb2 ("vfs: support statx(..., NULL, AT_EMPTY_PATH, ...)")

from the vfs-brauner tree and commit:

  0f9ca80fa4f96 ("fs: Add initial atomic write support info to statx")
  9abcfbd235f59 ("block: Add atomic write support for statx")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --cc fs/stat.c
index 6f65b3456cadb,bd0698dfd7b36..0000000000000
--- a/fs/stat.c
+++ b/fs/stat.c
@@@ -214,43 -245,6 +245,45 @@@ int getname_statx_lookup_flags(int flag
  	return lookup_flags;
  }
  
 +static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
 +			  u32 request_mask)
 +{
 +	int error = vfs_getattr(path, stat, request_mask, flags);
++	struct inode *backing_inode;
 +
 +	if (request_mask & STATX_MNT_ID_UNIQUE) {
 +		stat->mnt_id = real_mount(path->mnt)->mnt_id_unique;
 +		stat->result_mask |= STATX_MNT_ID_UNIQUE;
 +	} else {
 +		stat->mnt_id = real_mount(path->mnt)->mnt_id;
 +		stat->result_mask |= STATX_MNT_ID;
 +	}
 +
 +	if (path_mounted(path))
 +		stat->attributes |= STATX_ATTR_MOUNT_ROOT;
 +	stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
 +
- 	/* Handle STATX_DIOALIGN for block devices. */
- 	if (request_mask & STATX_DIOALIGN) {
- 		struct inode *inode = d_backing_inode(path->dentry);
- 
- 		if (S_ISBLK(inode->i_mode))
- 			bdev_statx_dioalign(inode, stat);
- 	}
++	/*
++	 * If this is a block device inode, override the filesystem
++	 * attributes with the block device specific parameters that need to be
++	 * obtained from the bdev backing inode.
++	 */
++	backing_inode = d_backing_inode(path->dentry);
++	if (S_ISBLK(backing_inode->i_mode))
++		bdev_statx(backing_inode, stat, request_mask);
 +
 +	return error;
 +}
 +
 +static int vfs_statx_fd(int fd, int flags, struct kstat *stat,
 +			  u32 request_mask)
 +{
 +	CLASS(fd_raw, f)(fd);
 +	if (!f.file)
 +		return -EBADF;
 +	return vfs_statx_path(&f.file->f_path, flags, stat, request_mask);
 +}
 +
  /**
   * vfs_statx - Get basic and extra attributes by filename
   * @dfd: A file descriptor representing the base dir for a relative filename

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2024-05-08  3:02 Stephen Rothwell
  2024-05-08  6:46 ` Christoph Hellwig
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Rothwell @ 2024-05-08  3:02 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Al Viro, Christian Brauner, Christoph Hellwig,
	Linux Kernel Mailing List, Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 2418 bytes --]

Hi all,

FIXME: Add owner of second tree to To:
       Add author(s)/SOB of conflicting commits.

Today's linux-next merge of the block tree got a conflict in:

  block/ioctl.c

between commit:

  695eaf683e8e ("blk_ioctl_{discard,zeroout}(): we only want ->bd_inode->i_mapping here...")

from the vfs-brauner tree and commits:

  719c15a75ebf ("blk-lib: check for kill signal in ioctl BLKDISCARD")
  fb4271f2bfac ("Merge branch 'for-6.10/block' into for-next")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc block/ioctl.c
index 3b31c09941dc,c0f1b6583a9a..000000000000
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@@ -95,8 -95,13 +95,12 @@@ static int compat_blkpg_ioctl(struct bl
  static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
  		unsigned long arg)
  {
+ 	unsigned int bs_mask = bdev_logical_block_size(bdev) - 1;
  	uint64_t range[2];
  	uint64_t start, len, end;
 -	struct inode *inode = bdev->bd_inode;
+ 	struct bio *prev = NULL, *bio;
+ 	sector_t sector, nr_sects;
+ 	struct blk_plug plug;
  	int err;
  
  	if (!(mode & BLK_OPEN_WRITE))
@@@ -124,9 -131,34 +130,34 @@@
  	err = truncate_bdev_range(bdev, mode, start, start + len - 1);
  	if (err)
  		goto fail;
- 	err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
+ 
+ 	sector = start >> SECTOR_SHIFT;
+ 	nr_sects = len >> SECTOR_SHIFT;
+ 
+ 	blk_start_plug(&plug);
+ 	while (1) {
+ 		if (fatal_signal_pending(current)) {
+ 			if (prev)
+ 				bio_await_chain(prev);
+ 			err = -EINTR;
+ 			goto out_unplug;
+ 		}
+ 		bio = blk_alloc_discard_bio(bdev, &sector, &nr_sects,
+ 				GFP_KERNEL);
+ 		if (!bio)
+ 			break;
+ 		prev = bio_chain_and_submit(prev, bio);
+ 	}
+ 	if (prev) {
+ 		err = submit_bio_wait(prev);
+ 		if (err == -EOPNOTSUPP)
+ 			err = 0;
+ 		bio_put(prev);
+ 	}
+ out_unplug:
+ 	blk_finish_plug(&plug);
  fail:
 -	filemap_invalidate_unlock(inode->i_mapping);
 +	filemap_invalidate_unlock(bdev->bd_mapping);
  	return err;
  }
  

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2024-04-02  0:21 Stephen Rothwell
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Rothwell @ 2024-04-02  0:21 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner
  Cc: Linux Kernel Mailing List, Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 1557 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  io_uring/rw.c

between commit:

  80a07849c0b8 ("fs: claw back a few FMODE_* bits")

from the vfs-brauner tree and commit:

  40ffda3dc1a1 ("io_uring/rw: always setup io_async_rw for read/write requests")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc io_uring/rw.c
index d9dfde1142a1,3134a6ece1be..000000000000
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@@ -1021,13 -1003,13 +1004,13 @@@ int io_write(struct io_kiocb *req, unsi
  	if (force_nonblock) {
  		/* If the file doesn't support async, just async punt */
  		if (unlikely(!io_file_supports_nowait(req)))
- 			goto copy_iov;
+ 			goto ret_eagain;
  
 -		/* File path supports NOWAIT for non-direct_IO only for block devices. */
 +		/* Check if we can support NOWAIT. */
  		if (!(kiocb->ki_flags & IOCB_DIRECT) &&
 -			!(kiocb->ki_filp->f_mode & FMODE_BUF_WASYNC) &&
 -			(req->flags & REQ_F_ISREG))
 +		    !(req->file->f_op->fop_flags & FOP_BUFFER_WASYNC) &&
 +		    (req->flags & REQ_F_ISREG))
- 			goto copy_iov;
+ 			goto ret_eagain;
  
  		kiocb->ki_flags |= IOCB_NOWAIT;
  	} else {

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread
* linux-next: manual merge of the block tree with the vfs-brauner tree
@ 2024-02-06  1:48 Stephen Rothwell
  2024-02-06 16:37 ` Jens Axboe
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Rothwell @ 2024-02-06  1:48 UTC (permalink / raw)
  To: Jens Axboe, Christian Brauner
  Cc: Linux Kernel Mailing List, Linux Next Mailing List

[-- Attachment #1: Type: text/plain, Size: 3656 bytes --]

Hi all,

Today's linux-next merge of the block tree got a conflict in:

  block/blk.h

between commits:

  19db932fd2b0 ("bdev: make bdev_{release, open_by_dev}() private to block layer")
  09f8289e1b74 ("bdev: make struct bdev_handle private to the block layer")
  d75140abba91 ("bdev: remove bdev pointer from struct bdev_handle")

from the vfs-brauner tree and commits:

  c4e47bbb00da ("block: move cgroup time handling code into blk.h")
  08420cf70cfb ("block: add blk_time_get_ns() and blk_time_get() helpers")
  da4c8c3d0975 ("block: cache current nsec time in struct blk_plug")
  06b23f92af87 ("block: update cached timestamp post schedule/preemption")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc block/blk.h
index f02b25f22e8b,913c93838a01..000000000000
--- a/block/blk.h
+++ b/block/blk.h
@@@ -516,8 -517,70 +517,75 @@@ static inline int req_ref_read(struct r
  	return atomic_read(&req->ref);
  }
  
 +void bdev_release(struct file *bdev_file);
 +int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
 +	      const struct blk_holder_ops *hops, struct file *bdev_file);
 +int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
++
+ static inline u64 blk_time_get_ns(void)
+ {
+ 	struct blk_plug *plug = current->plug;
+ 
+ 	if (!plug)
+ 		return ktime_get_ns();
+ 
+ 	/*
+ 	 * 0 could very well be a valid time, but rather than flag "this is
+ 	 * a valid timestamp" separately, just accept that we'll do an extra
+ 	 * ktime_get_ns() if we just happen to get 0 as the current time.
+ 	 */
+ 	if (!plug->cur_ktime) {
+ 		plug->cur_ktime = ktime_get_ns();
+ 		current->flags |= PF_BLOCK_TS;
+ 	}
+ 	return plug->cur_ktime;
+ }
+ 
+ static inline ktime_t blk_time_get(void)
+ {
+ 	return ns_to_ktime(blk_time_get_ns());
+ }
+ 
+ /*
+  * From most significant bit:
+  * 1 bit: reserved for other usage, see below
+  * 12 bits: original size of bio
+  * 51 bits: issue time of bio
+  */
+ #define BIO_ISSUE_RES_BITS      1
+ #define BIO_ISSUE_SIZE_BITS     12
+ #define BIO_ISSUE_RES_SHIFT     (64 - BIO_ISSUE_RES_BITS)
+ #define BIO_ISSUE_SIZE_SHIFT    (BIO_ISSUE_RES_SHIFT - BIO_ISSUE_SIZE_BITS)
+ #define BIO_ISSUE_TIME_MASK     ((1ULL << BIO_ISSUE_SIZE_SHIFT) - 1)
+ #define BIO_ISSUE_SIZE_MASK     \
+ 	(((1ULL << BIO_ISSUE_SIZE_BITS) - 1) << BIO_ISSUE_SIZE_SHIFT)
+ #define BIO_ISSUE_RES_MASK      (~((1ULL << BIO_ISSUE_RES_SHIFT) - 1))
+ 
+ /* Reserved bit for blk-throtl */
+ #define BIO_ISSUE_THROTL_SKIP_LATENCY (1ULL << 63)
+ 
+ static inline u64 __bio_issue_time(u64 time)
+ {
+ 	return time & BIO_ISSUE_TIME_MASK;
+ }
+ 
+ static inline u64 bio_issue_time(struct bio_issue *issue)
+ {
+ 	return __bio_issue_time(issue->value);
+ }
+ 
+ static inline sector_t bio_issue_size(struct bio_issue *issue)
+ {
+ 	return ((issue->value & BIO_ISSUE_SIZE_MASK) >> BIO_ISSUE_SIZE_SHIFT);
+ }
+ 
+ static inline void bio_issue_init(struct bio_issue *issue,
+ 				       sector_t size)
+ {
+ 	size &= (1ULL << BIO_ISSUE_SIZE_BITS) - 1;
+ 	issue->value = ((issue->value & BIO_ISSUE_RES_MASK) |
+ 			(blk_time_get_ns() & BIO_ISSUE_TIME_MASK) |
+ 			((u64)size << BIO_ISSUE_SIZE_SHIFT));
+ }
+ 
  #endif /* BLK_INTERNAL_H */

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2026-10-13 17:00 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 17:00 linux-next: manual merge of the block tree with the vfs-brauner tree Mark Brown
  -- strict thread matches above, loose matches on Subject: below --
2026-10-13 16:49 Mark Brown
2026-03-05 13:44 Mark Brown
2026-03-05 14:54 ` Christoph Hellwig
2026-03-05 15:18   ` Mark Brown
2026-03-05 17:34   ` Keith Busch
2026-03-06 14:22     ` Christoph Hellwig
2026-03-09 13:45       ` Jens Axboe
2026-03-09 13:48         ` Jens Axboe
2026-03-09 13:54           ` Jens Axboe
2026-03-10  6:26             ` Christoph Hellwig
2025-11-17  3:32 Stephen Rothwell
2024-06-28 17:59 Mark Brown
2024-06-28 17:59 Mark Brown
2024-06-29 10:05 ` Christian Brauner
2024-06-29 14:28   ` Jens Axboe
2024-05-08  3:02 Stephen Rothwell
2024-05-08  6:46 ` Christoph Hellwig
2024-04-02  0:21 Stephen Rothwell
2024-02-06  1:48 Stephen Rothwell
2024-02-06 16:37 ` Jens Axboe
2024-02-07  9:27   ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®