NFS: Remove BKL requirement from attribute updates
The main problem is dealing with inode->i_size: we need to set the inode->i_lock on all attribute updates, and so vmtruncate won't cut it. Make an NFS-private version of vmtruncate that has the necessary locking semantics. The result should be that the following inode attribute updates are protected by inode->i_lock nfsi->cache_validity nfsi->read_cache_jiffies nfsi->attrtimeo nfsi->attrtimeo_timestamp nfsi->change_attr nfsi->last_updated nfsi->cache_change_attribute nfsi->access_cache nfsi->access_cache_entry_lru nfsi->access_cache_inode_lru nfsi->acl_access nfsi->acl_default nfsi->nfs_page_tree nfsi->ncommit nfsi->npages nfsi->open_files nfsi->silly_list nfsi->acl nfsi->open_states inode->i_size inode->i_atime inode->i_mtime inode->i_ctime inode->i_nlink inode->i_uid inode->i_gid The following is protected by dir->i_mutex nfsi->cookieverf Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
@@ -133,16 +133,21 @@ static struct nfs_page *nfs_page_find_request(struct page *page)
|
||||
static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count)
|
||||
{
|
||||
struct inode *inode = page->mapping->host;
|
||||
loff_t end, i_size = i_size_read(inode);
|
||||
pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
|
||||
loff_t end, i_size;
|
||||
pgoff_t end_index;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
i_size = i_size_read(inode);
|
||||
end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
|
||||
if (i_size > 0 && page->index < end_index)
|
||||
return;
|
||||
goto out;
|
||||
end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count);
|
||||
if (i_size >= end)
|
||||
return;
|
||||
nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
|
||||
goto out;
|
||||
i_size_write(inode, end);
|
||||
nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
|
||||
out:
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
/* A writeback failed: mark the page as bad, and invalidate the page cache */
|
||||
|
Reference in New Issue
Block a user