aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index ed9b5a8fb51f..253170dfa716 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1565,10 +1565,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1565struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, 1565struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1566 bool fsuid_only) 1566 bool fsuid_only)
1567{ 1567{
1568 struct cifsFileInfo *open_file; 1568 struct cifsFileInfo *open_file, *inv_file = NULL;
1569 struct cifs_sb_info *cifs_sb; 1569 struct cifs_sb_info *cifs_sb;
1570 bool any_available = false; 1570 bool any_available = false;
1571 int rc; 1571 int rc;
1572 unsigned int refind = 0;
1572 1573
1573 /* Having a null inode here (because mapping->host was set to zero by 1574 /* Having a null inode here (because mapping->host was set to zero by
1574 the VFS or MM) should not happen but we had reports of on oops (due to 1575 the VFS or MM) should not happen but we had reports of on oops (due to
@@ -1588,40 +1589,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1588 1589
1589 spin_lock(&cifs_file_list_lock); 1590 spin_lock(&cifs_file_list_lock);
1590refind_writable: 1591refind_writable:
1592 if (refind > MAX_REOPEN_ATT) {
1593 spin_unlock(&cifs_file_list_lock);
1594 return NULL;
1595 }
1591 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1596 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1592 if (!any_available && open_file->pid != current->tgid) 1597 if (!any_available && open_file->pid != current->tgid)
1593 continue; 1598 continue;
1594 if (fsuid_only && open_file->uid != current_fsuid()) 1599 if (fsuid_only && open_file->uid != current_fsuid())
1595 continue; 1600 continue;
1596 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 1601 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
1597 cifsFileInfo_get(open_file);
1598
1599 if (!open_file->invalidHandle) { 1602 if (!open_file->invalidHandle) {
1600 /* found a good writable file */ 1603 /* found a good writable file */
1604 cifsFileInfo_get(open_file);
1601 spin_unlock(&cifs_file_list_lock); 1605 spin_unlock(&cifs_file_list_lock);
1602 return open_file; 1606 return open_file;
1607 } else {
1608 if (!inv_file)
1609 inv_file = open_file;
1603 } 1610 }
1604
1605 spin_unlock(&cifs_file_list_lock);
1606
1607 /* Had to unlock since following call can block */
1608 rc = cifs_reopen_file(open_file, false);
1609 if (!rc)
1610 return open_file;
1611
1612 /* if it fails, try another handle if possible */
1613 cFYI(1, "wp failed on reopen file");
1614 cifsFileInfo_put(open_file);
1615
1616 spin_lock(&cifs_file_list_lock);
1617
1618 /* else we simply continue to the next entry. Thus
1619 we do not loop on reopen errors. If we
1620 can not reopen the file, for example if we
1621 reconnected to a server with another client
1622 racing to delete or lock the file we would not
1623 make progress if we restarted before the beginning
1624 of the loop here. */
1625 } 1611 }
1626 } 1612 }
1627 /* couldn't find useable FH with same pid, try any available */ 1613 /* couldn't find useable FH with same pid, try any available */
@@ -1629,7 +1615,30 @@ refind_writable:
1629 any_available = true; 1615 any_available = true;
1630 goto refind_writable; 1616 goto refind_writable;
1631 } 1617 }
1618
1619 if (inv_file) {
1620 any_available = false;
1621 cifsFileInfo_get(inv_file);
1622 }
1623
1632 spin_unlock(&cifs_file_list_lock); 1624 spin_unlock(&cifs_file_list_lock);
1625
1626 if (inv_file) {
1627 rc = cifs_reopen_file(inv_file, false);
1628 if (!rc)
1629 return inv_file;
1630 else {
1631 spin_lock(&cifs_file_list_lock);
1632 list_move_tail(&inv_file->flist,
1633 &cifs_inode->openFileList);
1634 spin_unlock(&cifs_file_list_lock);
1635 cifsFileInfo_put(inv_file);
1636 spin_lock(&cifs_file_list_lock);
1637 ++refind;
1638 goto refind_writable;
1639 }
1640 }
1641
1633 return NULL; 1642 return NULL;
1634} 1643}
1635 1644