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