FUSE: interrupted open fix
Miklos Szeredi
maintainerPATCH 1/1 FUSE: interrupted open fix
This patch fixes incorrect behavior of open(..., O_CREAT|O_EXCL) in case it is interrupted after the file has been created. In this case the system call was restarted and returned -EEXIST. The solution is not to allow interruption. Thanks to David Shaw for the bug report and testing.
Signed-off-by Miklos Szeredi <[email protected]>
fs/fuse/file.c +12 -3
@@ -20,6 +20,9 @@ int fuse_open_common(struct inode *inodestruct fuse_open_out outarg;struct fuse_file *ff;int err; +/* Restarting the syscall is not allowed if O_CREAT and O_EXCL +are both set, because creation will fail on the restart */ +int excl = (file->f_flags & (O_CREAT |O_EXCL )) == (O_CREAT |O_EXCL ); err =generic_file_open (inode, file);if (err)
@@ -33,9 +36,12 @@ int fuse_open_common(struct inode *inodereturn err; } - req =fuse_get_request (fc); +if (excl) + req =fuse_get_request_nonint (fc); +else + req =fuse_get_request (fc);if (!req) -return -ERESTARTSYS ; +return excl ? -EINTR : -ERESTARTSYS ; err = -ENOMEM ; ff =kmalloc (sizeof (struct fuse_file ),GFP_KERNEL );
@@ -59,7 +65,10 @@ int fuse_open_common(struct inode *inode req->out.numargs =1 ; req->out.args[0 ].size =sizeof (outarg); req->out.args[0 ].value = &outarg; -request_send (fc, req); +if (excl) +request_send_nonint (fc, req); +else +request_send (fc, req); err = req->out.h.error;if (!err && !(fc->flags &FUSE_KERNEL_CACHE ))invalidate_inode_pages (inode->i_mapping);