diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2006-01-08 04:02:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:13:47 -0500 |
commit | 28fd129827b00e12829d48a5290f46277600619b (patch) | |
tree | 38e50e1b88965fec41ea5b36aa557fb5c2b1ca73 | |
parent | 05eb0b51fb46430050d5873458612f53e0234f2e (diff) |
[PATCH] Fix and add EXPORT_SYMBOL(filemap_write_and_wait)
This patch add EXPORT_SYMBOL(filemap_write_and_wait) and use it.
See mm/filemap.c:
And changes the filemap_write_and_wait() and filemap_write_and_wait_range().
Current filemap_write_and_wait() doesn't wait if filemap_fdatawrite()
returns error. However, even if filemap_fdatawrite() returned an
error, it may have submitted the partially data pages to the device.
(e.g. in the case of -ENOSPC)
<quotation>
Andrew Morton writes,
If filemap_fdatawrite() returns an error, this might be due to some
I/O problem: dead disk, unplugged cable, etc. Given the generally
crappy quality of the kernel's handling of such exceptions, there's a
good chance that the filemap_fdatawait() will get stuck in D state
forever.
</quotation>
So, this patch doesn't wait if filemap_fdatawrite() returns the -EIO.
Trond, could you please review the nfs part? Especially I'm not sure,
nfs must use the "filemap_fdatawrite(inode->i_mapping) == 0", or not.
Acked-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/9p/vfs_dir.c | 3 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 3 | ||||
-rw-r--r-- | fs/buffer.c | 10 | ||||
-rw-r--r-- | fs/cifs/file.c | 6 | ||||
-rw-r--r-- | fs/cifs/inode.c | 3 | ||||
-rw-r--r-- | fs/jfs/jfs_dmap.c | 3 | ||||
-rw-r--r-- | fs/jfs/jfs_imap.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_txnmgr.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_umount.c | 6 | ||||
-rw-r--r-- | fs/jfs/resize.c | 3 | ||||
-rw-r--r-- | fs/jfs/super.c | 3 | ||||
-rw-r--r-- | fs/nfs/inode.c | 8 | ||||
-rw-r--r-- | fs/smbfs/file.c | 3 | ||||
-rw-r--r-- | fs/smbfs/inode.c | 3 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_fs_subr.c | 3 | ||||
-rw-r--r-- | mm/filemap.c | 40 |
16 files changed, 48 insertions, 61 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 57a43b8feef5..17089d1905ff 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -193,8 +193,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
193 | fid->fid); | 193 | fid->fid); |
194 | fidnum = fid->fid; | 194 | fidnum = fid->fid; |
195 | 195 | ||
196 | filemap_fdatawrite(inode->i_mapping); | 196 | filemap_write_and_wait(inode->i_mapping); |
197 | filemap_fdatawait(inode->i_mapping); | ||
198 | 197 | ||
199 | if (fidnum >= 0) { | 198 | if (fidnum >= 0) { |
200 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, | 199 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 89c849da8504..e13577da9130 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -165,8 +165,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
165 | return -ENOLCK; | 165 | return -ENOLCK; |
166 | 166 | ||
167 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { | 167 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { |
168 | filemap_fdatawrite(inode->i_mapping); | 168 | filemap_write_and_wait(inode->i_mapping); |
169 | filemap_fdatawait(inode->i_mapping); | ||
170 | invalidate_inode_pages(&inode->i_data); | 169 | invalidate_inode_pages(&inode->i_data); |
171 | } | 170 | } |
172 | 171 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 55023231e460..263df0f192aa 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -153,14 +153,8 @@ int sync_blockdev(struct block_device *bdev) | |||
153 | { | 153 | { |
154 | int ret = 0; | 154 | int ret = 0; |
155 | 155 | ||
156 | if (bdev) { | 156 | if (bdev) |
157 | int err; | 157 | ret = filemap_write_and_wait(bdev->bd_inode->i_mapping); |
158 | |||
159 | ret = filemap_fdatawrite(bdev->bd_inode->i_mapping); | ||
160 | err = filemap_fdatawait(bdev->bd_inode->i_mapping); | ||
161 | if (!ret) | ||
162 | ret = err; | ||
163 | } | ||
164 | return ret; | 158 | return ret; |
165 | } | 159 | } |
166 | EXPORT_SYMBOL(sync_blockdev); | 160 | EXPORT_SYMBOL(sync_blockdev); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 14a1c72ced92..5ade53d7bca8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -127,8 +127,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
127 | if (file->f_dentry->d_inode->i_mapping) { | 127 | if (file->f_dentry->d_inode->i_mapping) { |
128 | /* BB no need to lock inode until after invalidate | 128 | /* BB no need to lock inode until after invalidate |
129 | since namei code should already have it locked? */ | 129 | since namei code should already have it locked? */ |
130 | filemap_fdatawrite(file->f_dentry->d_inode->i_mapping); | 130 | filemap_write_and_wait(file->f_dentry->d_inode->i_mapping); |
131 | filemap_fdatawait(file->f_dentry->d_inode->i_mapping); | ||
132 | } | 131 | } |
133 | cFYI(1, ("invalidating remote inode since open detected it " | 132 | cFYI(1, ("invalidating remote inode since open detected it " |
134 | "changed")); | 133 | "changed")); |
@@ -419,8 +418,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, | |||
419 | pCifsInode = CIFS_I(inode); | 418 | pCifsInode = CIFS_I(inode); |
420 | if (pCifsInode) { | 419 | if (pCifsInode) { |
421 | if (can_flush) { | 420 | if (can_flush) { |
422 | filemap_fdatawrite(inode->i_mapping); | 421 | filemap_write_and_wait(inode->i_mapping); |
423 | filemap_fdatawait(inode->i_mapping); | ||
424 | /* temporarily disable caching while we | 422 | /* temporarily disable caching while we |
425 | go to server to get inode info */ | 423 | go to server to get inode info */ |
426 | pCifsInode->clientCanCacheAll = FALSE; | 424 | pCifsInode->clientCanCacheAll = FALSE; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 411c1f7f84da..9558f51bca55 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1148,8 +1148,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1148 | /* BB check if we need to refresh inode from server now ? BB */ | 1148 | /* BB check if we need to refresh inode from server now ? BB */ |
1149 | 1149 | ||
1150 | /* need to flush data before changing file size on server */ | 1150 | /* need to flush data before changing file size on server */ |
1151 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1151 | filemap_write_and_wait(direntry->d_inode->i_mapping); |
1152 | filemap_fdatawait(direntry->d_inode->i_mapping); | ||
1153 | 1152 | ||
1154 | if (attrs->ia_valid & ATTR_SIZE) { | 1153 | if (attrs->ia_valid & ATTR_SIZE) { |
1155 | /* To avoid spurious oplock breaks from server, in the case of | 1154 | /* To avoid spurious oplock breaks from server, in the case of |
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 68000a50ceb6..2967b7393415 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c | |||
@@ -302,8 +302,7 @@ int dbSync(struct inode *ipbmap) | |||
302 | /* | 302 | /* |
303 | * write out dirty pages of bmap | 303 | * write out dirty pages of bmap |
304 | */ | 304 | */ |
305 | filemap_fdatawrite(ipbmap->i_mapping); | 305 | filemap_write_and_wait(ipbmap->i_mapping); |
306 | filemap_fdatawait(ipbmap->i_mapping); | ||
307 | 306 | ||
308 | diWriteSpecial(ipbmap, 0); | 307 | diWriteSpecial(ipbmap, 0); |
309 | 308 | ||
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 28201b194f53..31b4aa13dd4b 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c | |||
@@ -265,8 +265,7 @@ int diSync(struct inode *ipimap) | |||
265 | /* | 265 | /* |
266 | * write out dirty pages of imap | 266 | * write out dirty pages of imap |
267 | */ | 267 | */ |
268 | filemap_fdatawrite(ipimap->i_mapping); | 268 | filemap_write_and_wait(ipimap->i_mapping); |
269 | filemap_fdatawait(ipimap->i_mapping); | ||
270 | 269 | ||
271 | diWriteSpecial(ipimap, 0); | 270 | diWriteSpecial(ipimap, 0); |
272 | 271 | ||
@@ -565,8 +564,7 @@ void diFreeSpecial(struct inode *ip) | |||
565 | jfs_err("diFreeSpecial called with NULL ip!"); | 564 | jfs_err("diFreeSpecial called with NULL ip!"); |
566 | return; | 565 | return; |
567 | } | 566 | } |
568 | filemap_fdatawrite(ip->i_mapping); | 567 | filemap_write_and_wait(ip->i_mapping); |
569 | filemap_fdatawait(ip->i_mapping); | ||
570 | truncate_inode_pages(ip->i_mapping, 0); | 568 | truncate_inode_pages(ip->i_mapping, 0); |
571 | iput(ip); | 569 | iput(ip); |
572 | } | 570 | } |
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index b660c93c92de..2ddb6b892bcf 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c | |||
@@ -1231,10 +1231,8 @@ int txCommit(tid_t tid, /* transaction identifier */ | |||
1231 | * when we don't need to worry about it at all. | 1231 | * when we don't need to worry about it at all. |
1232 | * | 1232 | * |
1233 | * if ((!S_ISDIR(ip->i_mode)) | 1233 | * if ((!S_ISDIR(ip->i_mode)) |
1234 | * && (tblk->flag & COMMIT_DELETE) == 0) { | 1234 | * && (tblk->flag & COMMIT_DELETE) == 0) |
1235 | * filemap_fdatawrite(ip->i_mapping); | 1235 | * filemap_write_and_wait(ip->i_mapping); |
1236 | * filemap_fdatawait(ip->i_mapping); | ||
1237 | * } | ||
1238 | */ | 1236 | */ |
1239 | 1237 | ||
1240 | /* | 1238 | /* |
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c index 5cf91785b541..21eaf7ac0fcb 100644 --- a/fs/jfs/jfs_umount.c +++ b/fs/jfs/jfs_umount.c | |||
@@ -108,8 +108,7 @@ int jfs_umount(struct super_block *sb) | |||
108 | * Make sure all metadata makes it to disk before we mark | 108 | * Make sure all metadata makes it to disk before we mark |
109 | * the superblock as clean | 109 | * the superblock as clean |
110 | */ | 110 | */ |
111 | filemap_fdatawrite(sbi->direct_inode->i_mapping); | 111 | filemap_write_and_wait(sbi->direct_inode->i_mapping); |
112 | filemap_fdatawait(sbi->direct_inode->i_mapping); | ||
113 | 112 | ||
114 | /* | 113 | /* |
115 | * ensure all file system file pages are propagated to their | 114 | * ensure all file system file pages are propagated to their |
@@ -161,8 +160,7 @@ int jfs_umount_rw(struct super_block *sb) | |||
161 | * mark the superblock clean before everything is flushed to | 160 | * mark the superblock clean before everything is flushed to |
162 | * disk. | 161 | * disk. |
163 | */ | 162 | */ |
164 | filemap_fdatawrite(sbi->direct_inode->i_mapping); | 163 | filemap_write_and_wait(sbi->direct_inode->i_mapping); |
165 | filemap_fdatawait(sbi->direct_inode->i_mapping); | ||
166 | 164 | ||
167 | updateSuper(sb, FM_CLEAN); | 165 | updateSuper(sb, FM_CLEAN); |
168 | 166 | ||
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index c6dc254d3253..45180361871c 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c | |||
@@ -376,8 +376,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
376 | * by txCommit(); | 376 | * by txCommit(); |
377 | */ | 377 | */ |
378 | filemap_fdatawait(ipbmap->i_mapping); | 378 | filemap_fdatawait(ipbmap->i_mapping); |
379 | filemap_fdatawrite(ipbmap->i_mapping); | 379 | filemap_write_and_wait(ipbmap->i_mapping); |
380 | filemap_fdatawait(ipbmap->i_mapping); | ||
381 | diWriteSpecial(ipbmap, 0); | 380 | diWriteSpecial(ipbmap, 0); |
382 | 381 | ||
383 | newPage = nPages; /* first new page number */ | 382 | newPage = nPages; /* first new page number */ |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 4226af3ea91b..8d31f1336431 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -502,8 +502,7 @@ out_no_rw: | |||
502 | jfs_err("jfs_umount failed with return code %d", rc); | 502 | jfs_err("jfs_umount failed with return code %d", rc); |
503 | } | 503 | } |
504 | out_mount_failed: | 504 | out_mount_failed: |
505 | filemap_fdatawrite(sbi->direct_inode->i_mapping); | 505 | filemap_write_and_wait(sbi->direct_inode->i_mapping); |
506 | filemap_fdatawait(sbi->direct_inode->i_mapping); | ||
507 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); | 506 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); |
508 | make_bad_inode(sbi->direct_inode); | 507 | make_bad_inode(sbi->direct_inode); |
509 | iput(sbi->direct_inode); | 508 | iput(sbi->direct_inode); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e7bd0d92600f..3e4ba9cb7f80 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -644,10 +644,7 @@ int nfs_sync_mapping(struct address_space *mapping) | |||
644 | if (mapping->nrpages == 0) | 644 | if (mapping->nrpages == 0) |
645 | return 0; | 645 | return 0; |
646 | unmap_mapping_range(mapping, 0, 0, 0); | 646 | unmap_mapping_range(mapping, 0, 0, 0); |
647 | ret = filemap_fdatawrite(mapping); | 647 | ret = filemap_write_and_wait(mapping); |
648 | if (ret != 0) | ||
649 | goto out; | ||
650 | ret = filemap_fdatawait(mapping); | ||
651 | if (ret != 0) | 648 | if (ret != 0) |
652 | goto out; | 649 | goto out; |
653 | ret = nfs_wb_all(mapping->host); | 650 | ret = nfs_wb_all(mapping->host); |
@@ -864,8 +861,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
864 | nfs_begin_data_update(inode); | 861 | nfs_begin_data_update(inode); |
865 | /* Write all dirty data if we're changing file permissions or size */ | 862 | /* Write all dirty data if we're changing file permissions or size */ |
866 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) { | 863 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) { |
867 | if (filemap_fdatawrite(inode->i_mapping) == 0) | 864 | filemap_write_and_wait(inode->i_mapping); |
868 | filemap_fdatawait(inode->i_mapping); | ||
869 | nfs_wb_all(inode); | 865 | nfs_wb_all(inode); |
870 | } | 866 | } |
871 | /* | 867 | /* |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index b4fcfa8b55a1..3c6eb3ba718e 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -374,8 +374,7 @@ smb_file_release(struct inode *inode, struct file * file) | |||
374 | /* We must flush any dirty pages now as we won't be able to | 374 | /* We must flush any dirty pages now as we won't be able to |
375 | write anything after close. mmap can trigger this. | 375 | write anything after close. mmap can trigger this. |
376 | "openers" should perhaps include mmap'ers ... */ | 376 | "openers" should perhaps include mmap'ers ... */ |
377 | filemap_fdatawrite(inode->i_mapping); | 377 | filemap_write_and_wait(inode->i_mapping); |
378 | filemap_fdatawait(inode->i_mapping); | ||
379 | smb_close(inode); | 378 | smb_close(inode); |
380 | } | 379 | } |
381 | unlock_kernel(); | 380 | unlock_kernel(); |
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 10b994428fef..6ec88bf59b2d 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c | |||
@@ -697,8 +697,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr) | |||
697 | DENTRY_PATH(dentry), | 697 | DENTRY_PATH(dentry), |
698 | (long) inode->i_size, (long) attr->ia_size); | 698 | (long) inode->i_size, (long) attr->ia_size); |
699 | 699 | ||
700 | filemap_fdatawrite(inode->i_mapping); | 700 | filemap_write_and_wait(inode->i_mapping); |
701 | filemap_fdatawait(inode->i_mapping); | ||
702 | 701 | ||
703 | error = smb_open(dentry, O_WRONLY); | 702 | error = smb_open(dentry, O_WRONLY); |
704 | if (error) | 703 | if (error) |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index f89340c61bf2..4fa4b1a5187e 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c | |||
@@ -79,8 +79,7 @@ fs_flushinval_pages( | |||
79 | struct inode *ip = LINVFS_GET_IP(vp); | 79 | struct inode *ip = LINVFS_GET_IP(vp); |
80 | 80 | ||
81 | if (VN_CACHED(vp)) { | 81 | if (VN_CACHED(vp)) { |
82 | filemap_fdatawrite(ip->i_mapping); | 82 | filemap_write_and_wait(ip->i_mapping); |
83 | filemap_fdatawait(ip->i_mapping); | ||
84 | 83 | ||
85 | truncate_inode_pages(ip->i_mapping, first); | 84 | truncate_inode_pages(ip->i_mapping, first); |
86 | } | 85 | } |
diff --git a/mm/filemap.c b/mm/filemap.c index 8fdf36508023..478f4c74cc31 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -343,30 +343,44 @@ EXPORT_SYMBOL(filemap_fdatawait); | |||
343 | 343 | ||
344 | int filemap_write_and_wait(struct address_space *mapping) | 344 | int filemap_write_and_wait(struct address_space *mapping) |
345 | { | 345 | { |
346 | int retval = 0; | 346 | int err = 0; |
347 | 347 | ||
348 | if (mapping->nrpages) { | 348 | if (mapping->nrpages) { |
349 | retval = filemap_fdatawrite(mapping); | 349 | err = filemap_fdatawrite(mapping); |
350 | if (retval == 0) | 350 | /* |
351 | retval = filemap_fdatawait(mapping); | 351 | * Even if the above returned error, the pages may be |
352 | * written partially (e.g. -ENOSPC), so we wait for it. | ||
353 | * But the -EIO is special case, it may indicate the worst | ||
354 | * thing (e.g. bug) happened, so we avoid waiting for it. | ||
355 | */ | ||
356 | if (err != -EIO) { | ||
357 | int err2 = filemap_fdatawait(mapping); | ||
358 | if (!err) | ||
359 | err = err2; | ||
360 | } | ||
352 | } | 361 | } |
353 | return retval; | 362 | return err; |
354 | } | 363 | } |
364 | EXPORT_SYMBOL(filemap_write_and_wait); | ||
355 | 365 | ||
356 | int filemap_write_and_wait_range(struct address_space *mapping, | 366 | int filemap_write_and_wait_range(struct address_space *mapping, |
357 | loff_t lstart, loff_t lend) | 367 | loff_t lstart, loff_t lend) |
358 | { | 368 | { |
359 | int retval = 0; | 369 | int err = 0; |
360 | 370 | ||
361 | if (mapping->nrpages) { | 371 | if (mapping->nrpages) { |
362 | retval = __filemap_fdatawrite_range(mapping, lstart, lend, | 372 | err = __filemap_fdatawrite_range(mapping, lstart, lend, |
363 | WB_SYNC_ALL); | 373 | WB_SYNC_ALL); |
364 | if (retval == 0) | 374 | /* See comment of filemap_write_and_wait() */ |
365 | retval = wait_on_page_writeback_range(mapping, | 375 | if (err != -EIO) { |
366 | lstart >> PAGE_CACHE_SHIFT, | 376 | int err2 = wait_on_page_writeback_range(mapping, |
367 | lend >> PAGE_CACHE_SHIFT); | 377 | lstart >> PAGE_CACHE_SHIFT, |
378 | lend >> PAGE_CACHE_SHIFT); | ||
379 | if (!err) | ||
380 | err = err2; | ||
381 | } | ||
368 | } | 382 | } |
369 | return retval; | 383 | return err; |
370 | } | 384 | } |
371 | 385 | ||
372 | /* | 386 | /* |