1// SPDX-License-Identifier: GPL-2.0 2/* 3 * DFS referral cache routines 4 * 5 * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de> 6 */ 7 8#include <linux/jhash.h> 9#include <linux/ktime.h> 10#include <linux/slab.h> 11#include <linux/proc_fs.h> 12#include <linux/nls.h> 13#include <linux/workqueue.h> 14#include "cifsglob.h" 15#include "smb2pdu.h" 16#include "smb2proto.h" 17#include "cifsproto.h" 18#include "cifs_debug.h" 19#include "cifs_unicode.h" 20#include "smb2glob.h" 21 22#include "dfs_cache.h" 23 24#define CACHE_HTABLE_SIZE 32 25#define CACHE_MAX_ENTRIES 64 26 27#define IS_INTERLINK_SET(v) ((v) & (DFSREF_REFERRAL_SERVER | \ 28 DFSREF_STORAGE_SERVER)) 29 30struct cache_dfs_tgt { 31 char *name; 32 int path_consumed; 33 struct list_head list; 34}; 35 36struct cache_entry { 37 struct hlist_node hlist; 38 const char *path; 39 int ttl; 40 int srvtype; 41 int flags; 42 struct timespec64 etime; 43 int path_consumed; 44 int numtgts; 45 struct list_head tlist; 46 struct cache_dfs_tgt *tgthint; 47}; 48 49struct vol_info { 50 char *fullpath; 51 spinlock_t smb_vol_lock; 52 struct smb_vol smb_vol; 53 char *mntdata; 54 struct list_head list; 55 struct list_head rlist; 56 struct kref refcnt; 57}; 58 59static struct kmem_cache *cache_slab __read_mostly; 60static struct workqueue_struct *dfscache_wq __read_mostly; 61 62static int cache_ttl; 63static DEFINE_SPINLOCK(cache_ttl_lock); 64 65static struct nls_table *cache_nlsc; 66 67/* 68 * Number of entries in the cache 69 */ 70static atomic_t cache_count; 71 72static struct hlist_head cache_htable[CACHE_HTABLE_SIZE]; 73static DECLARE_RWSEM(htable_rw_lock); 74 75static LIST_HEAD(vol_list); 76static DEFINE_SPINLOCK(vol_list_lock); 77 78static void refresh_cache_worker(struct work_struct *work); 79 80static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker); 81 82static int get_normalized_path(const char *path, char **npath) 83{ 84 if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/')) 85 return -EINVAL; 86 87 if (*path == '\\') { 88 *npath = (char *)path; 89 } else { 90 *npath = kstrndup(path, strlen(path), GFP_KERNEL); 91 if (!*npath) 92 return -ENOMEM; 93 convert_delimiter(*npath, '\\'); 94 } 95 return 0; 96} 97 98static inline void free_normalized_path(const char *path, char *npath) 99{ 100 if (path != npath) 101 kfree(npath); 102} 103 104static inline bool cache_entry_expired(const struct cache_entry *ce) 105{ 106 struct timespec64 ts; 107 108 ktime_get_coarse_real_ts64(&ts); 109 return timespec64_compare(&ts, &ce->etime) >= 0; 110} 111 112static inline void free_tgts(struct cache_entry *ce) 113{ 114 struct cache_dfs_tgt *t, *n; 115 116 list_for_each_entry_safe(t, n, &ce->tlist, list) { 117 list_del(&t->list); 118 kfree(t->name); 119 kfree(t); 120 } 121} 122 123static inline void flush_cache_ent(struct cache_entry *ce) 124{ 125 hlist_del_init(&ce->hlist); 126 kfree(ce->path); 127 free_tgts(ce); 128 atomic_dec(&cache_count); 129 kmem_cache_free(cache_slab, ce); 130} 131 132static void flush_cache_ents(void) 133{ 134 int i; 135 136 for (i = 0; i < CACHE_HTABLE_SIZE; i++) { 137 struct hlist_head *l = &cache_htable[i]; 138 struct hlist_node *n; 139 struct cache_entry *ce; 140 141 hlist_for_each_entry_safe(ce, n, l, hlist) { 142 if (!hlist_unhashed(&ce->hlist)) 143 flush_cache_ent(ce); 144 } 145 } 146} 147 148/* 149 * dfs cache /proc file 150 */ 151static int dfscache_proc_show(struct seq_file *m, void *v) 152{ 153 int i; 154 struct cache_entry *ce; 155 struct cache_dfs_tgt *t; 156 157 seq_puts(m, "DFS cache\n---------\n"); 158 159 down_read(&htable_rw_lock); 160 for (i = 0; i < CACHE_HTABLE_SIZE; i++) { 161 struct hlist_head *l = &cache_htable[i]; 162 163 hlist_for_each_entry(ce, l, hlist) { 164 if (hlist_unhashed(&ce->hlist)) 165 continue; 166 167 seq_printf(m, 168 "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," 169 "interlink=%s,path_consumed=%d,expired=%s\n", 170 ce->path, 171 ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", 172 ce->ttl, ce->etime.tv_nsec, 173 IS_INTERLINK_SET(ce->flags) ? "yes" : "no", 174 ce->path_consumed, 175 cache_entry_expired(ce) ? "yes" : "no"); 176 177 list_for_each_entry(t, &ce->tlist, list) { 178 seq_printf(m, " %s%s\n", 179 t->name, 180 ce->tgthint == t ? " (target hint)" : ""); 181 } 182 } 183 } 184 up_read(&htable_rw_lock); 185 186 return 0; 187} 188 189static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer, 190 size_t count, loff_t *ppos) 191{ 192 char c; 193 int rc; 194 195 rc = get_user(c, buffer); 196 if (rc) 197 return rc; 198 199 if (c != '0') 200 return -EINVAL; 201 202 cifs_dbg(FYI, "clearing dfs cache\n"); 203 204 down_write(&htable_rw_lock); 205 flush_cache_ents(); 206 up_write(&htable_rw_lock); 207 208 return count; 209} 210 211static int dfscache_proc_open(struct inode *inode, struct file *file) 212{ 213 return single_open(file, dfscache_proc_show, NULL); 214} 215 216const struct proc_ops dfscache_proc_ops = { 217 .proc_open = dfscache_proc_open, 218 .proc_read = seq_read, 219 .proc_lseek = seq_lseek, 220 .proc_release = single_release, 221 .proc_write = dfscache_proc_write, 222}; 223 224#ifdef CONFIG_CIFS_DEBUG2 225static inline void dump_tgts(const struct cache_entry *ce) 226{ 227 struct cache_dfs_tgt *t; 228 229 cifs_dbg(FYI, "target list:\n"); 230 list_for_each_entry(t, &ce->tlist, list) { 231 cifs_dbg(FYI, " %s%s\n", t->name, 232 ce->tgthint == t ? " (target hint)" : ""); 233 } 234} 235 236static inline void dump_ce(const struct cache_entry *ce) 237{ 238 cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,interlink=%s,path_consumed=%d,expired=%s\n", 239 ce->path, 240 ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, 241 ce->etime.tv_nsec, 242 IS_INTERLINK_SET(ce->flags) ? "yes" : "no", 243 ce->path_consumed, 244 cache_entry_expired(ce) ? "yes" : "no"); 245 dump_tgts(ce); 246} 247 248static inline void dump_refs(const struct dfs_info3_param *refs, int numrefs) 249{ 250 int i; 251 252 cifs_dbg(FYI, "DFS referrals returned by the server:\n"); 253 for (i = 0; i < numrefs; i++) { 254 const struct dfs_info3_param *ref = &refs[i]; 255 256 cifs_dbg(FYI, 257 "\n" 258 "flags: 0x%x\n" 259 "path_consumed: %d\n" 260 "server_type: 0x%x\n" 261 "ref_flag: 0x%x\n" 262 "path_name: %s\n" 263 "node_name: %s\n" 264 "ttl: %d (%dm)\n", 265 ref->flags, ref->path_consumed, ref->server_type, 266 ref->ref_flag, ref->path_name, ref->node_name, 267 ref->ttl, ref->ttl / 60); 268 } 269} 270#else 271#define dump_tgts(e) 272#define dump_ce(e) 273#define dump_refs(r, n) 274#endif 275 276/** 277 * dfs_cache_init - Initialize DFS referral cache. 278 * 279 * Return zero if initialized successfully, otherwise non-zero. 280 */ 281int dfs_cache_init(void) 282{ 283 int rc; 284 int i; 285 286 dfscache_wq = alloc_workqueue("cifs-dfscache", 287 WQ_FREEZABLE | WQ_MEM_RECLAIM, 1); 288 if (!dfscache_wq) 289 return -ENOMEM; 290 291 cache_slab = kmem_cache_create("cifs_dfs_cache", 292 sizeof(struct cache_entry), 0, 293 SLAB_HWCACHE_ALIGN, NULL); 294 if (!cache_slab) { 295 rc = -ENOMEM; 296 goto out_destroy_wq; 297 } 298 299 for (i = 0; i < CACHE_HTABLE_SIZE; i++) 300 INIT_HLIST_HEAD(&cache_htable[i]); 301 302 atomic_set(&cache_count, 0); 303 cache_nlsc = load_nls_default(); 304 305 cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__); 306 return 0; 307 308out_destroy_wq: 309 destroy_workqueue(dfscache_wq); 310 return rc; 311} 312 313static inline unsigned int cache_entry_hash(const void *data, int size) 314{ 315 unsigned int h; 316 317 h = jhash(data, size, 0); 318 return h & (CACHE_HTABLE_SIZE - 1); 319} 320 321/* Check whether second path component of @path is SYSVOL or NETLOGON */ 322static inline bool is_sysvol_or_netlogon(const char *path) 323{ 324 const char *s; 325 char sep = path[0]; 326 327 s = strchr(path + 1, sep) + 1; 328 return !strncasecmp(s, "sysvol", strlen("sysvol")) || 329 !strncasecmp(s, "netlogon", strlen("netlogon")); 330} 331 332/* Return target hint of a DFS cache entry */ 333static inline char *get_tgt_name(const struct cache_entry *ce) 334{ 335 struct cache_dfs_tgt *t = ce->tgthint; 336 337 return t ? t->name : ERR_PTR(-ENOENT); 338} 339 340/* Return expire time out of a new entry's TTL */ 341static inline struct timespec64 get_expire_time(int ttl) 342{ 343 struct timespec64 ts = { 344 .tv_sec = ttl, 345 .tv_nsec = 0, 346 }; 347 struct timespec64 now; 348 349 ktime_get_coarse_real_ts64(&now); 350 return timespec64_add(now, ts); 351} 352 353/* Allocate a new DFS target */ 354static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed) 355{ 356 struct cache_dfs_tgt *t; 357 358 t = kmalloc(sizeof(*t), GFP_ATOMIC); 359 if (!t) 360 return ERR_PTR(-ENOMEM); 361 t->name = kstrndup(name, strlen(name), GFP_ATOMIC); 362 if (!t->name) { 363 kfree(t); 364 return ERR_PTR(-ENOMEM); 365 } 366 t->path_consumed = path_consumed; 367 INIT_LIST_HEAD(&t->list); 368 return t; 369} 370 371/* 372 * Copy DFS referral information to a cache entry and conditionally update 373 * target hint. 374 */ 375static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, 376 struct cache_entry *ce, const char *tgthint) 377{ 378 int i; 379 380 ce->ttl = refs[0].ttl; 381 ce->etime = get_expire_time(ce->ttl); 382 ce->srvtype = refs[0].server_type; 383 ce->flags = refs[0].ref_flag; 384 ce->path_consumed = refs[0].path_consumed; 385 386 for (i = 0; i < numrefs; i++) { 387 struct cache_dfs_tgt *t; 388 389 t = alloc_target(refs[i].node_name, refs[i].path_consumed); 390 if (IS_ERR(t)) { 391 free_tgts(ce); 392 return PTR_ERR(t); 393 } 394 if (tgthint && !strcasecmp(t->name, tgthint)) { 395 list_add(&t->list, &ce->tlist); 396 tgthint = NULL; 397 } else { 398 list_add_tail(&t->list, &ce->tlist); 399 } 400 ce->numtgts++; 401 } 402 403 ce->tgthint = list_first_entry_or_null(&ce->tlist, 404 struct cache_dfs_tgt, list); 405 406 return 0; 407} 408 409/* Allocate a new cache entry */ 410static struct cache_entry *alloc_cache_entry(const char *path, 411 const struct dfs_info3_param *refs, 412 int numrefs) 413{ 414 struct cache_entry *ce; 415 int rc; 416 417 ce = kmem_cache_zalloc(cache_slab, GFP_KERNEL); 418 if (!ce) 419 return ERR_PTR(-ENOMEM); 420 421 ce->path = kstrndup(path, strlen(path), GFP_KERNEL); 422 if (!ce->path) { 423 kmem_cache_free(cache_slab, ce); 424 return ERR_PTR(-ENOMEM); 425 } 426 INIT_HLIST_NODE(&ce->hlist); 427 INIT_LIST_HEAD(&ce->tlist); 428 429 rc = copy_ref_data(refs, numrefs, ce, NULL); 430 if (rc) { 431 kfree(ce->path); 432 kmem_cache_free(cache_slab, ce); 433 ce = ERR_PTR(rc); 434 } 435 return ce; 436} 437 438/* Must be called with htable_rw_lock held */ 439static void remove_oldest_entry(void) 440{ 441 int i; 442 struct cache_entry *ce; 443 struct cache_entry *to_del = NULL; 444 445 for (i = 0; i < CACHE_HTABLE_SIZE; i++) { 446 struct hlist_head *l = &cache_htable[i]; 447 448 hlist_for_each_entry(ce, l, hlist) { 449 if (hlist_unhashed(&ce->hlist)) 450 continue; 451 if (!to_del || timespec64_compare(&ce->etime, 452 &to_del->etime) < 0) 453 to_del = ce; 454 } 455 } 456 457 if (!to_del) { 458 cifs_dbg(FYI, "%s: no entry to remove\n", __func__); 459 return; 460 } 461 462 cifs_dbg(FYI, "%s: removing entry\n", __func__); 463 dump_ce(to_del); 464 flush_cache_ent(to_del); 465} 466 467/* Add a new DFS cache entry */ 468static int add_cache_entry(const char *path, unsigned int hash, 469 struct dfs_info3_param *refs, int numrefs) 470{ 471 struct cache_entry *ce; 472 473 ce = alloc_cache_entry(path, refs, numrefs); 474 if (IS_ERR(ce)) 475 return PTR_ERR(ce); 476 477 spin_lock(&cache_ttl_lock); 478 if (!cache_ttl) { 479 cache_ttl = ce->ttl; 480 queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); 481 } else { 482 cache_ttl = min_t(int, cache_ttl, ce->ttl); 483 mod_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); 484 } 485 spin_unlock(&cache_ttl_lock); 486 487 down_write(&htable_rw_lock); 488 hlist_add_head(&ce->hlist, &cache_htable[hash]); 489 dump_ce(ce); 490 up_write(&htable_rw_lock); 491 492 return 0; 493} 494 495static struct cache_entry *__lookup_cache_entry(const char *path) 496{ 497 struct cache_entry *ce; 498 unsigned int h; 499 bool found = false; 500 501 h = cache_entry_hash(path, strlen(path)); 502 503 hlist_for_each_entry(ce, &cache_htable[h], hlist) { 504 if (!strcasecmp(path, ce->path)) { 505 found = true; 506 dump_ce(ce); 507 break; 508 } 509 } 510 511 if (!found) 512 ce = ERR_PTR(-ENOENT); 513 return ce; 514} 515 516/* 517 * Find a DFS cache entry in hash table and optionally check prefix path against 518 * @path. 519 * Use whole path components in the match. 520 * Must be called with htable_rw_lock held. 521 * 522 * Return ERR_PTR(-ENOENT) if the entry is not found. 523 */ 524static struct cache_entry *lookup_cache_entry(const char *path, unsigned int *hash) 525{ 526 struct cache_entry *ce = ERR_PTR(-ENOENT); 527 unsigned int h; 528 int cnt = 0; 529 char *npath; 530 char *s, *e; 531 char sep; 532 533 npath = kstrndup(path, strlen(path), GFP_KERNEL); 534 if (!npath) 535 return ERR_PTR(-ENOMEM); 536 537 s = npath; 538 sep = *npath; 539 while ((s = strchr(s, sep)) && ++cnt < 3) 540 s++; 541 542 if (cnt < 3) { 543 h = cache_entry_hash(path, strlen(path)); 544 ce = __lookup_cache_entry(path); 545 goto out; 546 } 547 /* 548 * Handle paths that have more than two path components and are a complete prefix of the DFS 549 * referral request path (@path). 550 * 551 * See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request". 552 */ 553 h = cache_entry_hash(npath, strlen(npath)); 554 e = npath + strlen(npath) - 1; 555 while (e > s) { 556 char tmp; 557 558 /* skip separators */ 559 while (e > s && *e == sep) 560 e--; 561 if (e == s) 562 goto out; 563 564 tmp = *(e+1); 565 *(e+1) = 0; 566 567 ce = __lookup_cache_entry(npath); 568 if (!IS_ERR(ce)) { 569 h = cache_entry_hash(npath, strlen(npath)); 570 break; 571 } 572 573 *(e+1) = tmp; 574 /* backward until separator */ 575 while (e > s && *e != sep) 576 e--; 577 } 578out: 579 if (hash) 580 *hash = h; 581 kfree(npath); 582 return ce; 583} 584 585static void __vol_release(struct vol_info *vi) 586{ 587 kfree(vi->fullpath); 588 kfree(vi->mntdata); 589 cifs_cleanup_volume_info_contents(&vi->smb_vol); 590 kfree(vi); 591} 592 593static void vol_release(struct kref *kref) 594{ 595 struct vol_info *vi = container_of(kref, struct vol_info, refcnt); 596 597 spin_lock(&vol_list_lock); 598 list_del(&vi->list); 599 spin_unlock(&vol_list_lock); 600 __vol_release(vi); 601} 602 603static inline void free_vol_list(void) 604{ 605 struct vol_info *vi, *nvi; 606 607 list_for_each_entry_safe(vi, nvi, &vol_list, list) { 608 list_del_init(&vi->list); 609 __vol_release(vi); 610 } 611} 612 613/** 614 * dfs_cache_destroy - destroy DFS referral cache 615 */ 616void dfs_cache_destroy(void) 617{ 618 cancel_delayed_work_sync(&refresh_task); 619 unload_nls(cache_nlsc); 620 free_vol_list(); 621 flush_cache_ents(); 622 kmem_cache_destroy(cache_slab); 623 destroy_workqueue(dfscache_wq); 624 625 cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__); 626} 627 628/* Must be called with htable_rw_lock held */ 629static int __update_cache_entry(const char *path, 630 const struct dfs_info3_param *refs, 631 int numrefs) 632{ 633 int rc; 634 struct cache_entry *ce; 635 char *s, *th = NULL; 636 637 ce = lookup_cache_entry(path, NULL); 638 if (IS_ERR(ce)) 639 return PTR_ERR(ce); 640 641 if (ce->tgthint) { 642 s = ce->tgthint->name; 643 th = kstrndup(s, strlen(s), GFP_ATOMIC); 644 if (!th) 645 return -ENOMEM; 646 } 647 648 free_tgts(ce); 649 ce->numtgts = 0; 650 651 rc = copy_ref_data(refs, numrefs, ce, th); 652 653 kfree(th); 654 655 return rc; 656} 657 658static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, 659 const struct nls_table *nls_codepage, int remap, 660 const char *path, struct dfs_info3_param **refs, 661 int *numrefs) 662{ 663 cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path); 664 665 if (!ses || !ses->server || !ses->server->ops->get_dfs_refer) 666 return -EOPNOTSUPP; 667 if (unlikely(!nls_codepage)) 668 return -EINVAL; 669 670 *refs = NULL; 671 *numrefs = 0; 672 673 return ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, 674 nls_codepage, remap); 675} 676 677/* Update an expired cache entry by getting a new DFS referral from server */ 678static int update_cache_entry(const char *path, 679 const struct dfs_info3_param *refs, 680 int numrefs) 681{ 682 683 int rc; 684 685 down_write(&htable_rw_lock); 686 rc = __update_cache_entry(path, refs, numrefs); 687 up_write(&htable_rw_lock); 688 689 return rc; 690} 691 692/* 693 * Find, create or update a DFS cache entry. 694 * 695 * If the entry wasn't found, it will create a new one. Or if it was found but 696 * expired, then it will update the entry accordingly. 697 * 698 * For interlinks, __cifs_dfs_mount() and expand_dfs_referral() are supposed to 699 * handle them properly. 700 */ 701static int __dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, 702 const struct nls_table *nls_codepage, int remap, 703 const char *path, bool noreq) 704{ 705 int rc; 706 unsigned int hash; 707 struct cache_entry *ce; 708 struct dfs_info3_param *refs = NULL; 709 int numrefs = 0; 710 bool newent = false; 711 712 cifs_dbg(FYI, "%s: search path: %s\n", __func__, path); 713 714 down_read(&htable_rw_lock); 715 716 ce = lookup_cache_entry(path, &hash); 717 718 /* 719 * If @noreq is set, no requests will be sent to the server. Just return 720 * the cache entry. 721 */ 722 if (noreq) { 723 up_read(&htable_rw_lock); 724 return PTR_ERR_OR_ZERO(ce); 725 } 726 727 if (!IS_ERR(ce)) { 728 if (!cache_entry_expired(ce)) { 729 dump_ce(ce); 730 up_read(&htable_rw_lock); 731 return 0; 732 } 733 } else { 734 newent = true; 735 } 736 737 up_read(&htable_rw_lock); 738 739 /* 740 * No entry was found. 741 * 742 * Request a new DFS referral in order to create a new cache entry, or 743 * updating an existing one. 744 */ 745 rc = get_dfs_referral(xid, ses, nls_codepage, remap, path, 746 &refs, &numrefs); 747 if (rc) 748 return rc; 749 750 dump_refs(refs, numrefs); 751 752 if (!newent) { 753 rc = update_cache_entry(path, refs, numrefs); 754 goto out_free_refs; 755 } 756 757 if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) { 758 cifs_dbg(FYI, "%s: reached max cache size (%d)\n", 759 __func__, CACHE_MAX_ENTRIES); 760 down_write(&htable_rw_lock); 761 remove_oldest_entry(); 762 up_write(&htable_rw_lock); 763 } 764 765 rc = add_cache_entry(path, hash, refs, numrefs); 766 if (!rc) 767 atomic_inc(&cache_count); 768 769out_free_refs: 770 free_dfs_info_array(refs, numrefs); 771 return rc; 772} 773 774/* 775 * Set up a DFS referral from a given cache entry. 776 * 777 * Must be called with htable_rw_lock held. 778 */ 779static int setup_referral(const char *path, struct cache_entry *ce, 780 struct dfs_info3_param *ref, const char *target) 781{ 782 int rc; 783 784 cifs_dbg(FYI, "%s: set up new ref\n", __func__); 785 786 memset(ref, 0, sizeof(*ref)); 787 788 ref->path_name = kstrndup(path, strlen(path), GFP_ATOMIC); 789 if (!ref->path_name) 790 return -ENOMEM; 791 792 ref->node_name = kstrndup(target, strlen(target), GFP_ATOMIC); 793 if (!ref->node_name) { 794 rc = -ENOMEM; 795 goto err_free_path; 796 } 797 798 ref->path_consumed = ce->path_consumed; 799 ref->ttl = ce->ttl; 800 ref->server_type = ce->srvtype; 801 ref->ref_flag = ce->flags; 802 803 return 0; 804 805err_free_path: 806 kfree(ref->path_name); 807 ref->path_name = NULL; 808 return rc; 809} 810 811/* Return target list of a DFS cache entry */ 812static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl) 813{ 814 int rc; 815 struct list_head *head = &tl->tl_list; 816 struct cache_dfs_tgt *t; 817 struct dfs_cache_tgt_iterator *it, *nit; 818 819 memset(tl, 0, sizeof(*tl)); 820 INIT_LIST_HEAD(head); 821 822 list_for_each_entry(t, &ce->tlist, list) { 823 it = kzalloc(sizeof(*it), GFP_ATOMIC); 824 if (!it) { 825 rc = -ENOMEM; 826 goto err_free_it; 827 } 828 829 it->it_name = kstrndup(t->name, strlen(t->name), GFP_ATOMIC); 830 if (!it->it_name) { 831 kfree(it); 832 rc = -ENOMEM; 833 goto err_free_it; 834 } 835 it->it_path_consumed = t->path_consumed; 836 837 if (ce->tgthint == t) 838 list_add(&it->it_list, head); 839 else 840 list_add_tail(&it->it_list, head); 841 } 842 843 tl->tl_numtgts = ce->numtgts; 844 845 return 0; 846 847err_free_it: 848 list_for_each_entry_safe(it, nit, head, it_list) { 849 kfree(it->it_name); 850 kfree(it); 851 } 852 return rc; 853} 854 855/** 856 * dfs_cache_find - find a DFS cache entry 857 * 858 * If it doesn't find the cache entry, then it will get a DFS referral 859 * for @path and create a new entry. 860 * 861 * In case the cache entry exists but expired, it will get a DFS referral 862 * for @path and then update the respective cache entry. 863 * 864 * These parameters are passed down to the get_dfs_refer() call if it 865 * needs to be issued: 866 * @xid: syscall xid 867 * @ses: smb session to issue the request on 868 * @nls_codepage: charset conversion 869 * @remap: path character remapping type 870 * @path: path to lookup in DFS referral cache. 871 * 872 * @ref: when non-NULL, store single DFS referral result in it. 873 * @tgt_list: when non-NULL, store complete DFS target list in it. 874 * 875 * Return zero if the target was found, otherwise non-zero. 876 */ 877int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, 878 const struct nls_table *nls_codepage, int remap, 879 const char *path, struct dfs_info3_param *ref, 880 struct dfs_cache_tgt_list *tgt_list) 881{ 882 int rc; 883 char *npath; 884 struct cache_entry *ce; 885 886 rc = get_normalized_path(path, &npath); 887 if (rc) 888 return rc; 889 890 rc = __dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); 891 if (rc) 892 goto out_free_path; 893 894 down_read(&htable_rw_lock); 895 896 ce = lookup_cache_entry(npath, NULL); 897 if (IS_ERR(ce)) { 898 up_read(&htable_rw_lock); 899 rc = PTR_ERR(ce); 900 goto out_free_path; 901 } 902 903 if (ref) 904 rc = setup_referral(path, ce, ref, get_tgt_name(ce)); 905 else 906 rc = 0; 907 if (!rc && tgt_list) 908 rc = get_targets(ce, tgt_list); 909 910 up_read(&htable_rw_lock); 911 912out_free_path: 913 free_normalized_path(path, npath); 914 return rc; 915} 916 917/** 918 * dfs_cache_noreq_find - find a DFS cache entry without sending any requests to 919 * the currently connected server. 920 * 921 * NOTE: This function will neither update a cache entry in case it was 922 * expired, nor create a new cache entry if @path hasn't been found. It heavily 923 * relies on an existing cache entry. 924 * 925 * @path: path to lookup in the DFS referral cache. 926 * @ref: when non-NULL, store single DFS referral result in it. 927 * @tgt_list: when non-NULL, store complete DFS target list in it. 928 * 929 * Return 0 if successful. 930 * Return -ENOENT if the entry was not found. 931 * Return non-zero for other errors. 932 */ 933int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref, 934 struct dfs_cache_tgt_list *tgt_list) 935{ 936 int rc; 937 char *npath; 938 struct cache_entry *ce; 939 940 rc = get_normalized_path(path, &npath); 941 if (rc) 942 return rc; 943 944 cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); 945 946 down_read(&htable_rw_lock); 947 948 ce = lookup_cache_entry(npath, NULL); 949 if (IS_ERR(ce)) { 950 rc = PTR_ERR(ce); 951 goto out_unlock; 952 } 953 954 if (ref) 955 rc = setup_referral(path, ce, ref, get_tgt_name(ce)); 956 else 957 rc = 0; 958 if (!rc && tgt_list) 959 rc = get_targets(ce, tgt_list); 960 961out_unlock: 962 up_read(&htable_rw_lock); 963 free_normalized_path(path, npath); 964 965 return rc; 966} 967 968/** 969 * dfs_cache_update_tgthint - update target hint of a DFS cache entry 970 * 971 * If it doesn't find the cache entry, then it will get a DFS referral for @path 972 * and create a new entry. 973 * 974 * In case the cache entry exists but expired, it will get a DFS referral 975 * for @path and then update the respective cache entry. 976 * 977 * @xid: syscall id 978 * @ses: smb session 979 * @nls_codepage: charset conversion 980 * @remap: type of character remapping for paths 981 * @path: path to lookup in DFS referral cache. 982 * @it: DFS target iterator 983 * 984 * Return zero if the target hint was updated successfully, otherwise non-zero. 985 */ 986int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses, 987 const struct nls_table *nls_codepage, int remap, 988 const char *path, 989 const struct dfs_cache_tgt_iterator *it) 990{ 991 int rc; 992 char *npath; 993 struct cache_entry *ce; 994 struct cache_dfs_tgt *t; 995 996 rc = get_normalized_path(path, &npath); 997 if (rc) 998 return rc; 999 1000 cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath); 1001 1002 rc = __dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); 1003 if (rc) 1004 goto out_free_path; 1005 1006 down_write(&htable_rw_lock); 1007 1008 ce = lookup_cache_entry(npath, NULL); 1009 if (IS_ERR(ce)) { 1010 rc = PTR_ERR(ce); 1011 goto out_unlock; 1012 } 1013 1014 t = ce->tgthint; 1015 1016 if (likely(!strcasecmp(it->it_name, t->name))) 1017 goto out_unlock; 1018 1019 list_for_each_entry(t, &ce->tlist, list) { 1020 if (!strcasecmp(t->name, it->it_name)) { 1021 ce->tgthint = t; 1022 cifs_dbg(FYI, "%s: new target hint: %s\n", __func__, 1023 it->it_name); 1024 break; 1025 } 1026 } 1027 1028out_unlock: 1029 up_write(&htable_rw_lock); 1030out_free_path: 1031 free_normalized_path(path, npath); 1032 1033 return rc; 1034} 1035 1036/** 1037 * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry 1038 * without sending any requests to the currently connected server. 1039 * 1040 * NOTE: This function will neither update a cache entry in case it was 1041 * expired, nor create a new cache entry if @path hasn't been found. It heavily 1042 * relies on an existing cache entry. 1043 * 1044 * @path: path to lookup in DFS referral cache. 1045 * @it: target iterator which contains the target hint to update the cache 1046 * entry with. 1047 * 1048 * Return zero if the target hint was updated successfully, otherwise non-zero. 1049 */ 1050int dfs_cache_noreq_update_tgthint(const char *path, 1051 const struct dfs_cache_tgt_iterator *it) 1052{ 1053 int rc; 1054 char *npath; 1055 struct cache_entry *ce; 1056 struct cache_dfs_tgt *t; 1057 1058 if (!it) 1059 return -EINVAL; 1060 1061 rc = get_normalized_path(path, &npath); 1062 if (rc) 1063 return rc; 1064 1065 cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); 1066 1067 down_write(&htable_rw_lock); 1068 1069 ce = lookup_cache_entry(npath, NULL); 1070 if (IS_ERR(ce)) { 1071 rc = PTR_ERR(ce); 1072 goto out_unlock; 1073 } 1074 1075 rc = 0; 1076 t = ce->tgthint; 1077 1078 if (unlikely(!strcasecmp(it->it_name, t->name))) 1079 goto out_unlock; 1080 1081 list_for_each_entry(t, &ce->tlist, list) { 1082 if (!strcasecmp(t->name, it->it_name)) { 1083 ce->tgthint = t; 1084 cifs_dbg(FYI, "%s: new target hint: %s\n", __func__, 1085 it->it_name); 1086 break; 1087 } 1088 } 1089 1090out_unlock: 1091 up_write(&htable_rw_lock); 1092 free_normalized_path(path, npath); 1093 1094 return rc; 1095} 1096 1097/** 1098 * dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given 1099 * target iterator (@it). 1100 * 1101 * @path: path to lookup in DFS referral cache. 1102 * @it: DFS target iterator. 1103 * @ref: DFS referral pointer to set up the gathered information. 1104 * 1105 * Return zero if the DFS referral was set up correctly, otherwise non-zero. 1106 */ 1107int dfs_cache_get_tgt_referral(const char *path, 1108 const struct dfs_cache_tgt_iterator *it, 1109 struct dfs_info3_param *ref) 1110{ 1111 int rc; 1112 char *npath; 1113 struct cache_entry *ce; 1114 1115 if (!it || !ref) 1116 return -EINVAL; 1117 1118 rc = get_normalized_path(path, &npath); 1119 if (rc) 1120 return rc; 1121 1122 cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); 1123 1124 down_read(&htable_rw_lock); 1125 1126 ce = lookup_cache_entry(npath, NULL); 1127 if (IS_ERR(ce)) { 1128 rc = PTR_ERR(ce); 1129 goto out_unlock; 1130 } 1131 1132 cifs_dbg(FYI, "%s: target name: %s\n", __func__, it->it_name); 1133 1134 rc = setup_referral(path, ce, ref, it->it_name); 1135 1136out_unlock: 1137 up_read(&htable_rw_lock); 1138 free_normalized_path(path, npath); 1139 1140 return rc; 1141} 1142 1143static int dup_vol(struct smb_vol *vol, struct smb_vol *new) 1144{ 1145 memcpy(new, vol, sizeof(*new)); 1146 1147 if (vol->username) { 1148 new->username = kstrndup(vol->username, strlen(vol->username), 1149 GFP_KERNEL); 1150 if (!new->username) 1151 return -ENOMEM; 1152 } 1153 if (vol->password) { 1154 new->password = kstrndup(vol->password, strlen(vol->password), 1155 GFP_KERNEL); 1156 if (!new->password) 1157 goto err_free_username; 1158 } 1159 if (vol->UNC) { 1160 cifs_dbg(FYI, "%s: vol->UNC: %s\n", __func__, vol->UNC); 1161 new->UNC = kstrndup(vol->UNC, strlen(vol->UNC), GFP_KERNEL); 1162 if (!new->UNC) 1163 goto err_free_password; 1164 } 1165 if (vol->domainname) { 1166 new->domainname = kstrndup(vol->domainname, 1167 strlen(vol->domainname), GFP_KERNEL); 1168 if (!new->domainname) 1169 goto err_free_unc; 1170 } 1171 if (vol->iocharset) { 1172 new->iocharset = kstrndup(vol->iocharset, 1173 strlen(vol->iocharset), GFP_KERNEL); 1174 if (!new->iocharset) 1175 goto err_free_domainname; 1176 } 1177 if (vol->prepath) { 1178 cifs_dbg(FYI, "%s: vol->prepath: %s\n", __func__, vol->prepath); 1179 new->prepath = kstrndup(vol->prepath, strlen(vol->prepath), 1180 GFP_KERNEL); 1181 if (!new->prepath) 1182 goto err_free_iocharset; 1183 } 1184 1185 return 0; 1186 1187err_free_iocharset: 1188 kfree(new->iocharset); 1189err_free_domainname: 1190 kfree(new->domainname); 1191err_free_unc: 1192 kfree(new->UNC); 1193err_free_password: 1194 kfree_sensitive(new->password); 1195err_free_username: 1196 kfree(new->username); 1197 kfree(new); 1198 return -ENOMEM; 1199} 1200 1201/** 1202 * dfs_cache_add_vol - add a cifs volume during mount() that will be handled by 1203 * DFS cache refresh worker. 1204 * 1205 * @mntdata: mount data. 1206 * @vol: cifs volume. 1207 * @fullpath: origin full path. 1208 * 1209 * Return zero if volume was set up correctly, otherwise non-zero. 1210 */ 1211int dfs_cache_add_vol(char *mntdata, struct smb_vol *vol, const char *fullpath) 1212{ 1213 int rc; 1214 struct vol_info *vi; 1215 1216 if (!vol || !fullpath || !mntdata) 1217 return -EINVAL; 1218 1219 cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); 1220 1221 vi = kzalloc(sizeof(*vi), GFP_KERNEL); 1222 if (!vi) 1223 return -ENOMEM; 1224 1225 vi->fullpath = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL); 1226 if (!vi->fullpath) { 1227 rc = -ENOMEM; 1228 goto err_free_vi; 1229 } 1230 1231 rc = dup_vol(vol, &vi->smb_vol); 1232 if (rc) 1233 goto err_free_fullpath; 1234 1235 vi->mntdata = mntdata; 1236 spin_lock_init(&vi->smb_vol_lock); 1237 kref_init(&vi->refcnt); 1238 1239 spin_lock(&vol_list_lock); 1240 list_add_tail(&vi->list, &vol_list); 1241 spin_unlock(&vol_list_lock); 1242 1243 return 0; 1244 1245err_free_fullpath: 1246 kfree(vi->fullpath); 1247err_free_vi: 1248 kfree(vi); 1249 return rc; 1250} 1251 1252/* Must be called with vol_list_lock held */ 1253static struct vol_info *find_vol(const char *fullpath) 1254{ 1255 struct vol_info *vi; 1256 1257 list_for_each_entry(vi, &vol_list, list) { 1258 cifs_dbg(FYI, "%s: vi->fullpath: %s\n", __func__, vi->fullpath); 1259 if (!strcasecmp(vi->fullpath, fullpath)) 1260 return vi; 1261 } 1262 return ERR_PTR(-ENOENT); 1263} 1264 1265/** 1266 * dfs_cache_update_vol - update vol info in DFS cache after failover 1267 * 1268 * @fullpath: fullpath to look up in volume list. 1269 * @server: TCP ses pointer. 1270 * 1271 * Return zero if volume was updated, otherwise non-zero. 1272 */ 1273int dfs_cache_update_vol(const char *fullpath, struct TCP_Server_Info *server) 1274{ 1275 struct vol_info *vi; 1276 1277 if (!fullpath || !server) 1278 return -EINVAL; 1279 1280 cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); 1281 1282 spin_lock(&vol_list_lock); 1283 vi = find_vol(fullpath); 1284 if (IS_ERR(vi)) { 1285 spin_unlock(&vol_list_lock); 1286 return PTR_ERR(vi); 1287 } 1288 kref_get(&vi->refcnt); 1289 spin_unlock(&vol_list_lock); 1290 1291 cifs_dbg(FYI, "%s: updating volume info\n", __func__); 1292 spin_lock(&vi->smb_vol_lock); 1293 memcpy(&vi->smb_vol.dstaddr, &server->dstaddr, 1294 sizeof(vi->smb_vol.dstaddr)); 1295 spin_unlock(&vi->smb_vol_lock); 1296 1297 kref_put(&vi->refcnt, vol_release); 1298 1299 return 0; 1300} 1301 1302/** 1303 * dfs_cache_del_vol - remove volume info in DFS cache during umount() 1304 * 1305 * @fullpath: fullpath to look up in volume list. 1306 */ 1307void dfs_cache_del_vol(const char *fullpath) 1308{ 1309 struct vol_info *vi; 1310 1311 if (!fullpath || !*fullpath) 1312 return; 1313 1314 cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); 1315 1316 spin_lock(&vol_list_lock); 1317 vi = find_vol(fullpath); 1318 spin_unlock(&vol_list_lock); 1319 1320 if (!IS_ERR(vi)) 1321 kref_put(&vi->refcnt, vol_release); 1322} 1323 1324/** 1325 * dfs_cache_get_tgt_share - parse a DFS target 1326 * 1327 * @path: DFS full path 1328 * @it: DFS target iterator. 1329 * @share: tree name. 1330 * @prefix: prefix path. 1331 * 1332 * Return zero if target was parsed correctly, otherwise non-zero. 1333 */ 1334int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, 1335 char **share, char **prefix) 1336{ 1337 char *s, sep, *p; 1338 size_t len; 1339 size_t plen1, plen2; 1340 1341 if (!it || !path || !share || !prefix || strlen(path) < it->it_path_consumed) 1342 return -EINVAL; 1343 1344 *share = NULL; 1345 *prefix = NULL; 1346 1347 sep = it->it_name[0]; 1348 if (sep != '\\' && sep != '/') 1349 return -EINVAL; 1350 1351 s = strchr(it->it_name + 1, sep); 1352 if (!s) 1353 return -EINVAL; 1354 1355 /* point to prefix in target node */ 1356 s = strchrnul(s + 1, sep); 1357 1358 /* extract target share */ 1359 *share = kstrndup(it->it_name, s - it->it_name, GFP_KERNEL); 1360 if (!*share) 1361 return -ENOMEM; 1362 1363 /* skip separator */ 1364 if (*s) 1365 s++; 1366 /* point to prefix in DFS path */ 1367 p = path + it->it_path_consumed; 1368 if (*p == sep) 1369 p++; 1370 1371 /* merge prefix paths from DFS path and target node */ 1372 plen1 = it->it_name + strlen(it->it_name) - s; 1373 plen2 = path + strlen(path) - p; 1374 if (plen1 || plen2) { 1375 len = plen1 + plen2 + 2; 1376 *prefix = kmalloc(len, GFP_KERNEL); 1377 if (!*prefix) { 1378 kfree(*share); 1379 *share = NULL; 1380 return -ENOMEM; 1381 } 1382 if (plen1) 1383 scnprintf(*prefix, len, "%.*s%c%.*s", (int)plen1, s, sep, (int)plen2, p); 1384 else 1385 strscpy(*prefix, p, len); 1386 } 1387 return 0; 1388} 1389 1390/* Get all tcons that are within a DFS namespace and can be refreshed */ 1391static void get_tcons(struct TCP_Server_Info *server, struct list_head *head) 1392{ 1393 struct cifs_ses *ses; 1394 struct cifs_tcon *tcon; 1395 1396 INIT_LIST_HEAD(head); 1397 1398 spin_lock(&cifs_tcp_ses_lock); 1399 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 1400 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 1401 if (!tcon->need_reconnect && !tcon->need_reopen_files && 1402 tcon->dfs_path) { 1403 tcon->tc_count++; 1404 list_add_tail(&tcon->ulist, head); 1405 } 1406 } 1407 if (ses->tcon_ipc && !ses->tcon_ipc->need_reconnect && 1408 ses->tcon_ipc->dfs_path) { 1409 list_add_tail(&ses->tcon_ipc->ulist, head); 1410 } 1411 } 1412 spin_unlock(&cifs_tcp_ses_lock); 1413} 1414 1415static bool is_dfs_link(const char *path) 1416{ 1417 char *s; 1418 1419 s = strchr(path + 1, '\\'); 1420 if (!s) 1421 return false; 1422 return !!strchr(s + 1, '\\'); 1423} 1424 1425static char *get_dfs_root(const char *path) 1426{ 1427 char *s, *npath; 1428 1429 s = strchr(path + 1, '\\'); 1430 if (!s) 1431 return ERR_PTR(-EINVAL); 1432 1433 s = strchr(s + 1, '\\'); 1434 if (!s) 1435 return ERR_PTR(-EINVAL); 1436 1437 npath = kstrndup(path, s - path, GFP_KERNEL); 1438 if (!npath) 1439 return ERR_PTR(-ENOMEM); 1440 1441 return npath; 1442} 1443 1444static inline void put_tcp_server(struct TCP_Server_Info *server) 1445{ 1446 cifs_put_tcp_session(server, 0); 1447} 1448 1449static struct TCP_Server_Info *get_tcp_server(struct smb_vol *vol) 1450{ 1451 struct TCP_Server_Info *server; 1452 1453 server = cifs_find_tcp_session(vol); 1454 if (IS_ERR_OR_NULL(server)) 1455 return NULL; 1456 1457 spin_lock(&GlobalMid_Lock); 1458 if (server->tcpStatus != CifsGood) { 1459 spin_unlock(&GlobalMid_Lock); 1460 put_tcp_server(server); 1461 return NULL; 1462 } 1463 spin_unlock(&GlobalMid_Lock); 1464 1465 return server; 1466} 1467 1468/* Find root SMB session out of a DFS link path */ 1469static struct cifs_ses *find_root_ses(struct vol_info *vi, 1470 struct cifs_tcon *tcon, 1471 const char *path) 1472{ 1473 char *rpath; 1474 int rc; 1475 struct cache_entry *ce; 1476 struct dfs_info3_param ref = {0}; 1477 char *mdata = NULL, *devname = NULL; 1478 struct TCP_Server_Info *server; 1479 struct cifs_ses *ses; 1480 struct smb_vol vol = {NULL}; 1481 1482 rpath = get_dfs_root(path); 1483 if (IS_ERR(rpath)) 1484 return ERR_CAST(rpath); 1485 1486 down_read(&htable_rw_lock); 1487 1488 ce = lookup_cache_entry(rpath, NULL); 1489 if (IS_ERR(ce)) { 1490 up_read(&htable_rw_lock); 1491 ses = ERR_CAST(ce); 1492 goto out; 1493 } 1494 1495 rc = setup_referral(path, ce, &ref, get_tgt_name(ce)); 1496 if (rc) { 1497 up_read(&htable_rw_lock); 1498 ses = ERR_PTR(rc); 1499 goto out; 1500 } 1501 1502 up_read(&htable_rw_lock); 1503 1504 mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref, 1505 &devname); 1506 free_dfs_info_param(&ref); 1507 1508 if (IS_ERR(mdata)) { 1509 ses = ERR_CAST(mdata); 1510 mdata = NULL; 1511 goto out; 1512 } 1513 1514 rc = cifs_setup_volume_info(&vol, mdata, devname, false); 1515 kfree(devname); 1516 1517 if (rc) { 1518 ses = ERR_PTR(rc); 1519 goto out; 1520 } 1521 1522 server = get_tcp_server(&vol); 1523 if (!server) { 1524 ses = ERR_PTR(-EHOSTDOWN); 1525 goto out; 1526 } 1527 1528 ses = cifs_get_smb_ses(server, &vol); 1529 1530out: 1531 cifs_cleanup_volume_info_contents(&vol); 1532 kfree(mdata); 1533 kfree(rpath); 1534 1535 return ses; 1536} 1537 1538/* Refresh DFS cache entry from a given tcon */ 1539static int refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) 1540{ 1541 int rc = 0; 1542 unsigned int xid; 1543 char *path, *npath; 1544 struct cache_entry *ce; 1545 struct cifs_ses *root_ses = NULL, *ses; 1546 struct dfs_info3_param *refs = NULL; 1547 int numrefs = 0; 1548 1549 xid = get_xid(); 1550 1551 path = tcon->dfs_path + 1; 1552 1553 rc = get_normalized_path(path, &npath); 1554 if (rc) 1555 goto out_free_xid; 1556 1557 down_read(&htable_rw_lock); 1558 1559 ce = lookup_cache_entry(npath, NULL); 1560 if (IS_ERR(ce)) { 1561 rc = PTR_ERR(ce); 1562 up_read(&htable_rw_lock); 1563 goto out_free_path; 1564 } 1565 1566 if (!cache_entry_expired(ce)) { 1567 up_read(&htable_rw_lock); 1568 goto out_free_path; 1569 } 1570 1571 up_read(&htable_rw_lock); 1572 1573 /* If it's a DFS Link, then use root SMB session for refreshing it */ 1574 if (is_dfs_link(npath)) { 1575 ses = root_ses = find_root_ses(vi, tcon, npath); 1576 if (IS_ERR(ses)) { 1577 rc = PTR_ERR(ses); 1578 root_ses = NULL; 1579 goto out_free_path; 1580 } 1581 } else { 1582 ses = tcon->ses; 1583 } 1584 1585 rc = get_dfs_referral(xid, ses, cache_nlsc, tcon->remap, npath, &refs, 1586 &numrefs); 1587 if (!rc) { 1588 dump_refs(refs, numrefs); 1589 rc = update_cache_entry(npath, refs, numrefs); 1590 free_dfs_info_array(refs, numrefs); 1591 } 1592 1593 if (root_ses) 1594 cifs_put_smb_ses(root_ses); 1595 1596out_free_path: 1597 free_normalized_path(path, npath); 1598 1599out_free_xid: 1600 free_xid(xid); 1601 return rc; 1602} 1603 1604/* 1605 * Worker that will refresh DFS cache based on lowest TTL value from a DFS 1606 * referral. 1607 */ 1608static void refresh_cache_worker(struct work_struct *work) 1609{ 1610 struct vol_info *vi, *nvi; 1611 struct TCP_Server_Info *server; 1612 LIST_HEAD(vols); 1613 LIST_HEAD(tcons); 1614 struct cifs_tcon *tcon, *ntcon; 1615 int rc; 1616 1617 /* 1618 * Find SMB volumes that are eligible (server->tcpStatus == CifsGood) 1619 * for refreshing. 1620 */ 1621 spin_lock(&vol_list_lock); 1622 list_for_each_entry(vi, &vol_list, list) { 1623 server = get_tcp_server(&vi->smb_vol); 1624 if (!server) 1625 continue; 1626 1627 kref_get(&vi->refcnt); 1628 list_add_tail(&vi->rlist, &vols); 1629 put_tcp_server(server); 1630 } 1631 spin_unlock(&vol_list_lock); 1632 1633 /* Walk through all TCONs and refresh any expired cache entry */ 1634 list_for_each_entry_safe(vi, nvi, &vols, rlist) { 1635 spin_lock(&vi->smb_vol_lock); 1636 server = get_tcp_server(&vi->smb_vol); 1637 spin_unlock(&vi->smb_vol_lock); 1638 1639 if (!server) 1640 goto next_vol; 1641 1642 get_tcons(server, &tcons); 1643 rc = 0; 1644 1645 list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { 1646 /* 1647 * Skip tcp server if any of its tcons failed to refresh 1648 * (possibily due to reconnects). 1649 */ 1650 if (!rc) 1651 rc = refresh_tcon(vi, tcon); 1652 1653 list_del_init(&tcon->ulist); 1654 cifs_put_tcon(tcon); 1655 } 1656 1657 put_tcp_server(server); 1658 1659next_vol: 1660 list_del_init(&vi->rlist); 1661 kref_put(&vi->refcnt, vol_release); 1662 } 1663 1664 spin_lock(&cache_ttl_lock); 1665 queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); 1666 spin_unlock(&cache_ttl_lock); 1667} 1668