Skip to content

Commit 865ffef

Browse files
Dmitry Monakhovtorvalds
authored andcommitted
fs: fix fsync() error reporting
There are two convenient ways to report errors to userspace 1) retun error to original syscall for example write(2) 2) mark mapping with error flag and return it on later fsync(2) Second one is broken if (mapping->nrpages == 0) This is real-life situation because after error pages are likey to be truncated or invalidated. We have to return an error regardless to number of pages in the mapping. #Original testcase: [email protected]:dmonakhov/xfstests.git MOUNT_OPTIONS="-b1024" ./check shared/305 Signed-off-by: Dmitry Monakhov <[email protected]> Reviewed-by: Jan Kara <[email protected]> Cc: Al Viro <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 209ff86 commit 865ffef

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

mm/filemap.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@ static int sleep_on_page_killable(void *word)
188188
return fatal_signal_pending(current) ? -EINTR : 0;
189189
}
190190

191+
static int filemap_check_errors(struct address_space *mapping)
192+
{
193+
int ret = 0;
194+
/* Check for outstanding write errors */
195+
if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
196+
ret = -ENOSPC;
197+
if (test_and_clear_bit(AS_EIO, &mapping->flags))
198+
ret = -EIO;
199+
return ret;
200+
}
201+
191202
/**
192203
* __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
193204
* @mapping: address space structure to write
@@ -269,10 +280,10 @@ int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
269280
pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
270281
struct pagevec pvec;
271282
int nr_pages;
272-
int ret = 0;
283+
int ret2, ret = 0;
273284

274285
if (end_byte < start_byte)
275-
return 0;
286+
goto out;
276287

277288
pagevec_init(&pvec, 0);
278289
while ((index <= end) &&
@@ -295,12 +306,10 @@ int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
295306
pagevec_release(&pvec);
296307
cond_resched();
297308
}
298-
299-
/* Check for outstanding write errors */
300-
if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
301-
ret = -ENOSPC;
302-
if (test_and_clear_bit(AS_EIO, &mapping->flags))
303-
ret = -EIO;
309+
out:
310+
ret2 = filemap_check_errors(mapping);
311+
if (!ret)
312+
ret = ret2;
304313

305314
return ret;
306315
}
@@ -341,6 +350,8 @@ int filemap_write_and_wait(struct address_space *mapping)
341350
if (!err)
342351
err = err2;
343352
}
353+
} else {
354+
err = filemap_check_errors(mapping);
344355
}
345356
return err;
346357
}
@@ -372,6 +383,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
372383
if (!err)
373384
err = err2;
374385
}
386+
} else {
387+
err = filemap_check_errors(mapping);
375388
}
376389
return err;
377390
}

0 commit comments

Comments
 (0)