diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-06-11 12:21:19 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-07-15 18:10:51 -0400 |
commit | a3d01454bc58b5a211ef64a7670572a40b71e682 (patch) | |
tree | 68c1ba383fb2c6702a8cc02bc81d51da6fb2920b /fs/nfs/write.c | |
parent | 1b83d707032a1be40a60ed0a9bd841662cc04a5d (diff) |
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>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index feca8c648766..3229e217c773 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -133,16 +133,21 @@ static struct nfs_page *nfs_page_find_request(struct page *page) | |||
133 | static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) | 133 | static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) |
134 | { | 134 | { |
135 | struct inode *inode = page->mapping->host; | 135 | struct inode *inode = page->mapping->host; |
136 | loff_t end, i_size = i_size_read(inode); | 136 | loff_t end, i_size; |
137 | pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; | 137 | pgoff_t end_index; |
138 | 138 | ||
139 | spin_lock(&inode->i_lock); | ||
140 | i_size = i_size_read(inode); | ||
141 | end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; | ||
139 | if (i_size > 0 && page->index < end_index) | 142 | if (i_size > 0 && page->index < end_index) |
140 | return; | 143 | goto out; |
141 | end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); | 144 | end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); |
142 | if (i_size >= end) | 145 | if (i_size >= end) |
143 | return; | 146 | goto out; |
144 | nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); | ||
145 | i_size_write(inode, end); | 147 | i_size_write(inode, end); |
148 | nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); | ||
149 | out: | ||
150 | spin_unlock(&inode->i_lock); | ||
146 | } | 151 | } |
147 | 152 | ||
148 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ | 153 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ |