diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 10:52:35 -0400 |
commit | df632d3ce7eacf92ad9b642301c7b53a1d95b8d8 (patch) | |
tree | 848c39ed4f7cfdb582bf2e0a0a03147efaa5198d /fs/nfs/file.c | |
parent | 2474542f64432398f503373f53bdf620491bcfa8 (diff) | |
parent | af283885b70248268617955a5ea5476647bd556b (diff) |
Merge tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Features include:
- Remove CONFIG_EXPERIMENTAL dependency from NFSv4.1
Aside from the issues discussed at the LKS, distros are shipping
NFSv4.1 with all the trimmings.
- Fix fdatasync()/fsync() for the corner case of a server reboot.
- NFSv4 OPEN access fix: finally distinguish correctly between
open-for-read and open-for-execute permissions in all situations.
- Ensure that the TCP socket is closed when we're in CLOSE_WAIT
- More idmapper bugfixes
- Lots of pNFS bugfixes and cleanups to remove unnecessary state and
make the code easier to read.
- In cases where a pNFS read or write fails, allow the client to
resume trying layoutgets after two minutes of read/write-
through-mds.
- More net namespace fixes to the NFSv4 callback code.
- More net namespace fixes to the NFSv3 locking code.
- More NFSv4 migration preparatory patches.
Including patches to detect network trunking in both NFSv4 and
NFSv4.1
- pNFS block updates to optimise LAYOUTGET calls."
* tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (113 commits)
pnfsblock: cleanup nfs4_blkdev_get
NFS41: send real read size in layoutget
NFS41: send real write size in layoutget
NFS: track direct IO left bytes
NFSv4.1: Cleanup ugliness in pnfs_layoutgets_blocked()
NFSv4.1: Ensure that the layout sequence id stays 'close' to the current
NFSv4.1: Deal with seqid wraparound in the pNFS return-on-close code
NFSv4 set open access operation call flag in nfs4_init_opendata_res
NFSv4.1: Remove the dependency on CONFIG_EXPERIMENTAL
NFSv4 reduce attribute requests for open reclaim
NFSv4: nfs4_open_done first must check that GETATTR decoded a file type
NFSv4.1: Deal with wraparound when updating the layout "barrier" seqid
NFSv4.1: Deal with wraparound issues when updating the layout stateid
NFSv4.1: Always set the layout stateid if this is the first layoutget
NFSv4.1: Fix another refcount issue in pnfs_find_alloc_layout
NFSv4: don't put ACCESS in OPEN compound if O_EXCL
NFSv4: don't check MAY_WRITE access bit in OPEN
NFS: Set key construction data for the legacy upcall
NFSv4.1: don't do two EXCHANGE_IDs on mount
NFS: nfs41_walk_client_list(): re-lock before iterating
...
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f692be97676d..582bb8866131 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -259,7 +259,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) | |||
259 | struct dentry *dentry = file->f_path.dentry; | 259 | struct dentry *dentry = file->f_path.dentry; |
260 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 260 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
261 | struct inode *inode = dentry->d_inode; | 261 | struct inode *inode = dentry->d_inode; |
262 | int have_error, status; | 262 | int have_error, do_resend, status; |
263 | int ret = 0; | 263 | int ret = 0; |
264 | 264 | ||
265 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", | 265 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
@@ -267,15 +267,23 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) | |||
267 | datasync); | 267 | datasync); |
268 | 268 | ||
269 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 269 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
270 | do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); | ||
270 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | 271 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
271 | status = nfs_commit_inode(inode, FLUSH_SYNC); | 272 | status = nfs_commit_inode(inode, FLUSH_SYNC); |
272 | if (status >= 0 && ret < 0) | ||
273 | status = ret; | ||
274 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | 273 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
275 | if (have_error) | 274 | if (have_error) { |
276 | ret = xchg(&ctx->error, 0); | 275 | ret = xchg(&ctx->error, 0); |
277 | if (!ret && status < 0) | 276 | if (ret) |
277 | goto out; | ||
278 | } | ||
279 | if (status < 0) { | ||
278 | ret = status; | 280 | ret = status; |
281 | goto out; | ||
282 | } | ||
283 | do_resend |= test_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); | ||
284 | if (do_resend) | ||
285 | ret = -EAGAIN; | ||
286 | out: | ||
279 | return ret; | 287 | return ret; |
280 | } | 288 | } |
281 | EXPORT_SYMBOL_GPL(nfs_file_fsync_commit); | 289 | EXPORT_SYMBOL_GPL(nfs_file_fsync_commit); |
@@ -286,13 +294,22 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
286 | int ret; | 294 | int ret; |
287 | struct inode *inode = file->f_path.dentry->d_inode; | 295 | struct inode *inode = file->f_path.dentry->d_inode; |
288 | 296 | ||
289 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 297 | do { |
290 | if (ret != 0) | 298 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
291 | goto out; | 299 | if (ret != 0) |
292 | mutex_lock(&inode->i_mutex); | 300 | break; |
293 | ret = nfs_file_fsync_commit(file, start, end, datasync); | 301 | mutex_lock(&inode->i_mutex); |
294 | mutex_unlock(&inode->i_mutex); | 302 | ret = nfs_file_fsync_commit(file, start, end, datasync); |
295 | out: | 303 | mutex_unlock(&inode->i_mutex); |
304 | /* | ||
305 | * If nfs_file_fsync_commit detected a server reboot, then | ||
306 | * resend all dirty pages that might have been covered by | ||
307 | * the NFS_CONTEXT_RESEND_WRITES flag | ||
308 | */ | ||
309 | start = 0; | ||
310 | end = LLONG_MAX; | ||
311 | } while (ret == -EAGAIN); | ||
312 | |||
296 | return ret; | 313 | return ret; |
297 | } | 314 | } |
298 | 315 | ||