Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag '5.2-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Four small SMB3 fixes, all for stable"

* tag '5.2-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: fix GlobalMid_Lock bug in cifs_reconnect
SMB3: retry on STATUS_INSUFFICIENT_RESOURCES instead of failing write
cifs: add spinlock for the openFileList to cifsInodeInfo
cifs: fix panic in smb2_reconnect

+24 -4
+1
fs/cifs/cifsfs.c
··· 303 303 cifs_inode->uniqueid = 0; 304 304 cifs_inode->createtime = 0; 305 305 cifs_inode->epoch = 0; 306 + spin_lock_init(&cifs_inode->open_file_lock); 306 307 generate_random_uuid(cifs_inode->lease_key); 307 308 308 309 /*
+5
fs/cifs/cifsglob.h
··· 1377 1377 struct rw_semaphore lock_sem; /* protect the fields above */ 1378 1378 /* BB add in lists for dirty pages i.e. write caching info for oplock */ 1379 1379 struct list_head openFileList; 1380 + spinlock_t open_file_lock; /* protects openFileList */ 1380 1381 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ 1381 1382 unsigned int oplock; /* oplock/lease level we have */ 1382 1383 unsigned int epoch; /* used to track lease state changes */ ··· 1781 1780 * tcp_ses_lock protects: 1782 1781 * list operations on tcp and SMB session lists 1783 1782 * tcon->open_file_lock protects the list of open files hanging off the tcon 1783 + * inode->open_file_lock protects the openFileList hanging off the inode 1784 1784 * cfile->file_info_lock protects counters and fields in cifs file struct 1785 1785 * f_owner.lock protects certain per file struct operations 1786 1786 * mapping->page_lock protects certain per page operations 1787 + * 1788 + * Note that the cifs_tcon.open_file_lock should be taken before 1789 + * not after the cifsInodeInfo.open_file_lock 1787 1790 * 1788 1791 * Semaphores 1789 1792 * ----------
+2
fs/cifs/connect.c
··· 476 476 spin_lock(&GlobalMid_Lock); 477 477 server->nr_targets = 1; 478 478 #ifdef CONFIG_CIFS_DFS_UPCALL 479 + spin_unlock(&GlobalMid_Lock); 479 480 cifs_sb = find_super_by_tcp(server); 480 481 if (IS_ERR(cifs_sb)) { 481 482 rc = PTR_ERR(cifs_sb); ··· 494 493 } 495 494 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__, 496 495 server->nr_targets); 496 + spin_lock(&GlobalMid_Lock); 497 497 #endif 498 498 if (server->tcpStatus == CifsExiting) { 499 499 /* the demux thread will exit normally
+6 -2
fs/cifs/file.c
··· 338 338 atomic_inc(&tcon->num_local_opens); 339 339 340 340 /* if readable file instance put first in list*/ 341 + spin_lock(&cinode->open_file_lock); 341 342 if (file->f_mode & FMODE_READ) 342 343 list_add(&cfile->flist, &cinode->openFileList); 343 344 else 344 345 list_add_tail(&cfile->flist, &cinode->openFileList); 346 + spin_unlock(&cinode->open_file_lock); 345 347 spin_unlock(&tcon->open_file_lock); 346 348 347 349 if (fid->purge_cache) ··· 415 413 cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); 416 414 417 415 /* remove it from the lists */ 416 + spin_lock(&cifsi->open_file_lock); 418 417 list_del(&cifs_file->flist); 418 + spin_unlock(&cifsi->open_file_lock); 419 419 list_del(&cifs_file->tlist); 420 420 atomic_dec(&tcon->num_local_opens); 421 421 ··· 1954 1950 return 0; 1955 1951 } 1956 1952 1957 - spin_lock(&tcon->open_file_lock); 1953 + spin_lock(&cifs_inode->open_file_lock); 1958 1954 list_move_tail(&inv_file->flist, &cifs_inode->openFileList); 1959 - spin_unlock(&tcon->open_file_lock); 1955 + spin_unlock(&cifs_inode->open_file_lock); 1960 1956 cifsFileInfo_put(inv_file); 1961 1957 ++refind; 1962 1958 inv_file = NULL;
+1 -1
fs/cifs/smb2maperror.c
··· 457 457 {STATUS_FILE_INVALID, -EIO, "STATUS_FILE_INVALID"}, 458 458 {STATUS_ALLOTTED_SPACE_EXCEEDED, -EIO, 459 459 "STATUS_ALLOTTED_SPACE_EXCEEDED"}, 460 - {STATUS_INSUFFICIENT_RESOURCES, -EREMOTEIO, 460 + {STATUS_INSUFFICIENT_RESOURCES, -EAGAIN, 461 461 "STATUS_INSUFFICIENT_RESOURCES"}, 462 462 {STATUS_DFS_EXIT_PATH_FOUND, -EIO, "STATUS_DFS_EXIT_PATH_FOUND"}, 463 463 {STATUS_DEVICE_DATA_ERROR, -EIO, "STATUS_DEVICE_DATA_ERROR"},
+9 -1
fs/cifs/smb2pdu.c
··· 3114 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 3121 if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { 3118 3122 list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); 3119 3123 tcon_exist = true; 3124 + ses->ses_count++; 3120 3125 } 3121 3126 } 3122 3127 /* ··· 3140 3135 else 3141 3136 resched = true; 3142 3137 list_del_init(&tcon->rlist); 3143 - cifs_put_tcon(tcon); 3138 + if (tcon->ipc) 3139 + cifs_put_smb_ses(tcon->ses); 3140 + else 3141 + cifs_put_tcon(tcon); 3144 3142 } 3145 3143 3146 3144 cifs_dbg(FYI, "Reconnecting tcons finished\n");