From: Miklos Szeredi 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 Signed-off-by: Andrew Morton --- fs/fuse/file.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) diff -puN fs/fuse/file.c~fuse-file-operations-interrupted-open-fix fs/fuse/file.c --- 25/fs/fuse/file.c~fuse-file-operations-interrupted-open-fix 2005-05-10 02:21:59.000000000 -0700 +++ 25-akpm/fs/fuse/file.c 2005-05-10 02:21:59.000000000 -0700 @@ -20,6 +20,9 @@ static int fuse_open(struct inode *inode struct 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 @@ static int fuse_open(struct inode *inode return 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 @@ static int fuse_open(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) invalidate_inode_pages(inode->i_mapping); _