提交 15745320 编写于 作者: S Steve French

[CIFS] Fix oops in find_writable_file

There was a case in which find_writable_file was not waiting long enough
under heavy stress when writepages was racing with close of the file
handle being used by the write.
Signed-off-by: NSteve French <sfrench@us.ibm.com>
上级 77159b4d
...@@ -467,7 +467,7 @@ static int cifs_reopen_file(struct file *file, int can_flush) ...@@ -467,7 +467,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
int cifs_close(struct inode *inode, struct file *file) int cifs_close(struct inode *inode, struct file *file)
{ {
int rc = 0; int rc = 0;
int xid; int xid, timeout;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile = struct cifsFileInfo *pSMBFile =
...@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
/* no sense reconnecting to close a file that is /* no sense reconnecting to close a file that is
already closed */ already closed */
if (pTcon->tidStatus != CifsNeedReconnect) { if (pTcon->tidStatus != CifsNeedReconnect) {
int timeout = 2; timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0) while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout < 1000) ) { && (timeout <= 2048)) {
/* Give write a better chance to get to /* Give write a better chance to get to
server ahead of the close. We do not server ahead of the close. We do not
want to add a wait_q here as it would want to add a wait_q here as it would
...@@ -522,6 +522,23 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -522,6 +522,23 @@ int cifs_close(struct inode *inode, struct file *file)
list_del(&pSMBFile->flist); list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist); list_del(&pSMBFile->tlist);
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
timeout = 10;
/* We waited above to give the SMBWrite a chance to issue
on the wire (so we do not get SMBWrite returning EBADF
if writepages is racing with close. Note that writepages
does not specify a file handle, so it is possible for a file
to be opened twice, and the application close the "wrong"
file handle - in these cases we delay long enough to allow
the SMBWrite to get on the wire before the SMB Close.
We allow total wait here over 45 seconds, more than
oplock break time, and more than enough to allow any write
to complete on the server, or to time out on the client */
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout <= 50000)) {
cERROR(1, ("writes pending, delay free of handle"));
msleep(timeout);
timeout *= 8;
}
kfree(pSMBFile->search_resume_name); kfree(pSMBFile->search_resume_name);
kfree(file->private_data); kfree(file->private_data);
file->private_data = NULL; file->private_data = NULL;
...@@ -1031,22 +1048,24 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) ...@@ -1031,22 +1048,24 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
(open_file->pfile->f_flags & O_WRONLY))) { (open_file->pfile->f_flags & O_WRONLY))) {
atomic_inc(&open_file->wrtPending); atomic_inc(&open_file->wrtPending);
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
if ((open_file->invalidHandle) && if (open_file->invalidHandle) {
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
rc = cifs_reopen_file(open_file->pfile, FALSE); rc = cifs_reopen_file(open_file->pfile, FALSE);
/* if it fails, try another handle - might be */ /* if it fails, try another handle - might be */
/* dangerous to hold up writepages with retry */ /* dangerous to hold up writepages with retry */
if (rc) { if (rc) {
cFYI(1, cFYI(1, ("wp failed on reopen file"));
("failed on reopen file in wp"));
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write /* can not use this handle, no write
pending on this one after all */ pending on this one after all */
atomic_dec atomic_dec(&open_file->wrtPending);
(&open_file->wrtPending);
continue; continue;
} }
} }
if (open_file->closePend) {
read_lock(&GlobalSMBSeslock);
atomic_dec(&open_file->wrtPending);
continue;
}
return open_file; return open_file;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册