diff options
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 48 | 
1 files changed, 29 insertions, 19 deletions
| diff --git a/mm/filemap.c b/mm/filemap.c index 657bcd887fdb..d62150418b91 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -177,7 +177,7 @@ static void filemap_unaccount_folio(struct address_space *mapping,  				 * and we'd rather not leak it: if we're wrong,  				 * another bad page check should catch it later.  				 */ -				page_mapcount_reset(&folio->page); +				atomic_set(&folio->_mapcount, -1);  				folio_ref_sub(folio, mapcount);  			}  		} @@ -1752,12 +1752,12 @@ pgoff_t page_cache_next_miss(struct address_space *mapping,  	while (max_scan--) {  		void *entry = xas_next(&xas);  		if (!entry || xa_is_value(entry)) -			break; +			return xas.xa_index;  		if (xas.xa_index == 0) -			break; +			return 0;  	} -	return xas.xa_index; +	return index + max_scan;  }  EXPORT_SYMBOL(page_cache_next_miss); @@ -3982,21 +3982,24 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i)  	loff_t pos = iocb->ki_pos;  	struct address_space *mapping = file->f_mapping;  	const struct address_space_operations *a_ops = mapping->a_ops; +	size_t chunk = mapping_max_folio_size(mapping);  	long status = 0;  	ssize_t written = 0;  	do {  		struct page *page; -		unsigned long offset;	/* Offset into pagecache page */ -		unsigned long bytes;	/* Bytes to write to page */ +		struct folio *folio; +		size_t offset;		/* Offset into folio */ +		size_t bytes;		/* Bytes to write to folio */  		size_t copied;		/* Bytes copied from user */  		void *fsdata = NULL; -		offset = (pos & (PAGE_SIZE - 1)); -		bytes = min_t(unsigned long, PAGE_SIZE - offset, -						iov_iter_count(i)); +		bytes = iov_iter_count(i); +retry: +		offset = pos & (chunk - 1); +		bytes = min(chunk - offset, bytes); +		balance_dirty_pages_ratelimited(mapping); -again:  		/*  		 * Bring in the user page that we will copy from _first_.  		 * Otherwise there's a nasty deadlock on copying from the @@ -4018,11 +4021,16 @@ again:  		if (unlikely(status < 0))  			break; +		folio = page_folio(page); +		offset = offset_in_folio(folio, pos); +		if (bytes > folio_size(folio) - offset) +			bytes = folio_size(folio) - offset; +  		if (mapping_writably_mapped(mapping)) -			flush_dcache_page(page); +			flush_dcache_folio(folio); -		copied = copy_page_from_iter_atomic(page, offset, bytes, i); -		flush_dcache_page(page); +		copied = copy_folio_from_iter_atomic(folio, offset, bytes, i); +		flush_dcache_folio(folio);  		status = a_ops->write_end(file, mapping, pos, bytes, copied,  						page, fsdata); @@ -4040,14 +4048,16 @@ again:  			 * halfway through, might be a race with munmap,  			 * might be severe memory pressure.  			 */ -			if (copied) +			if (chunk > PAGE_SIZE) +				chunk /= 2; +			if (copied) {  				bytes = copied; -			goto again; +				goto retry; +			} +		} else { +			pos += status; +			written += status;  		} -		pos += status; -		written += status; - -		balance_dirty_pages_ratelimited(mapping);  	} while (iov_iter_count(i));  	if (!written) |