diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2005-09-09 16:10:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 17:03:48 -0400 |
commit | 7c352bdf048811b8128019ffc1e886161e09c11c (patch) | |
tree | 74c48298b67d37295433d9b2bb08d590a5f97a78 /fs/fuse/file.c | |
parent | 8254798199332966e2ab647380c990193af7e854 (diff) |
[PATCH] FUSE: don't allow restarting of system calls
This patch removes ability to interrupt and restart operations while there
hasn't been any side-effect.
The reason: applications. There are some apps it seems that generate
signals at a fast rate. This means, that if the operation cannot make
enough progress between two signals, it will be restarted for ever. This
bug actually manifested itself with 'krusader' trying to open a file for
writing under sshfs. Thanks to Eduard Czimbalmos for the report.
The problem can be solved just by making open() uninterruptible, because in
this case it was the truncate operation that slowed down the progress. But
it's better to solve this by simply not allowing interrupts at all (except
SIGKILL), because applications don't expect file operations to be
interruptible anyway. As an added bonus the code is simplified somewhat.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 33 |
1 files changed, 12 insertions, 21 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e225f8c0b267..6454022b0536 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -22,9 +22,6 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
22 | struct fuse_open_out outarg; | 22 | struct fuse_open_out outarg; |
23 | struct fuse_file *ff; | 23 | struct fuse_file *ff; |
24 | int err; | 24 | int err; |
25 | /* Restarting the syscall is not allowed if O_CREAT and O_EXCL | ||
26 | are both set, because creation will fail on the restart */ | ||
27 | int excl = (file->f_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL); | ||
28 | 25 | ||
29 | err = generic_file_open(inode, file); | 26 | err = generic_file_open(inode, file); |
30 | if (err) | 27 | if (err) |
@@ -38,12 +35,9 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
38 | return err; | 35 | return err; |
39 | } | 36 | } |
40 | 37 | ||
41 | if (excl) | 38 | req = fuse_get_request(fc); |
42 | req = fuse_get_request_nonint(fc); | ||
43 | else | ||
44 | req = fuse_get_request(fc); | ||
45 | if (!req) | 39 | if (!req) |
46 | return excl ? -EINTR : -ERESTARTSYS; | 40 | return -EINTR; |
47 | 41 | ||
48 | err = -ENOMEM; | 42 | err = -ENOMEM; |
49 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); | 43 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); |
@@ -67,10 +61,7 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
67 | req->out.numargs = 1; | 61 | req->out.numargs = 1; |
68 | req->out.args[0].size = sizeof(outarg); | 62 | req->out.args[0].size = sizeof(outarg); |
69 | req->out.args[0].value = &outarg; | 63 | req->out.args[0].value = &outarg; |
70 | if (excl) | 64 | request_send(fc, req); |
71 | request_send_nonint(fc, req); | ||
72 | else | ||
73 | request_send(fc, req); | ||
74 | err = req->out.h.error; | 65 | err = req->out.h.error; |
75 | if (err) { | 66 | if (err) { |
76 | fuse_request_free(ff->release_req); | 67 | fuse_request_free(ff->release_req); |
@@ -133,7 +124,7 @@ static int fuse_flush(struct file *file) | |||
133 | if (fc->no_flush) | 124 | if (fc->no_flush) |
134 | return 0; | 125 | return 0; |
135 | 126 | ||
136 | req = fuse_get_request_nonint(fc); | 127 | req = fuse_get_request(fc); |
137 | if (!req) | 128 | if (!req) |
138 | return -EINTR; | 129 | return -EINTR; |
139 | 130 | ||
@@ -146,7 +137,7 @@ static int fuse_flush(struct file *file) | |||
146 | req->in.numargs = 1; | 137 | req->in.numargs = 1; |
147 | req->in.args[0].size = sizeof(inarg); | 138 | req->in.args[0].size = sizeof(inarg); |
148 | req->in.args[0].value = &inarg; | 139 | req->in.args[0].value = &inarg; |
149 | request_send_nonint(fc, req); | 140 | request_send(fc, req); |
150 | err = req->out.h.error; | 141 | err = req->out.h.error; |
151 | fuse_put_request(fc, req); | 142 | fuse_put_request(fc, req); |
152 | if (err == -ENOSYS) { | 143 | if (err == -ENOSYS) { |
@@ -171,7 +162,7 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, | |||
171 | 162 | ||
172 | req = fuse_get_request(fc); | 163 | req = fuse_get_request(fc); |
173 | if (!req) | 164 | if (!req) |
174 | return -ERESTARTSYS; | 165 | return -EINTR; |
175 | 166 | ||
176 | memset(&inarg, 0, sizeof(inarg)); | 167 | memset(&inarg, 0, sizeof(inarg)); |
177 | inarg.fh = ff->fh; | 168 | inarg.fh = ff->fh; |
@@ -224,7 +215,7 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, | |||
224 | req->out.argvar = 1; | 215 | req->out.argvar = 1; |
225 | req->out.numargs = 1; | 216 | req->out.numargs = 1; |
226 | req->out.args[0].size = count; | 217 | req->out.args[0].size = count; |
227 | request_send_nonint(fc, req); | 218 | request_send(fc, req); |
228 | return req->out.args[0].size; | 219 | return req->out.args[0].size; |
229 | } | 220 | } |
230 | 221 | ||
@@ -240,7 +231,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
240 | struct inode *inode = page->mapping->host; | 231 | struct inode *inode = page->mapping->host; |
241 | struct fuse_conn *fc = get_fuse_conn(inode); | 232 | struct fuse_conn *fc = get_fuse_conn(inode); |
242 | loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT; | 233 | loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT; |
243 | struct fuse_req *req = fuse_get_request_nonint(fc); | 234 | struct fuse_req *req = fuse_get_request(fc); |
244 | int err = -EINTR; | 235 | int err = -EINTR; |
245 | if (!req) | 236 | if (!req) |
246 | goto out; | 237 | goto out; |
@@ -314,7 +305,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
314 | int err; | 305 | int err; |
315 | data.file = file; | 306 | data.file = file; |
316 | data.inode = inode; | 307 | data.inode = inode; |
317 | data.req = fuse_get_request_nonint(fc); | 308 | data.req = fuse_get_request(fc); |
318 | if (!data.req) | 309 | if (!data.req) |
319 | return -EINTR; | 310 | return -EINTR; |
320 | 311 | ||
@@ -350,7 +341,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
350 | req->out.numargs = 1; | 341 | req->out.numargs = 1; |
351 | req->out.args[0].size = sizeof(struct fuse_write_out); | 342 | req->out.args[0].size = sizeof(struct fuse_write_out); |
352 | req->out.args[0].value = &outarg; | 343 | req->out.args[0].value = &outarg; |
353 | request_send_nonint(fc, req); | 344 | request_send(fc, req); |
354 | return outarg.size; | 345 | return outarg.size; |
355 | } | 346 | } |
356 | 347 | ||
@@ -370,7 +361,7 @@ static int fuse_commit_write(struct file *file, struct page *page, | |||
370 | struct inode *inode = page->mapping->host; | 361 | struct inode *inode = page->mapping->host; |
371 | struct fuse_conn *fc = get_fuse_conn(inode); | 362 | struct fuse_conn *fc = get_fuse_conn(inode); |
372 | loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset; | 363 | loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset; |
373 | struct fuse_req *req = fuse_get_request_nonint(fc); | 364 | struct fuse_req *req = fuse_get_request(fc); |
374 | if (!req) | 365 | if (!req) |
375 | return -EINTR; | 366 | return -EINTR; |
376 | 367 | ||
@@ -444,7 +435,7 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
444 | ssize_t res = 0; | 435 | ssize_t res = 0; |
445 | struct fuse_req *req = fuse_get_request(fc); | 436 | struct fuse_req *req = fuse_get_request(fc); |
446 | if (!req) | 437 | if (!req) |
447 | return -ERESTARTSYS; | 438 | return -EINTR; |
448 | 439 | ||
449 | while (count) { | 440 | while (count) { |
450 | size_t tmp; | 441 | size_t tmp; |