summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.c1
-rw-r--r--fs/cifs/cifsglob.h5
-rw-r--r--fs/cifs/connect.c2
-rw-r--r--fs/cifs/file.c8
-rw-r--r--fs/cifs/smb2maperror.c2
-rw-r--r--fs/cifs/smb2pdu.c10
6 files changed, 24 insertions, 4 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index f5fcd6360056..65d9771e49f9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -303,6 +303,7 @@ cifs_alloc_inode(struct super_block *sb)
303 cifs_inode->uniqueid = 0; 303 cifs_inode->uniqueid = 0;
304 cifs_inode->createtime = 0; 304 cifs_inode->createtime = 0;
305 cifs_inode->epoch = 0; 305 cifs_inode->epoch = 0;
306 spin_lock_init(&cifs_inode->open_file_lock);
306 generate_random_uuid(cifs_inode->lease_key); 307 generate_random_uuid(cifs_inode->lease_key);
307 308
308 /* 309 /*
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 334ff5f9c3f3..4777b3c4a92c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1377,6 +1377,7 @@ struct cifsInodeInfo {
1377 struct rw_semaphore lock_sem; /* protect the fields above */ 1377 struct rw_semaphore lock_sem; /* protect the fields above */
1378 /* BB add in lists for dirty pages i.e. write caching info for oplock */ 1378 /* BB add in lists for dirty pages i.e. write caching info for oplock */
1379 struct list_head openFileList; 1379 struct list_head openFileList;
1380 spinlock_t open_file_lock; /* protects openFileList */
1380 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ 1381 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
1381 unsigned int oplock; /* oplock/lease level we have */ 1382 unsigned int oplock; /* oplock/lease level we have */
1382 unsigned int epoch; /* used to track lease state changes */ 1383 unsigned int epoch; /* used to track lease state changes */
@@ -1780,10 +1781,14 @@ require use of the stronger protocol */
1780 * tcp_ses_lock protects: 1781 * tcp_ses_lock protects:
1781 * list operations on tcp and SMB session lists 1782 * list operations on tcp and SMB session lists
1782 * tcon->open_file_lock protects the list of open files hanging off the tcon 1783 * tcon->open_file_lock protects the list of open files hanging off the tcon
1784 * inode->open_file_lock protects the openFileList hanging off the inode
1783 * cfile->file_info_lock protects counters and fields in cifs file struct 1785 * cfile->file_info_lock protects counters and fields in cifs file struct
1784 * f_owner.lock protects certain per file struct operations 1786 * f_owner.lock protects certain per file struct operations
1785 * mapping->page_lock protects certain per page operations 1787 * mapping->page_lock protects certain per page operations
1786 * 1788 *
1789 * Note that the cifs_tcon.open_file_lock should be taken before
1790 * not after the cifsInodeInfo.open_file_lock
1791 *
1787 * Semaphores 1792 * Semaphores
1788 * ---------- 1793 * ----------
1789 * sesSem operations on smb session 1794 * sesSem operations on smb session
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8c4121da624e..8dd6637a3cbb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -476,6 +476,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
476 spin_lock(&GlobalMid_Lock); 476 spin_lock(&GlobalMid_Lock);
477 server->nr_targets = 1; 477 server->nr_targets = 1;
478#ifdef CONFIG_CIFS_DFS_UPCALL 478#ifdef CONFIG_CIFS_DFS_UPCALL
479 spin_unlock(&GlobalMid_Lock);
479 cifs_sb = find_super_by_tcp(server); 480 cifs_sb = find_super_by_tcp(server);
480 if (IS_ERR(cifs_sb)) { 481 if (IS_ERR(cifs_sb)) {
481 rc = PTR_ERR(cifs_sb); 482 rc = PTR_ERR(cifs_sb);
@@ -493,6 +494,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
493 } 494 }
494 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__, 495 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
495 server->nr_targets); 496 server->nr_targets);
497 spin_lock(&GlobalMid_Lock);
496#endif 498#endif
497 if (server->tcpStatus == CifsExiting) { 499 if (server->tcpStatus == CifsExiting) {
498 /* the demux thread will exit normally 500 /* the demux thread will exit normally
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 06e27ac6d82c..97090693d182 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -338,10 +338,12 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
338 atomic_inc(&tcon->num_local_opens); 338 atomic_inc(&tcon->num_local_opens);
339 339
340 /* if readable file instance put first in list*/ 340 /* if readable file instance put first in list*/
341 spin_lock(&cinode->open_file_lock);
341 if (file->f_mode & FMODE_READ) 342 if (file->f_mode & FMODE_READ)
342 list_add(&cfile->flist, &cinode->openFileList); 343 list_add(&cfile->flist, &cinode->openFileList);
343 else 344 else
344 list_add_tail(&cfile->flist, &cinode->openFileList); 345 list_add_tail(&cfile->flist, &cinode->openFileList);
346 spin_unlock(&cinode->open_file_lock);
345 spin_unlock(&tcon->open_file_lock); 347 spin_unlock(&tcon->open_file_lock);
346 348
347 if (fid->purge_cache) 349 if (fid->purge_cache)
@@ -413,7 +415,9 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
413 cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); 415 cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
414 416
415 /* remove it from the lists */ 417 /* remove it from the lists */
418 spin_lock(&cifsi->open_file_lock);
416 list_del(&cifs_file->flist); 419 list_del(&cifs_file->flist);
420 spin_unlock(&cifsi->open_file_lock);
417 list_del(&cifs_file->tlist); 421 list_del(&cifs_file->tlist);
418 atomic_dec(&tcon->num_local_opens); 422 atomic_dec(&tcon->num_local_opens);
419 423
@@ -1950,9 +1954,9 @@ refind_writable:
1950 return 0; 1954 return 0;
1951 } 1955 }
1952 1956
1953 spin_lock(&tcon->open_file_lock); 1957 spin_lock(&cifs_inode->open_file_lock);
1954 list_move_tail(&inv_file->flist, &cifs_inode->openFileList); 1958 list_move_tail(&inv_file->flist, &cifs_inode->openFileList);
1955 spin_unlock(&tcon->open_file_lock); 1959 spin_unlock(&cifs_inode->open_file_lock);
1956 cifsFileInfo_put(inv_file); 1960 cifsFileInfo_put(inv_file);
1957 ++refind; 1961 ++refind;
1958 inv_file = NULL; 1962 inv_file = NULL;
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
index e32c264e3adb..82ade16c9501 100644
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -457,7 +457,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
457 {STATUS_FILE_INVALID, -EIO, "STATUS_FILE_INVALID"}, 457 {STATUS_FILE_INVALID, -EIO, "STATUS_FILE_INVALID"},
458 {STATUS_ALLOTTED_SPACE_EXCEEDED, -EIO, 458 {STATUS_ALLOTTED_SPACE_EXCEEDED, -EIO,
459 "STATUS_ALLOTTED_SPACE_EXCEEDED"}, 459 "STATUS_ALLOTTED_SPACE_EXCEEDED"},
460 {STATUS_INSUFFICIENT_RESOURCES, -EREMOTEIO, 460 {STATUS_INSUFFICIENT_RESOURCES, -EAGAIN,
461 "STATUS_INSUFFICIENT_RESOURCES"}, 461 "STATUS_INSUFFICIENT_RESOURCES"},
462 {STATUS_DFS_EXIT_PATH_FOUND, -EIO, "STATUS_DFS_EXIT_PATH_FOUND"}, 462 {STATUS_DFS_EXIT_PATH_FOUND, -EIO, "STATUS_DFS_EXIT_PATH_FOUND"},
463 {STATUS_DEVICE_DATA_ERROR, -EIO, "STATUS_DEVICE_DATA_ERROR"}, 463 {STATUS_DEVICE_DATA_ERROR, -EIO, "STATUS_DEVICE_DATA_ERROR"},
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 29b699d532ef..75311a8a68bf 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -3114,9 +3114,14 @@ void smb2_reconnect_server(struct work_struct *work)
3114 tcon_exist = true; 3114 tcon_exist = true;
3115 } 3115 }
3116 } 3116 }
3117 /*
3118 * IPC has the same lifetime as its session and uses its
3119 * refcount.
3120 */
3117 if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { 3121 if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
3118 list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); 3122 list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
3119 tcon_exist = true; 3123 tcon_exist = true;
3124 ses->ses_count++;
3120 } 3125 }
3121 } 3126 }
3122 /* 3127 /*
@@ -3135,7 +3140,10 @@ void smb2_reconnect_server(struct work_struct *work)
3135 else 3140 else
3136 resched = true; 3141 resched = true;
3137 list_del_init(&tcon->rlist); 3142 list_del_init(&tcon->rlist);
3138 cifs_put_tcon(tcon); 3143 if (tcon->ipc)
3144 cifs_put_smb_ses(tcon->ses);
3145 else
3146 cifs_put_tcon(tcon);
3139 } 3147 }
3140 3148
3141 cifs_dbg(FYI, "Reconnecting tcons finished\n"); 3149 cifs_dbg(FYI, "Reconnecting tcons finished\n");