Commit c1f8b629 authored by Steve French's avatar Steve French Committed by Steve French

do not filemap_fdatawrite when reconnecting in write to avoid potential deadlock

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent e70aaeb1
...@@ -155,7 +155,7 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -155,7 +155,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} }
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
up(&ses->server->tcpSem); up(&server->tcpSem);
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
{ {
......
...@@ -267,7 +267,7 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile) ...@@ -267,7 +267,7 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile)
return rc; return rc;
} }
static int cifs_reopen_file(struct inode *inode, struct file *file) static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
{ {
int rc = -EACCES; int rc = -EACCES;
int xid, oplock; int xid, oplock;
...@@ -358,19 +358,25 @@ and we can never tell if the caller already has the rename_sem */ ...@@ -358,19 +358,25 @@ and we can never tell if the caller already has the rename_sem */
up(&pCifsFile->fh_sem); up(&pCifsFile->fh_sem);
pCifsInode = CIFS_I(inode); pCifsInode = CIFS_I(inode);
if(pCifsInode) { if(pCifsInode) {
filemap_fdatawrite(inode->i_mapping); if(can_flush) {
filemap_fdatawait(inode->i_mapping); filemap_fdatawrite(inode->i_mapping);
filemap_fdatawait(inode->i_mapping);
/* temporarily disable caching while we /* temporarily disable caching while we
go to server to get inode info */ go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE; pCifsInode->clientCanCacheAll = FALSE;
pCifsInode->clientCanCacheRead = FALSE; pCifsInode->clientCanCacheRead = FALSE;
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&inode, rc = cifs_get_inode_info_unix(&inode,
full_path, inode->i_sb); full_path, inode->i_sb);
else else
rc = cifs_get_inode_info(&inode, rc = cifs_get_inode_info(&inode,
full_path, NULL, inode->i_sb); full_path, NULL, inode->i_sb);
} /* else we are writing out data to server already
and could deadlock if we tried to flush data, and
since we do not know if we have data that would
invalidate the current end of file on the server
we can not go to the server to get the new
inod info */
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
...@@ -621,7 +627,11 @@ cifs_write(struct file * file, const char *write_data, ...@@ -621,7 +627,11 @@ cifs_write(struct file * file, const char *write_data,
FreeXid(xid); FreeXid(xid);
return total_written; return total_written;
} }
rc = cifs_reopen_file(file->f_dentry->d_inode,file); /* we could deadlock if we called
filemap_fdatawait from here so tell
reopen_file not to flush data to server now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
file,FALSE);
if(rc != 0) if(rc != 0)
break; break;
} }
...@@ -977,7 +987,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size, ...@@ -977,7 +987,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
rc = -EAGAIN; rc = -EAGAIN;
while(rc == -EAGAIN) { while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) { if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file); rc = cifs_reopen_file(file->f_dentry->d_inode,
file,TRUE);
if(rc != 0) if(rc != 0)
break; break;
} }
...@@ -1132,7 +1143,8 @@ cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1132,7 +1143,8 @@ cifs_readpages(struct file *file, struct address_space *mapping,
rc = -EAGAIN; rc = -EAGAIN;
while(rc == -EAGAIN) { while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) { if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file); rc = cifs_reopen_file(file->f_dentry->d_inode,
file, TRUE);
if(rc != 0) if(rc != 0)
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment