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 'v6.18-rc6-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Fix potential memory leak in mount

- Add some missing read tracepoints

- Fix locking issue with directory leases

* tag 'v6.18-rc6-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Add the smb3_read_* tracepoints to SMB1
cifs: fix memory leak in smb3_fs_context_parse_param error path
smb: client: introduce close_cached_dir_locked()

+64 -3
+38 -3
fs/smb/client/cached_dir.c
··· 16 16 static void free_cached_dir(struct cached_fid *cfid); 17 17 static void smb2_close_cached_fid(struct kref *ref); 18 18 static void cfids_laundromat_worker(struct work_struct *work); 19 + static void close_cached_dir_locked(struct cached_fid *cfid); 19 20 20 21 struct cached_dir_dentry { 21 22 struct list_head entry; ··· 389 388 * lease. Release one here, and the second below. 390 389 */ 391 390 cfid->has_lease = false; 392 - close_cached_dir(cfid); 391 + close_cached_dir_locked(cfid); 393 392 } 394 393 spin_unlock(&cfids->cfid_list_lock); 395 394 ··· 481 480 spin_lock(&cfid->cfids->cfid_list_lock); 482 481 if (cfid->has_lease) { 483 482 cfid->has_lease = false; 484 - close_cached_dir(cfid); 483 + close_cached_dir_locked(cfid); 485 484 } 486 485 spin_unlock(&cfid->cfids->cfid_list_lock); 487 486 close_cached_dir(cfid); 488 487 } 489 488 490 - 489 + /** 490 + * close_cached_dir - drop a reference of a cached dir 491 + * 492 + * The release function will be called with cfid_list_lock held to remove the 493 + * cached dirs from the list before any other thread can take another @cfid 494 + * ref. Must not be called with cfid_list_lock held; use 495 + * close_cached_dir_locked() called instead. 496 + * 497 + * @cfid: cached dir 498 + */ 491 499 void close_cached_dir(struct cached_fid *cfid) 492 500 { 501 + lockdep_assert_not_held(&cfid->cfids->cfid_list_lock); 493 502 kref_put_lock(&cfid->refcount, smb2_close_cached_fid, &cfid->cfids->cfid_list_lock); 503 + } 504 + 505 + /** 506 + * close_cached_dir_locked - put a reference of a cached dir with 507 + * cfid_list_lock held 508 + * 509 + * Calling close_cached_dir() with cfid_list_lock held has the potential effect 510 + * of causing a deadlock if the invariant of refcount >= 2 is false. 511 + * 512 + * This function is used in paths that hold cfid_list_lock and expect at least 513 + * two references. If that invariant is violated, WARNs and returns without 514 + * dropping a reference; the final put must still go through 515 + * close_cached_dir(). 516 + * 517 + * @cfid: cached dir 518 + */ 519 + static void close_cached_dir_locked(struct cached_fid *cfid) 520 + { 521 + lockdep_assert_held(&cfid->cfids->cfid_list_lock); 522 + 523 + if (WARN_ON(kref_read(&cfid->refcount) < 2)) 524 + return; 525 + 526 + kref_put(&cfid->refcount, smb2_close_cached_fid); 494 527 } 495 528 496 529 /*
+22
fs/smb/client/cifssmb.c
··· 1363 1363 if (rdata->result == -ENODATA) { 1364 1364 rdata->result = 0; 1365 1365 __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags); 1366 + trace_smb3_read_err(rdata->rreq->debug_id, 1367 + rdata->subreq.debug_index, 1368 + rdata->xid, 1369 + rdata->req->cfile->fid.persistent_fid, 1370 + tcon->tid, tcon->ses->Suid, 1371 + rdata->subreq.start + rdata->subreq.transferred, 1372 + rdata->subreq.len - rdata->subreq.transferred, 1373 + rdata->result); 1366 1374 } else { 1367 1375 size_t trans = rdata->subreq.transferred + rdata->got_bytes; 1368 1376 if (trans < rdata->subreq.len && ··· 1382 1374 } 1383 1375 if (rdata->got_bytes) 1384 1376 __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags); 1377 + trace_smb3_read_done(rdata->rreq->debug_id, 1378 + rdata->subreq.debug_index, 1379 + rdata->xid, 1380 + rdata->req->cfile->fid.persistent_fid, 1381 + tcon->tid, tcon->ses->Suid, 1382 + rdata->subreq.start + rdata->subreq.transferred, 1383 + rdata->got_bytes); 1385 1384 } 1386 1385 1387 1386 trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value, ··· 1459 1444 rdata->iov[0].iov_len = 4; 1460 1445 rdata->iov[1].iov_base = (char *)smb + 4; 1461 1446 rdata->iov[1].iov_len = get_rfc1002_length(smb); 1447 + 1448 + trace_smb3_read_enter(rdata->rreq->debug_id, 1449 + rdata->subreq.debug_index, 1450 + rdata->xid, 1451 + rdata->req->cfile->fid.netfid, 1452 + tcon->tid, tcon->ses->Suid, 1453 + rdata->subreq.start, rdata->subreq.len); 1462 1454 1463 1455 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, 1464 1456 cifs_readv_callback, NULL, rdata, 0, NULL);
+4
fs/smb/client/fs_context.c
··· 1834 1834 ctx->password = NULL; 1835 1835 kfree_sensitive(ctx->password2); 1836 1836 ctx->password2 = NULL; 1837 + kfree(ctx->source); 1838 + ctx->source = NULL; 1839 + kfree(fc->source); 1840 + fc->source = NULL; 1837 1841 return -EINVAL; 1838 1842 } 1839 1843