|
@@ -1565,10 +1565,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
|
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
|
|
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
|
|
bool fsuid_only)
|
|
bool fsuid_only)
|
|
{
|
|
{
|
|
- struct cifsFileInfo *open_file;
|
|
|
|
|
|
+ struct cifsFileInfo *open_file, *inv_file = NULL;
|
|
struct cifs_sb_info *cifs_sb;
|
|
struct cifs_sb_info *cifs_sb;
|
|
bool any_available = false;
|
|
bool any_available = false;
|
|
int rc;
|
|
int rc;
|
|
|
|
+ unsigned int refind = 0;
|
|
|
|
|
|
/* Having a null inode here (because mapping->host was set to zero by
|
|
/* Having a null inode here (because mapping->host was set to zero by
|
|
the VFS or MM) should not happen but we had reports of on oops (due to
|
|
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,
|
|
|
|
|
|
spin_lock(&cifs_file_list_lock);
|
|
spin_lock(&cifs_file_list_lock);
|
|
refind_writable:
|
|
refind_writable:
|
|
|
|
+ if (refind > MAX_REOPEN_ATT) {
|
|
|
|
+ spin_unlock(&cifs_file_list_lock);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
|
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
|
if (!any_available && open_file->pid != current->tgid)
|
|
if (!any_available && open_file->pid != current->tgid)
|
|
continue;
|
|
continue;
|
|
if (fsuid_only && open_file->uid != current_fsuid())
|
|
if (fsuid_only && open_file->uid != current_fsuid())
|
|
continue;
|
|
continue;
|
|
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
|
|
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
|
|
- cifsFileInfo_get(open_file);
|
|
|
|
-
|
|
|
|
if (!open_file->invalidHandle) {
|
|
if (!open_file->invalidHandle) {
|
|
/* found a good writable file */
|
|
/* found a good writable file */
|
|
|
|
+ cifsFileInfo_get(open_file);
|
|
spin_unlock(&cifs_file_list_lock);
|
|
spin_unlock(&cifs_file_list_lock);
|
|
return open_file;
|
|
return open_file;
|
|
|
|
+ } else {
|
|
|
|
+ if (!inv_file)
|
|
|
|
+ inv_file = open_file;
|
|
}
|
|
}
|
|
-
|
|
|
|
- spin_unlock(&cifs_file_list_lock);
|
|
|
|
-
|
|
|
|
- /* Had to unlock since following call can block */
|
|
|
|
- rc = cifs_reopen_file(open_file, false);
|
|
|
|
- if (!rc)
|
|
|
|
- return open_file;
|
|
|
|
-
|
|
|
|
- /* if it fails, try another handle if possible */
|
|
|
|
- cFYI(1, "wp failed on reopen file");
|
|
|
|
- cifsFileInfo_put(open_file);
|
|
|
|
-
|
|
|
|
- spin_lock(&cifs_file_list_lock);
|
|
|
|
-
|
|
|
|
- /* else we simply continue to the next entry. Thus
|
|
|
|
- we do not loop on reopen errors. If we
|
|
|
|
- can not reopen the file, for example if we
|
|
|
|
- reconnected to a server with another client
|
|
|
|
- racing to delete or lock the file we would not
|
|
|
|
- make progress if we restarted before the beginning
|
|
|
|
- of the loop here. */
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* couldn't find useable FH with same pid, try any available */
|
|
/* couldn't find useable FH with same pid, try any available */
|
|
@@ -1629,7 +1615,30 @@ refind_writable:
|
|
any_available = true;
|
|
any_available = true;
|
|
goto refind_writable;
|
|
goto refind_writable;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (inv_file) {
|
|
|
|
+ any_available = false;
|
|
|
|
+ cifsFileInfo_get(inv_file);
|
|
|
|
+ }
|
|
|
|
+
|
|
spin_unlock(&cifs_file_list_lock);
|
|
spin_unlock(&cifs_file_list_lock);
|
|
|
|
+
|
|
|
|
+ if (inv_file) {
|
|
|
|
+ rc = cifs_reopen_file(inv_file, false);
|
|
|
|
+ if (!rc)
|
|
|
|
+ return inv_file;
|
|
|
|
+ else {
|
|
|
|
+ spin_lock(&cifs_file_list_lock);
|
|
|
|
+ list_move_tail(&inv_file->flist,
|
|
|
|
+ &cifs_inode->openFileList);
|
|
|
|
+ spin_unlock(&cifs_file_list_lock);
|
|
|
|
+ cifsFileInfo_put(inv_file);
|
|
|
|
+ spin_lock(&cifs_file_list_lock);
|
|
|
|
+ ++refind;
|
|
|
|
+ goto refind_writable;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|