mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	NFS: Allow nfs_updatepage to extend a write under additional circumstances
Currently nfs_updatepage allows a write to be extended to cover a full page only if we don't have a byte range lock lock on the file... but if we have a write delegation on the file or if we have the whole file locked for writing then we should be allowed to extend the write as well. Signed-off-by: Scott Mayhew <smayhew@redhat.com> [Trond: fix up call to nfs_have_delegation()] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									07b5ce8ef2
								
							
						
					
					
						commit
						c7559663e4
					
				
					 1 changed files with 23 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -888,6 +888,28 @@ static bool nfs_write_pageuptodate(struct page *page, struct inode *inode)
 | 
			
		|||
	return PageUptodate(page) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* If we know the page is up to date, and we're not using byte range locks (or
 | 
			
		||||
 * if we have the whole file locked for writing), it may be more efficient to
 | 
			
		||||
 * extend the write to cover the entire page in order to avoid fragmentation
 | 
			
		||||
 * inefficiencies.
 | 
			
		||||
 *
 | 
			
		||||
 * If the file is opened for synchronous writes or if we have a write delegation
 | 
			
		||||
 * from the server then we can just skip the rest of the checks.
 | 
			
		||||
 */
 | 
			
		||||
static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
 | 
			
		||||
{
 | 
			
		||||
	if (file->f_flags & O_DSYNC)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
 | 
			
		||||
		return 1;
 | 
			
		||||
	if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL ||
 | 
			
		||||
			(inode->i_flock->fl_start == 0 &&
 | 
			
		||||
			inode->i_flock->fl_end == OFFSET_MAX &&
 | 
			
		||||
			inode->i_flock->fl_type != F_RDLCK)))
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Update and possibly write a cached page of an NFS file.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -908,14 +930,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 | 
			
		|||
		file->f_path.dentry->d_name.name, count,
 | 
			
		||||
		(long long)(page_file_offset(page) + offset));
 | 
			
		||||
 | 
			
		||||
	/* If we're not using byte range locks, and we know the page
 | 
			
		||||
	 * is up to date, it may be more efficient to extend the write
 | 
			
		||||
	 * to cover the entire page in order to avoid fragmentation
 | 
			
		||||
	 * inefficiencies.
 | 
			
		||||
	 */
 | 
			
		||||
	if (nfs_write_pageuptodate(page, inode) &&
 | 
			
		||||
			inode->i_flock == NULL &&
 | 
			
		||||
			!(file->f_flags & O_DSYNC)) {
 | 
			
		||||
	if (nfs_can_extend_write(file, page, inode)) {
 | 
			
		||||
		count = max(count + offset, nfs_page_length(page));
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue