aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-09-09 16:10:39 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 17:03:48 -0400
commit7c352bdf048811b8128019ffc1e886161e09c11c (patch)
tree74c48298b67d37295433d9b2bb08d590a5f97a78 /fs/fuse/file.c
parent8254798199332966e2ab647380c990193af7e854 (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.c33
1 files changed, 12 insertions, 21 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e225f8c0b26..6454022b053 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;