afs: don't SetPageError() if afs_readpage is interrupted by a signal
Subsystems (2)
PATCH 1/1 afs: don't SetPageError() if afs_readpage is interrupted by a signal
Hi David,
while browsing with mc (midnight commander) my AFS filesystem, i've been seeing a lot of empty directories (which aren't empty on the server, of course). After looking into the code, i recognized that the afs_wait_for_call_to_complete() function was interrupted because mc has received a signal before the response from the fileserver arrived, and returned with -EINTR.
That would be not a big problem, as the system call may be restarted, but this doesn't work in this case because the page is marked as error in the page cache, and so even the retry returns with -EIO.
I've changed the code with the attached patch, which works for me. As i have not much insight in the filesystem code, is this a correct fix? If not, how would a proper solution look like?
Thanks,
Sven.
If a signal is delivered to a process who is reading data from AFS, the Pagecache Entry is marked with error - so even if the process retries the operation after finishing signal handling, it will fail. So we should only mark the page with error if there was an error on the remote side. also change EINTR to ERESTARTSYS, so the system call will be restarted.
--- fs/afs/file.c | 3 +++ fs/afs/rxrpc.c | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-)
fs/afs/file.c +0 -0
@@ -201,6 +201,8 @@ static int afs_readpage(struct file *file, struct
page *page)
#ifdef AFS_CACHING_SUPPORT
cachefs_uncache_page(vnode->cache, page);
#endif
+ if (ret == -ERESTARTSYS)
+ goto error_restart;
goto error;
} @@ -226,6 +228,7 @@ static int afs_readpage(struct file *file, struct page *page)
error:
SetPageError(page);
+error_restart:
unlock_page(page);
_leave(" = %d", ret);
return ret;fs/afs/rxrpc.c +1 -1
@@ -541,7 +541,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call) ret = call->error;if (call->state >=AFS_CALL_COMPLETE )break ; - ret = -EINTR ; + ret = -ERESTARTSYS ;if (signal_pending (current))break ;
schedule();
Signature · 1 line
1.5.5.3