aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/file.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 792549193865..780c0e3e4703 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1042,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1042 } 1042 }
1043 1043
1044 read_lock(&GlobalSMBSeslock); 1044 read_lock(&GlobalSMBSeslock);
1045refind_writable:
1045 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1046 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1046 if (open_file->closePend) 1047 if (open_file->closePend)
1047 continue; 1048 continue;
@@ -1049,26 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1049 ((open_file->pfile->f_flags & O_RDWR) || 1050 ((open_file->pfile->f_flags & O_RDWR) ||
1050 (open_file->pfile->f_flags & O_WRONLY))) { 1051 (open_file->pfile->f_flags & O_WRONLY))) {
1051 atomic_inc(&open_file->wrtPending); 1052 atomic_inc(&open_file->wrtPending);
1053
1054 if (!open_file->invalidHandle) {
1055 /* found a good writable file */
1056 read_unlock(&GlobalSMBSeslock);
1057 return open_file;
1058 }
1059
1052 read_unlock(&GlobalSMBSeslock); 1060 read_unlock(&GlobalSMBSeslock);
1053 if (open_file->invalidHandle) { 1061 /* Had to unlock since following call can block */
1054 rc = cifs_reopen_file(open_file->pfile, FALSE); 1062 rc = cifs_reopen_file(open_file->pfile, FALSE);
1055 /* if it fails, try another handle - might be */ 1063 if (!rc) {
1056 /* dangerous to hold up writepages with retry */ 1064 if (!open_file->closePend)
1057 if (rc) { 1065 return open_file;
1058 cFYI(1, ("wp failed on reopen file")); 1066 else { /* start over in case this was deleted */
1067 /* since the list could be modified */
1059 read_lock(&GlobalSMBSeslock); 1068 read_lock(&GlobalSMBSeslock);
1060 /* can not use this handle, no write
1061 pending on this one after all */
1062 atomic_dec(&open_file->wrtPending); 1069 atomic_dec(&open_file->wrtPending);
1063 continue; 1070 goto refind_writable;
1064 } 1071 }
1065 } 1072 }
1066 if (open_file->closePend) { 1073
1067 read_lock(&GlobalSMBSeslock); 1074 /* if it fails, try another handle if possible -
1068 atomic_dec(&open_file->wrtPending); 1075 (we can not do this if closePending since
1069 continue; 1076 loop could be modified - in which case we
1070 } 1077 have to start at the beginning of the list
1071 return open_file; 1078 again. Note that it would be bad
1079 to hold up writepages here (rather than
1080 in caller) with continuous retries */
1081 cFYI(1, ("wp failed on reopen file"));
1082 read_lock(&GlobalSMBSeslock);
1083 /* can not use this handle, no write
1084 pending on this one after all */
1085 atomic_dec(&open_file->wrtPending);
1086
1087 if (open_file->closePend) /* list could have changed */
1088 goto refind_writable;
1089 /* else we simply continue to the next entry. Thus
1090 we do not loop on reopen errors. If we
1091 can not reopen the file, for example if we
1092 reconnected to a server with another client
1093 racing to delete or lock the file we would not
1094 make progress if we restarted before the beginning
1095 of the loop here. */
1072 } 1096 }
1073 } 1097 }
1074 read_unlock(&GlobalSMBSeslock); 1098 read_unlock(&GlobalSMBSeslock);