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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull cifs fixes from Steve French:
"Seven cifs/smb3 fixes, including three for stable"

* tag '5.4-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Fix cifsInodeInfo lock_sem deadlock when reconnect occurs
CIFS: Fix use after free of file info structures
CIFS: Fix retry mid list corruption on reconnects
cifs: Fix missed free operations
CIFS: avoid using MID 0xFFFF
cifs: clarify comment about timestamp granularity for old servers
cifs: Handle -EINPROGRESS only when noblockcnt is set

+75 -37
+7 -1
fs/cifs/cifsfs.c
··· 169 169 else 170 170 sb->s_maxbytes = MAX_NON_LFS; 171 171 172 - /* Some very old servers like DOS and OS/2 used 2 second granularity */ 172 + /* 173 + * Some very old servers like DOS and OS/2 used 2 second granularity 174 + * (while all current servers use 100ns granularity - see MS-DTYP) 175 + * but 1 second is the maximum allowed granularity for the VFS 176 + * so for old servers set time granularity to 1 second while for 177 + * everything else (current servers) set it to 100ns. 178 + */ 173 179 if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) && 174 180 ((tcon->ses->capabilities & 175 181 tcon->ses->server->vals->cap_nt_find) == 0) &&
+5
fs/cifs/cifsglob.h
··· 1391 1391 struct cifsInodeInfo { 1392 1392 bool can_cache_brlcks; 1393 1393 struct list_head llist; /* locks helb by this inode */ 1394 + /* 1395 + * NOTE: Some code paths call down_read(lock_sem) twice, so 1396 + * we must always use use cifs_down_write() instead of down_write() 1397 + * for this semaphore to avoid deadlocks. 1398 + */ 1394 1399 struct rw_semaphore lock_sem; /* protect the fields above */ 1395 1400 /* BB add in lists for dirty pages i.e. write caching info for oplock */ 1396 1401 struct list_head openFileList;
+1
fs/cifs/cifsproto.h
··· 170 170 struct file_lock *flock, const unsigned int xid); 171 171 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile); 172 172 173 + extern void cifs_down_write(struct rw_semaphore *sem); 173 174 extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, 174 175 struct file *file, 175 176 struct tcon_link *tlink,
+15 -3
fs/cifs/connect.c
··· 564 564 spin_lock(&GlobalMid_Lock); 565 565 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 566 566 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 567 + kref_get(&mid_entry->refcount); 567 568 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) 568 569 mid_entry->mid_state = MID_RETRY_NEEDED; 569 570 list_move(&mid_entry->qhead, &retry_list); 571 + mid_entry->mid_flags |= MID_DELETED; 570 572 } 571 573 spin_unlock(&GlobalMid_Lock); 572 574 mutex_unlock(&server->srv_mutex); ··· 578 576 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 579 577 list_del_init(&mid_entry->qhead); 580 578 mid_entry->callback(mid_entry); 579 + cifs_mid_q_entry_release(mid_entry); 581 580 } 582 581 583 582 if (cifs_rdma_enabled(server)) { ··· 898 895 if (mid->mid_flags & MID_DELETED) 899 896 printk_once(KERN_WARNING 900 897 "trying to dequeue a deleted mid\n"); 901 - else 898 + else { 902 899 list_del_init(&mid->qhead); 900 + mid->mid_flags |= MID_DELETED; 901 + } 903 902 spin_unlock(&GlobalMid_Lock); 904 903 } 905 904 ··· 971 966 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 972 967 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 973 968 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid); 969 + kref_get(&mid_entry->refcount); 974 970 mid_entry->mid_state = MID_SHUTDOWN; 975 971 list_move(&mid_entry->qhead, &dispose_list); 972 + mid_entry->mid_flags |= MID_DELETED; 976 973 } 977 974 spin_unlock(&GlobalMid_Lock); 978 975 ··· 984 977 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid); 985 978 list_del_init(&mid_entry->qhead); 986 979 mid_entry->callback(mid_entry); 980 + cifs_mid_q_entry_release(mid_entry); 987 981 } 988 982 /* 1/8th of sec is more than enough time for them to exit */ 989 983 msleep(125); ··· 3890 3882 3891 3883 rc = socket->ops->connect(socket, saddr, slen, 3892 3884 server->noblockcnt ? O_NONBLOCK : 0); 3893 - 3894 - if (rc == -EINPROGRESS) 3885 + /* 3886 + * When mounting SMB root file systems, we do not want to block in 3887 + * connect. Otherwise bail out and then let cifs_reconnect() perform 3888 + * reconnect failover - if possible. 3889 + */ 3890 + if (server->noblockcnt && rc == -EINPROGRESS) 3895 3891 rc = 0; 3896 3892 if (rc < 0) { 3897 3893 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
+18 -11
fs/cifs/file.c
··· 281 281 return has_locks; 282 282 } 283 283 284 + void 285 + cifs_down_write(struct rw_semaphore *sem) 286 + { 287 + while (!down_write_trylock(sem)) 288 + msleep(10); 289 + } 290 + 284 291 struct cifsFileInfo * 285 292 cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 286 293 struct tcon_link *tlink, __u32 oplock) ··· 313 306 INIT_LIST_HEAD(&fdlocks->locks); 314 307 fdlocks->cfile = cfile; 315 308 cfile->llist = fdlocks; 316 - down_write(&cinode->lock_sem); 309 + cifs_down_write(&cinode->lock_sem); 317 310 list_add(&fdlocks->llist, &cinode->llist); 318 311 up_write(&cinode->lock_sem); 319 312 ··· 412 405 bool oplock_break_cancelled; 413 406 414 407 spin_lock(&tcon->open_file_lock); 415 - 408 + spin_lock(&cifsi->open_file_lock); 416 409 spin_lock(&cifs_file->file_info_lock); 417 410 if (--cifs_file->count > 0) { 418 411 spin_unlock(&cifs_file->file_info_lock); 412 + spin_unlock(&cifsi->open_file_lock); 419 413 spin_unlock(&tcon->open_file_lock); 420 414 return; 421 415 } ··· 429 421 cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); 430 422 431 423 /* remove it from the lists */ 432 - spin_lock(&cifsi->open_file_lock); 433 424 list_del(&cifs_file->flist); 434 - spin_unlock(&cifsi->open_file_lock); 435 425 list_del(&cifs_file->tlist); 436 426 atomic_dec(&tcon->num_local_opens); 437 427 ··· 446 440 cifs_set_oplock_level(cifsi, 0); 447 441 } 448 442 443 + spin_unlock(&cifsi->open_file_lock); 449 444 spin_unlock(&tcon->open_file_lock); 450 445 451 446 oplock_break_cancelled = wait_oplock_handler ? ··· 471 464 * Delete any outstanding lock records. We'll lose them when the file 472 465 * is closed anyway. 473 466 */ 474 - down_write(&cifsi->lock_sem); 467 + cifs_down_write(&cifsi->lock_sem); 475 468 list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { 476 469 list_del(&li->llist); 477 470 cifs_del_lock_waiters(li); ··· 1034 1027 cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) 1035 1028 { 1036 1029 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 1037 - down_write(&cinode->lock_sem); 1030 + cifs_down_write(&cinode->lock_sem); 1038 1031 list_add_tail(&lock->llist, &cfile->llist->locks); 1039 1032 up_write(&cinode->lock_sem); 1040 1033 } ··· 1056 1049 1057 1050 try_again: 1058 1051 exist = false; 1059 - down_write(&cinode->lock_sem); 1052 + cifs_down_write(&cinode->lock_sem); 1060 1053 1061 1054 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, 1062 1055 lock->type, lock->flags, &conf_lock, ··· 1079 1072 (lock->blist.next == &lock->blist)); 1080 1073 if (!rc) 1081 1074 goto try_again; 1082 - down_write(&cinode->lock_sem); 1075 + cifs_down_write(&cinode->lock_sem); 1083 1076 list_del_init(&lock->blist); 1084 1077 } 1085 1078 ··· 1132 1125 return rc; 1133 1126 1134 1127 try_again: 1135 - down_write(&cinode->lock_sem); 1128 + cifs_down_write(&cinode->lock_sem); 1136 1129 if (!cinode->can_cache_brlcks) { 1137 1130 up_write(&cinode->lock_sem); 1138 1131 return rc; ··· 1338 1331 int rc = 0; 1339 1332 1340 1333 /* we are going to update can_cache_brlcks here - need a write access */ 1341 - down_write(&cinode->lock_sem); 1334 + cifs_down_write(&cinode->lock_sem); 1342 1335 if (!cinode->can_cache_brlcks) { 1343 1336 up_write(&cinode->lock_sem); 1344 1337 return rc; ··· 1529 1522 if (!buf) 1530 1523 return -ENOMEM; 1531 1524 1532 - down_write(&cinode->lock_sem); 1525 + cifs_down_write(&cinode->lock_sem); 1533 1526 for (i = 0; i < 2; i++) { 1534 1527 cur = buf; 1535 1528 num = 0;
+2 -2
fs/cifs/inode.c
··· 2475 2475 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); 2476 2476 cifsFileInfo_put(wfile); 2477 2477 if (rc) 2478 - return rc; 2478 + goto cifs_setattr_exit; 2479 2479 } else if (rc != -EBADF) 2480 - return rc; 2480 + goto cifs_setattr_exit; 2481 2481 else 2482 2482 rc = 0; 2483 2483 }
+3
fs/cifs/smb1ops.c
··· 171 171 /* we do not want to loop forever */ 172 172 last_mid = cur_mid; 173 173 cur_mid++; 174 + /* avoid 0xFFFF MID */ 175 + if (cur_mid == 0xffff) 176 + cur_mid++; 174 177 175 178 /* 176 179 * This nested loop looks more expensive than it is.
+1 -1
fs/cifs/smb2file.c
··· 145 145 146 146 cur = buf; 147 147 148 - down_write(&cinode->lock_sem); 148 + cifs_down_write(&cinode->lock_sem); 149 149 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { 150 150 if (flock->fl_start > li->offset || 151 151 (flock->fl_start + length) <
+23 -19
fs/cifs/transport.c
··· 86 86 87 87 static void _cifs_mid_q_entry_release(struct kref *refcount) 88 88 { 89 - struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry, 90 - refcount); 91 - 92 - mempool_free(mid, cifs_mid_poolp); 93 - } 94 - 95 - void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) 96 - { 97 - spin_lock(&GlobalMid_Lock); 98 - kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); 99 - spin_unlock(&GlobalMid_Lock); 100 - } 101 - 102 - void 103 - DeleteMidQEntry(struct mid_q_entry *midEntry) 104 - { 89 + struct mid_q_entry *midEntry = 90 + container_of(refcount, struct mid_q_entry, refcount); 105 91 #ifdef CONFIG_CIFS_STATS2 106 92 __le16 command = midEntry->server->vals->lock_cmd; 107 93 __u16 smb_cmd = le16_to_cpu(midEntry->command); ··· 152 166 } 153 167 } 154 168 #endif 169 + 170 + mempool_free(midEntry, cifs_mid_poolp); 171 + } 172 + 173 + void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) 174 + { 175 + spin_lock(&GlobalMid_Lock); 176 + kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); 177 + spin_unlock(&GlobalMid_Lock); 178 + } 179 + 180 + void DeleteMidQEntry(struct mid_q_entry *midEntry) 181 + { 155 182 cifs_mid_q_entry_release(midEntry); 156 183 } 157 184 ··· 172 173 cifs_delete_mid(struct mid_q_entry *mid) 173 174 { 174 175 spin_lock(&GlobalMid_Lock); 175 - list_del_init(&mid->qhead); 176 - mid->mid_flags |= MID_DELETED; 176 + if (!(mid->mid_flags & MID_DELETED)) { 177 + list_del_init(&mid->qhead); 178 + mid->mid_flags |= MID_DELETED; 179 + } 177 180 spin_unlock(&GlobalMid_Lock); 178 181 179 182 DeleteMidQEntry(mid); ··· 873 872 rc = -EHOSTDOWN; 874 873 break; 875 874 default: 876 - list_del_init(&mid->qhead); 875 + if (!(mid->mid_flags & MID_DELETED)) { 876 + list_del_init(&mid->qhead); 877 + mid->mid_flags |= MID_DELETED; 878 + } 877 879 cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", 878 880 __func__, mid->mid, mid->mid_state); 879 881 rc = -EIO;