Print this page
Kill flags arg in smbfs_purge_caches
Lots of comment cleanup
5404 smbfs needs mmap support
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
          +++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
↓ open down ↓ 60 lines elided ↑ open up ↑
  61   61  #include <smbfs/smbfs_subr.h>
  62   62  
  63   63  #include <vm/hat.h>
  64   64  #include <vm/as.h>
  65   65  #include <vm/page.h>
  66   66  #include <vm/pvn.h>
  67   67  #include <vm/seg.h>
  68   68  #include <vm/seg_map.h>
  69   69  #include <vm/seg_vn.h>
  70   70  
       71 +#define ATTRCACHE_VALID(vp)     (gethrtime() < VTOSMB(vp)->r_attrtime)
       72 +
  71   73  static int smbfs_getattr_cache(vnode_t *, smbfattr_t *);
  72   74  static void smbfattr_to_vattr(vnode_t *, smbfattr_t *, vattr_t *);
  73   75  static void smbfattr_to_xvattr(smbfattr_t *, vattr_t *);
       76 +static int smbfs_getattr_otw(vnode_t *, struct smbfattr *, cred_t *);
  74   77  
       78 +
  75   79  /*
  76   80   * The following code provide zone support in order to perform an action
  77   81   * for each smbfs mount in a zone.  This is also where we would add
  78   82   * per-zone globals and kernel threads for the smbfs module (since
  79   83   * they must be terminated by the shutdown callback).
  80   84   */
  81   85  
  82   86  struct smi_globals {
  83   87          kmutex_t        smg_lock;  /* lock protecting smg_list */
  84   88          list_t          smg_list;  /* list of SMBFS mounts in zone */
↓ open down ↓ 10 lines elided ↑ open up ↑
  95   99   * There is a time associated with the cached attributes (r_attrtime)
  96  100   * which tells whether the attributes are valid. The time is initialized
  97  101   * to the difference between current time and the modify time of the vnode
  98  102   * when new attributes are cached. This allows the attributes for
  99  103   * files that have changed recently to be timed out sooner than for files
 100  104   * that have not changed for a long time. There are minimum and maximum
 101  105   * timeout values that can be set per mount point.
 102  106   */
 103  107  
 104  108  /*
 105      - * Validate caches by checking cached attributes. If they have timed out
 106      - * get the attributes from the server and compare mtimes. If mtimes are
 107      - * different purge all caches for this vnode.
      109 + * Helper for _validate_caches
 108  110   */
 109  111  int
      112 +smbfs_waitfor_purge_complete(vnode_t *vp)
      113 +{
      114 +        smbnode_t *np;
      115 +        k_sigset_t smask;
      116 +
      117 +        np = VTOSMB(vp);
      118 +        if (np->r_serial != NULL && np->r_serial != curthread) {
      119 +                mutex_enter(&np->r_statelock);
      120 +                sigintr(&smask, VTOSMI(vp)->smi_flags & SMI_INT);
      121 +                while (np->r_serial != NULL) {
      122 +                        if (!cv_wait_sig(&np->r_cv, &np->r_statelock)) {
      123 +                                sigunintr(&smask);
      124 +                                mutex_exit(&np->r_statelock);
      125 +                                return (EINTR);
      126 +                        }
      127 +                }
      128 +                sigunintr(&smask);
      129 +                mutex_exit(&np->r_statelock);
      130 +        }
      131 +        return (0);
      132 +}
      133 +
      134 +/*
      135 + * Validate caches by checking cached attributes. If the cached
      136 + * attributes have timed out, then get new attributes from the server.
      137 + * As a side affect, this will do cache invalidation if the attributes
      138 + * have changed.
      139 + *
      140 + * If the attributes have not timed out and if there is a cache
      141 + * invalidation being done by some other thread, then wait until that
      142 + * thread has completed the cache invalidation.
      143 + */
      144 +int
 110  145  smbfs_validate_caches(
 111  146          struct vnode *vp,
 112  147          cred_t *cr)
 113  148  {
 114      -        struct vattr va;
      149 +        struct smbfattr fa;
      150 +        int error;
 115  151  
 116      -        va.va_mask = AT_SIZE;
 117      -        return (smbfsgetattr(vp, &va, cr));
      152 +        if (ATTRCACHE_VALID(vp)) {
      153 +                error = smbfs_waitfor_purge_complete(vp);
      154 +                if (error)
      155 +                        return (error);
      156 +                return (0);
      157 +        }
      158 +
      159 +        return (smbfs_getattr_otw(vp, &fa, cr));
 118  160  }
 119  161  
 120  162  /*
 121  163   * Purge all of the various data caches.
      164 + *
      165 + * Here NFS also had a flags arg to control what gets flushed.
      166 + * We only have the page cache, so no flags arg.
 122  167   */
 123      -/*ARGSUSED*/
      168 +/* ARGSUSED */
 124  169  void
 125      -smbfs_purge_caches(struct vnode *vp)
      170 +smbfs_purge_caches(struct vnode *vp, cred_t *cr)
 126  171  {
 127      -#if 0   /* not yet: mmap support */
      172 +
 128  173          /*
 129      -         * NFS: Purge the DNLC for this vp,
      174 +         * Here NFS has: Purge the DNLC for this vp,
 130  175           * Clear any readdir state bits,
 131  176           * the readlink response cache, ...
 132  177           */
 133      -        smbnode_t *np = VTOSMB(vp);
 134  178  
 135  179          /*
 136  180           * Flush the page cache.
 137  181           */
 138  182          if (vn_has_cached_data(vp)) {
 139  183                  (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL);
 140  184          }
 141      -#endif  /* not yet */
      185 +
      186 +        /*
      187 +         * Here NFS has: Flush the readdir response cache.
      188 +         * No readdir cache in smbfs.
      189 +         */
 142  190  }
 143  191  
 144  192  /*
      193 + * Here NFS has:
      194 + * nfs_purge_rddir_cache()
      195 + * nfs3_cache_post_op_attr()
      196 + * nfs3_cache_post_op_vattr()
      197 + * nfs3_cache_wcc_data()
      198 + */
      199 +
      200 +/*
 145  201   * Check the attribute cache to see if the new attributes match
 146  202   * those cached.  If they do, the various `data' caches are
 147  203   * considered to be good.  Otherwise, purge the cached data.
 148  204   */
 149      -void
      205 +static void
 150  206  smbfs_cache_check(
 151  207          struct vnode *vp,
 152      -        struct smbfattr *fap)
      208 +        struct smbfattr *fap,
      209 +        cred_t *cr)
 153  210  {
 154  211          smbnode_t *np;
 155  212          int purge_data = 0;
 156  213          int purge_acl = 0;
 157  214  
 158  215          np = VTOSMB(vp);
 159  216          mutex_enter(&np->r_statelock);
 160  217  
 161  218          /*
 162  219           * Compare with NFS macro: CACHE_VALID
↓ open down ↓ 4 lines elided ↑ open up ↑
 167  224              np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec)
 168  225                  purge_data = 1;
 169  226          if (np->r_attr.fa_size != fap->fa_size)
 170  227                  purge_data = 1;
 171  228  
 172  229          if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec ||
 173  230              np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec)
 174  231                  purge_acl = 1;
 175  232  
 176  233          if (purge_acl) {
 177      -                /* just invalidate r_secattr (XXX: OK?) */
 178  234                  np->r_sectime = gethrtime();
 179  235          }
 180  236  
 181  237          mutex_exit(&np->r_statelock);
 182  238  
 183  239          if (purge_data)
 184      -                smbfs_purge_caches(vp);
      240 +                smbfs_purge_caches(vp, cr);
 185  241  }
 186  242  
 187  243  /*
 188      - * Set attributes cache for given vnode using vnode attributes.
 189      - * From NFS: nfs_attrcache_va
 190      - */
 191      -#if 0   /* not yet (not sure if we need this) */
 192      -void
 193      -smbfs_attrcache_va(vnode_t *vp, struct vattr *vap)
 194      -{
 195      -        smbfattr_t fa;
 196      -        smbnode_t *np;
 197      -
 198      -        vattr_to_fattr(vp, vap, &fa);
 199      -        smbfs_attrcache_fa(vp, &fa);
 200      -}
 201      -#endif  /* not yet */
 202      -
 203      -/*
 204  244   * Set attributes cache for given vnode using SMB fattr
 205  245   * and update the attribute cache timeout.
 206  246   *
 207      - * From NFS: nfs_attrcache, nfs_attrcache_va
      247 + * Based on NFS: nfs_attrcache, nfs_attrcache_va
 208  248   */
 209  249  void
 210  250  smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
 211  251  {
 212  252          smbnode_t *np;
 213  253          smbmntinfo_t *smi;
 214  254          hrtime_t delta, now;
 215  255          u_offset_t newsize;
 216  256          vtype_t  vtype, oldvt;
 217  257          mode_t mode;
↓ open down ↓ 68 lines elided ↑ open up ↑
 286  326           *
 287  327           * Also deal with the fact that SMB presents
 288  328           * directories as having size=0.  Doing that
 289  329           * here and leaving fa_size as returned OtW
 290  330           * avoids fixing the size lots of places.
 291  331           */
 292  332          newsize = fap->fa_size;
 293  333          if (vtype == VDIR && newsize < DEV_BSIZE)
 294  334                  newsize = DEV_BSIZE;
 295  335  
 296      -        if (np->r_size != newsize) {
 297      -#if 0   /* not yet: mmap support */
 298      -                if (!vn_has_cached_data(vp) || ...)
 299      -                        /* XXX: See NFS page cache code. */
 300      -#endif  /* not yet */
      336 +        if (np->r_size != newsize &&
      337 +            (!vn_has_cached_data(vp) ||
      338 +            (!(np->r_flags & RDIRTY) && np->r_count == 0))) {
 301  339                  /* OK to set the size. */
 302  340                  np->r_size = newsize;
 303  341          }
 304  342  
 305      -        /* NFS: np->r_flags &= ~RWRITEATTR; */
 306      -        np->n_flag &= ~NATTRCHANGED;
      343 +        /*
      344 +         * Here NFS has:
      345 +         * nfs_setswaplike(vp, va);
      346 +         * np->r_flags &= ~RWRITEATTR;
      347 +         * (not needed here)
      348 +         */
 307  349  
      350 +        np->n_flag &= ~NATTRCHANGED;
 308  351          mutex_exit(&np->r_statelock);
 309  352  
 310  353          if (oldvt != vtype) {
 311  354                  SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype);
 312  355          }
 313  356  }
 314  357  
 315  358  /*
 316  359   * Fill in attribute from the cache.
 317  360   *
↓ open down ↓ 23 lines elided ↑ open up ↑
 341  384  
 342  385          return (error);
 343  386  }
 344  387  
 345  388  /*
 346  389   * Get attributes over-the-wire and update attributes cache
 347  390   * if no error occurred in the over-the-wire operation.
 348  391   * Return 0 if successful, otherwise error.
 349  392   * From NFS: nfs_getattr_otw
 350  393   */
 351      -int
      394 +static int
 352  395  smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
 353  396  {
 354  397          struct smbnode *np;
 355  398          struct smb_cred scred;
 356  399          int error;
 357  400  
 358  401          np = VTOSMB(vp);
 359  402  
 360  403          /*
 361      -         * NFS uses the ACL rpc here (if smi_flags & SMI_ACL)
      404 +         * Here NFS uses the ACL RPC (if smi_flags & SMI_ACL)
 362  405           * With SMB, getting the ACL is a significantly more
 363  406           * expensive operation, so we do that only when asked
 364  407           * for the uid/gid.  See smbfsgetattr().
 365  408           */
 366  409  
 367  410          /* Shared lock for (possible) n_fid use. */
 368  411          if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 369  412                  return (EINTR);
 370  413          smb_credinit(&scred, cr);
 371  414  
 372  415          bzero(fap, sizeof (*fap));
 373  416          error = smbfs_smb_getfattr(np, fap, &scred);
 374  417  
 375  418          smb_credrele(&scred);
 376  419          smbfs_rw_exit(&np->r_lkserlock);
 377  420  
 378  421          if (error) {
 379      -                /* NFS had: PURGE_STALE_FH(error, vp, cr) */
      422 +                /* Here NFS has: PURGE_STALE_FH(error, vp, cr) */
 380  423                  smbfs_attrcache_remove(np);
 381  424                  if (error == ENOENT || error == ENOTDIR) {
 382  425                          /*
 383  426                           * Getattr failed because the object was
 384  427                           * removed or renamed by another client.
 385  428                           * Remove any cached attributes under it.
 386  429                           */
 387  430                          smbfs_attrcache_prune(np);
 388  431                  }
 389  432                  return (error);
 390  433          }
 391  434  
 392  435          /*
 393      -         * NFS: smbfs_cache_fattr(vap, fa, vap, t, cr);
      436 +         * Here NFS has: nfs_cache_fattr(vap, fa, vap, t, cr);
 394  437           * which did: fattr_to_vattr, nfs_attr_cache.
 395  438           * We cache the fattr form, so just do the
 396  439           * cache check and store the attributes.
 397  440           */
 398      -        smbfs_cache_check(vp, fap);
      441 +        smbfs_cache_check(vp, fap, cr);
 399  442          smbfs_attrcache_fa(vp, fap);
 400  443  
 401  444          return (0);
 402  445  }
 403  446  
 404  447  /*
 405      - * Return either cached or remote attributes. If get remote attr
      448 + * Return either cached or remote attributes. If we get remote attrs,
 406  449   * use them to check and invalidate caches, then cache the new attributes.
 407  450   *
 408  451   * From NFS: nfsgetattr()
 409  452   */
 410  453  int
 411  454  smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
 412  455  {
 413  456          struct smbfattr fa;
 414  457          smbmntinfo_t *smi;
 415  458          uint_t mask;
↓ open down ↓ 126 lines elided ↑ open up ↑
 542  585                      ((fa->fa_attr & SMB_FA_RDONLY) != 0);
 543  586                  XVA_SET_RTN(xvap, XAT_READONLY);
 544  587          }
 545  588  
 546  589          if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
 547  590                  xoap->xoa_hidden =
 548  591                      ((fa->fa_attr & SMB_FA_HIDDEN) != 0);
 549  592                  XVA_SET_RTN(xvap, XAT_HIDDEN);
 550  593          }
 551  594  }
      595 +
      596 +/*
      597 + * Here NFS has:
      598 + *      nfs_async_... stuff
      599 + * which we're not using (no async I/O), and:
      600 + *      writerp(),
      601 + *      nfs_putpages()
      602 + *      nfs_invalidate_pages()
      603 + * which we have in smbfs_vnops.c, and
      604 + *      nfs_printfhandle()
      605 + *      nfs_write_error()
      606 + * not needed here.
      607 + */
      608 +
      609 +/*
      610 + * Helper function for smbfs_sync
      611 + *
      612 + * Walk the per-zone list of smbfs mounts, calling smbfs_rflush
      613 + * on each one.  This is a little tricky because we need to exit
      614 + * the list mutex before each _rflush call and then try to resume
      615 + * where we were in the list after re-entering the mutex.
      616 + */
      617 +void
      618 +smbfs_flushall(cred_t *cr)
      619 +{
      620 +        smi_globals_t *smg;
      621 +        smbmntinfo_t *tmp_smi, *cur_smi, *next_smi;
      622 +
      623 +        smg = zone_getspecific(smi_list_key, crgetzone(cr));
      624 +        ASSERT(smg != NULL);
      625 +
      626 +        mutex_enter(&smg->smg_lock);
      627 +        cur_smi = list_head(&smg->smg_list);
      628 +        if (cur_smi == NULL) {
      629 +                mutex_exit(&smg->smg_lock);
      630 +                return;
      631 +        }
      632 +        VFS_HOLD(cur_smi->smi_vfsp);
      633 +        mutex_exit(&smg->smg_lock);
      634 +
      635 +flush:
      636 +        smbfs_rflush(cur_smi->smi_vfsp, cr);
      637 +
      638 +        mutex_enter(&smg->smg_lock);
      639 +        /*
      640 +         * Resume after cur_smi if that's still on the list,
      641 +         * otherwise restart at the head.
      642 +         */
      643 +        for (tmp_smi = list_head(&smg->smg_list);
      644 +            tmp_smi != NULL;
      645 +            tmp_smi = list_next(&smg->smg_list, tmp_smi))
      646 +                if (tmp_smi == cur_smi)
      647 +                        break;
      648 +        if (tmp_smi != NULL)
      649 +                next_smi = list_next(&smg->smg_list, tmp_smi);
      650 +        else
      651 +                next_smi = list_head(&smg->smg_list);
      652 +
      653 +        if (next_smi != NULL)
      654 +                VFS_HOLD(next_smi->smi_vfsp);
      655 +        VFS_RELE(cur_smi->smi_vfsp);
      656 +
      657 +        mutex_exit(&smg->smg_lock);
      658 +
      659 +        if (next_smi != NULL) {
      660 +                cur_smi = next_smi;
      661 +                goto flush;
      662 +        }
      663 +}
 552  664  
 553  665  /*
 554  666   * SMB Client initialization and cleanup.
 555  667   * Much of it is per-zone now.
 556  668   */
 557  669  
 558  670  
 559  671  /* ARGSUSED */
 560  672  static void *
 561  673  smbfs_zone_init(zoneid_t zoneid)
↓ open down ↓ 181 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX