diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 1 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 8 | ||||
-rw-r--r-- | fs/cifs/smb2maperror.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 10 |
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"); |