diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-05 00:35:40 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-12-06 10:46:38 -0500 |
commit | 200baa2112012dd8a13db9da3ee6885403f9c013 (patch) | |
tree | 261f9c2b85927c2dfaaecfb7ab808d353bd84da4 /fs/nfs | |
parent | e21195a740533348e77efa8a2e2cf03bb4092b2b (diff) |
NFS: Remove nfs_writepage_sync()
Maintaining two parallel ways of doing synchronous writes is rather
pointless. This patch gets rid of the legacy nfs_writepage_sync(), and
replaces it with the faster asynchronous writes.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/file.c | 6 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 47 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 85 | ||||
-rw-r--r-- | fs/nfs/proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/write.c | 100 |
5 files changed, 10 insertions, 256 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d6ee60fc3ba6..143a19037ce8 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -378,6 +378,12 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
378 | 378 | ||
379 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | 379 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); |
380 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); | 380 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); |
381 | /* Return error values for O_SYNC and IS_SYNC() */ | ||
382 | if (result >= 0 && (IS_SYNC(inode) || (iocb->ki_filp->f_flags & O_SYNC))) { | ||
383 | int err = nfs_fsync(iocb->ki_filp, dentry, 1); | ||
384 | if (err < 0) | ||
385 | result = err; | ||
386 | } | ||
381 | out: | 387 | out: |
382 | return result; | 388 | return result; |
383 | 389 | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 7fba06306b82..510ae524f3fd 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -276,51 +276,6 @@ static int nfs3_proc_read(struct nfs_read_data *rdata) | |||
276 | return status; | 276 | return status; |
277 | } | 277 | } |
278 | 278 | ||
279 | static int nfs3_proc_write(struct nfs_write_data *wdata) | ||
280 | { | ||
281 | int rpcflags = wdata->flags; | ||
282 | struct inode * inode = wdata->inode; | ||
283 | struct nfs_fattr * fattr = wdata->res.fattr; | ||
284 | struct rpc_message msg = { | ||
285 | .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], | ||
286 | .rpc_argp = &wdata->args, | ||
287 | .rpc_resp = &wdata->res, | ||
288 | .rpc_cred = wdata->cred, | ||
289 | }; | ||
290 | int status; | ||
291 | |||
292 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | ||
293 | (long long) wdata->args.offset); | ||
294 | nfs_fattr_init(fattr); | ||
295 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); | ||
296 | if (status >= 0) | ||
297 | nfs_post_op_update_inode(inode, fattr); | ||
298 | dprintk("NFS reply write: %d\n", status); | ||
299 | return status < 0? status : wdata->res.count; | ||
300 | } | ||
301 | |||
302 | static int nfs3_proc_commit(struct nfs_write_data *cdata) | ||
303 | { | ||
304 | struct inode * inode = cdata->inode; | ||
305 | struct nfs_fattr * fattr = cdata->res.fattr; | ||
306 | struct rpc_message msg = { | ||
307 | .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], | ||
308 | .rpc_argp = &cdata->args, | ||
309 | .rpc_resp = &cdata->res, | ||
310 | .rpc_cred = cdata->cred, | ||
311 | }; | ||
312 | int status; | ||
313 | |||
314 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | ||
315 | (long long) cdata->args.offset); | ||
316 | nfs_fattr_init(fattr); | ||
317 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | ||
318 | if (status >= 0) | ||
319 | nfs_post_op_update_inode(inode, fattr); | ||
320 | dprintk("NFS reply commit: %d\n", status); | ||
321 | return status; | ||
322 | } | ||
323 | |||
324 | /* | 279 | /* |
325 | * Create a regular file. | 280 | * Create a regular file. |
326 | * For now, we don't implement O_EXCL. | 281 | * For now, we don't implement O_EXCL. |
@@ -901,8 +856,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
901 | .access = nfs3_proc_access, | 856 | .access = nfs3_proc_access, |
902 | .readlink = nfs3_proc_readlink, | 857 | .readlink = nfs3_proc_readlink, |
903 | .read = nfs3_proc_read, | 858 | .read = nfs3_proc_read, |
904 | .write = nfs3_proc_write, | ||
905 | .commit = nfs3_proc_commit, | ||
906 | .create = nfs3_proc_create, | 859 | .create = nfs3_proc_create, |
907 | .remove = nfs3_proc_remove, | 860 | .remove = nfs3_proc_remove, |
908 | .unlink_setup = nfs3_proc_unlink_setup, | 861 | .unlink_setup = nfs3_proc_unlink_setup, |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4b5fc714d786..ee458aeab24a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1775,89 +1775,6 @@ static int nfs4_proc_read(struct nfs_read_data *rdata) | |||
1775 | return err; | 1775 | return err; |
1776 | } | 1776 | } |
1777 | 1777 | ||
1778 | static int _nfs4_proc_write(struct nfs_write_data *wdata) | ||
1779 | { | ||
1780 | int rpcflags = wdata->flags; | ||
1781 | struct inode *inode = wdata->inode; | ||
1782 | struct nfs_fattr *fattr = wdata->res.fattr; | ||
1783 | struct nfs_server *server = NFS_SERVER(inode); | ||
1784 | struct rpc_message msg = { | ||
1785 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], | ||
1786 | .rpc_argp = &wdata->args, | ||
1787 | .rpc_resp = &wdata->res, | ||
1788 | .rpc_cred = wdata->cred, | ||
1789 | }; | ||
1790 | int status; | ||
1791 | |||
1792 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | ||
1793 | (long long) wdata->args.offset); | ||
1794 | |||
1795 | wdata->args.bitmask = server->attr_bitmask; | ||
1796 | wdata->res.server = server; | ||
1797 | wdata->timestamp = jiffies; | ||
1798 | nfs_fattr_init(fattr); | ||
1799 | status = rpc_call_sync(server->client, &msg, rpcflags); | ||
1800 | dprintk("NFS reply write: %d\n", status); | ||
1801 | if (status < 0) | ||
1802 | return status; | ||
1803 | renew_lease(server, wdata->timestamp); | ||
1804 | nfs_post_op_update_inode(inode, fattr); | ||
1805 | return wdata->res.count; | ||
1806 | } | ||
1807 | |||
1808 | static int nfs4_proc_write(struct nfs_write_data *wdata) | ||
1809 | { | ||
1810 | struct nfs4_exception exception = { }; | ||
1811 | int err; | ||
1812 | do { | ||
1813 | err = nfs4_handle_exception(NFS_SERVER(wdata->inode), | ||
1814 | _nfs4_proc_write(wdata), | ||
1815 | &exception); | ||
1816 | } while (exception.retry); | ||
1817 | return err; | ||
1818 | } | ||
1819 | |||
1820 | static int _nfs4_proc_commit(struct nfs_write_data *cdata) | ||
1821 | { | ||
1822 | struct inode *inode = cdata->inode; | ||
1823 | struct nfs_fattr *fattr = cdata->res.fattr; | ||
1824 | struct nfs_server *server = NFS_SERVER(inode); | ||
1825 | struct rpc_message msg = { | ||
1826 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], | ||
1827 | .rpc_argp = &cdata->args, | ||
1828 | .rpc_resp = &cdata->res, | ||
1829 | .rpc_cred = cdata->cred, | ||
1830 | }; | ||
1831 | int status; | ||
1832 | |||
1833 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | ||
1834 | (long long) cdata->args.offset); | ||
1835 | |||
1836 | cdata->args.bitmask = server->attr_bitmask; | ||
1837 | cdata->res.server = server; | ||
1838 | cdata->timestamp = jiffies; | ||
1839 | nfs_fattr_init(fattr); | ||
1840 | status = rpc_call_sync(server->client, &msg, 0); | ||
1841 | if (status >= 0) | ||
1842 | renew_lease(server, cdata->timestamp); | ||
1843 | dprintk("NFS reply commit: %d\n", status); | ||
1844 | if (status >= 0) | ||
1845 | nfs_post_op_update_inode(inode, fattr); | ||
1846 | return status; | ||
1847 | } | ||
1848 | |||
1849 | static int nfs4_proc_commit(struct nfs_write_data *cdata) | ||
1850 | { | ||
1851 | struct nfs4_exception exception = { }; | ||
1852 | int err; | ||
1853 | do { | ||
1854 | err = nfs4_handle_exception(NFS_SERVER(cdata->inode), | ||
1855 | _nfs4_proc_commit(cdata), | ||
1856 | &exception); | ||
1857 | } while (exception.retry); | ||
1858 | return err; | ||
1859 | } | ||
1860 | |||
1861 | /* | 1778 | /* |
1862 | * Got race? | 1779 | * Got race? |
1863 | * We will need to arrange for the VFS layer to provide an atomic open. | 1780 | * We will need to arrange for the VFS layer to provide an atomic open. |
@@ -3730,8 +3647,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
3730 | .access = nfs4_proc_access, | 3647 | .access = nfs4_proc_access, |
3731 | .readlink = nfs4_proc_readlink, | 3648 | .readlink = nfs4_proc_readlink, |
3732 | .read = nfs4_proc_read, | 3649 | .read = nfs4_proc_read, |
3733 | .write = nfs4_proc_write, | ||
3734 | .commit = nfs4_proc_commit, | ||
3735 | .create = nfs4_proc_create, | 3650 | .create = nfs4_proc_create, |
3736 | .remove = nfs4_proc_remove, | 3651 | .remove = nfs4_proc_remove, |
3737 | .unlink_setup = nfs4_proc_unlink_setup, | 3652 | .unlink_setup = nfs4_proc_unlink_setup, |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 7a9013dd5d0a..10f5e80ca157 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -215,32 +215,6 @@ static int nfs_proc_read(struct nfs_read_data *rdata) | |||
215 | return status; | 215 | return status; |
216 | } | 216 | } |
217 | 217 | ||
218 | static int nfs_proc_write(struct nfs_write_data *wdata) | ||
219 | { | ||
220 | int flags = wdata->flags; | ||
221 | struct inode * inode = wdata->inode; | ||
222 | struct nfs_fattr * fattr = wdata->res.fattr; | ||
223 | struct rpc_message msg = { | ||
224 | .rpc_proc = &nfs_procedures[NFSPROC_WRITE], | ||
225 | .rpc_argp = &wdata->args, | ||
226 | .rpc_resp = &wdata->res, | ||
227 | .rpc_cred = wdata->cred, | ||
228 | }; | ||
229 | int status; | ||
230 | |||
231 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | ||
232 | (long long) wdata->args.offset); | ||
233 | nfs_fattr_init(fattr); | ||
234 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | ||
235 | if (status >= 0) { | ||
236 | nfs_post_op_update_inode(inode, fattr); | ||
237 | wdata->res.count = wdata->args.count; | ||
238 | wdata->verf.committed = NFS_FILE_SYNC; | ||
239 | } | ||
240 | dprintk("NFS reply write: %d\n", status); | ||
241 | return status < 0? status : wdata->res.count; | ||
242 | } | ||
243 | |||
244 | static int | 218 | static int |
245 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 219 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
246 | int flags, struct nameidata *nd) | 220 | int flags, struct nameidata *nd) |
@@ -693,8 +667,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = { | |||
693 | .access = NULL, /* access */ | 667 | .access = NULL, /* access */ |
694 | .readlink = nfs_proc_readlink, | 668 | .readlink = nfs_proc_readlink, |
695 | .read = nfs_proc_read, | 669 | .read = nfs_proc_read, |
696 | .write = nfs_proc_write, | ||
697 | .commit = NULL, /* commit */ | ||
698 | .create = nfs_proc_create, | 670 | .create = nfs_proc_create, |
699 | .remove = nfs_proc_remove, | 671 | .remove = nfs_proc_remove, |
700 | .unlink_setup = nfs_proc_unlink_setup, | 672 | .unlink_setup = nfs_proc_unlink_setup, |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index de9a16a8f7e4..f0720b544b12 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -210,78 +210,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int | |||
210 | SetPageUptodate(page); | 210 | SetPageUptodate(page); |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | ||
214 | * Write a page synchronously. | ||
215 | * Offset is the data offset within the page. | ||
216 | */ | ||
217 | static int nfs_writepage_sync(struct nfs_open_context *ctx, struct page *page, | ||
218 | unsigned int offset, unsigned int count, int how) | ||
219 | { | ||
220 | struct inode *inode = page->mapping->host; | ||
221 | unsigned int wsize = NFS_SERVER(inode)->wsize; | ||
222 | int result, written = 0; | ||
223 | struct nfs_write_data *wdata; | ||
224 | |||
225 | wdata = nfs_writedata_alloc(wsize); | ||
226 | if (!wdata) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | wdata->flags = how; | ||
230 | wdata->cred = ctx->cred; | ||
231 | wdata->inode = inode; | ||
232 | wdata->args.fh = NFS_FH(inode); | ||
233 | wdata->args.context = ctx; | ||
234 | wdata->args.pages = &page; | ||
235 | wdata->args.stable = NFS_FILE_SYNC; | ||
236 | wdata->args.pgbase = offset; | ||
237 | wdata->args.count = wsize; | ||
238 | wdata->res.fattr = &wdata->fattr; | ||
239 | wdata->res.verf = &wdata->verf; | ||
240 | |||
241 | dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n", | ||
242 | inode->i_sb->s_id, | ||
243 | (long long)NFS_FILEID(inode), | ||
244 | count, (long long)(page_offset(page) + offset)); | ||
245 | |||
246 | set_page_writeback(page); | ||
247 | nfs_begin_data_update(inode); | ||
248 | do { | ||
249 | if (count < wsize) | ||
250 | wdata->args.count = count; | ||
251 | wdata->args.offset = page_offset(page) + wdata->args.pgbase; | ||
252 | |||
253 | result = NFS_PROTO(inode)->write(wdata); | ||
254 | |||
255 | if (result < 0) { | ||
256 | /* Must mark the page invalid after I/O error */ | ||
257 | ClearPageUptodate(page); | ||
258 | goto io_error; | ||
259 | } | ||
260 | if (result < wdata->args.count) | ||
261 | printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n", | ||
262 | wdata->args.count, result); | ||
263 | |||
264 | wdata->args.offset += result; | ||
265 | wdata->args.pgbase += result; | ||
266 | written += result; | ||
267 | count -= result; | ||
268 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result); | ||
269 | } while (count); | ||
270 | /* Update file length */ | ||
271 | nfs_grow_file(page, offset, written); | ||
272 | /* Set the PG_uptodate flag? */ | ||
273 | nfs_mark_uptodate(page, offset, written); | ||
274 | |||
275 | if (PageError(page)) | ||
276 | ClearPageError(page); | ||
277 | |||
278 | io_error: | ||
279 | nfs_end_data_update(inode); | ||
280 | end_page_writeback(page); | ||
281 | nfs_writedata_release(wdata); | ||
282 | return written ? written : result; | ||
283 | } | ||
284 | |||
285 | static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | 213 | static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, |
286 | unsigned int offset, unsigned int count) | 214 | unsigned int offset, unsigned int count) |
287 | { | 215 | { |
@@ -342,22 +270,12 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) | |||
342 | err = -EBADF; | 270 | err = -EBADF; |
343 | goto out; | 271 | goto out; |
344 | } | 272 | } |
345 | lock_kernel(); | 273 | err = nfs_writepage_setup(ctx, page, 0, offset); |
346 | if (!IS_SYNC(inode)) { | ||
347 | err = nfs_writepage_setup(ctx, page, 0, offset); | ||
348 | if (!wbc->for_writepages) | ||
349 | nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc)); | ||
350 | } else { | ||
351 | err = nfs_writepage_sync(ctx, page, 0, offset, wb_priority(wbc)); | ||
352 | if (err >= 0) { | ||
353 | if (err != offset) | ||
354 | redirty_page_for_writepage(wbc, page); | ||
355 | err = 0; | ||
356 | } | ||
357 | } | ||
358 | unlock_kernel(); | ||
359 | put_nfs_open_context(ctx); | 274 | put_nfs_open_context(ctx); |
275 | |||
360 | out: | 276 | out: |
277 | if (!wbc->for_writepages) | ||
278 | nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc)); | ||
361 | unlock_page(page); | 279 | unlock_page(page); |
362 | return err; | 280 | return err; |
363 | } | 281 | } |
@@ -777,16 +695,6 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
777 | file->f_dentry->d_name.name, count, | 695 | file->f_dentry->d_name.name, count, |
778 | (long long)(page_offset(page) +offset)); | 696 | (long long)(page_offset(page) +offset)); |
779 | 697 | ||
780 | if (IS_SYNC(inode)) { | ||
781 | status = nfs_writepage_sync(ctx, page, offset, count, 0); | ||
782 | if (status > 0) { | ||
783 | if (offset == 0 && status == PAGE_CACHE_SIZE) | ||
784 | SetPageUptodate(page); | ||
785 | return 0; | ||
786 | } | ||
787 | return status; | ||
788 | } | ||
789 | |||
790 | /* If we're not using byte range locks, and we know the page | 698 | /* If we're not using byte range locks, and we know the page |
791 | * is entirely in cache, it may be more efficient to avoid | 699 | * is entirely in cache, it may be more efficient to avoid |
792 | * fragmenting write requests. | 700 | * fragmenting write requests. |