Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs_log.c
          +++ new/usr/src/uts/common/fs/nfs/nfs_log.c
↓ open down ↓ 10 lines elided ↑ open up ↑
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
  22   23   * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  23   24   */
  24   25  
       26 +/*
       27 + * Copyright 2018 Nexenta Systems, Inc.
       28 + */
       29 +
  25   30  #include <sys/cred.h>
  26   31  #include <sys/cmn_err.h>
  27   32  #include <sys/debug.h>
  28   33  #include <sys/systm.h>
  29   34  #include <sys/kmem.h>
  30   35  #include <sys/disp.h>
  31   36  #include <sys/atomic.h>
  32   37  #include <rpc/types.h>
  33   38  #include <nfs/nfs.h>
  34   39  #include <nfs/nfssys.h>
↓ open down ↓ 1 lines elided ↑ open up ↑
  36   41  #include <nfs/rnode.h>
  37   42  #include <rpc/auth.h>
  38   43  #include <rpc/svc.h>
  39   44  #include <rpc/xdr.h>
  40   45  #include <rpc/clnt.h>
  41   46  #include <nfs/nfs_log.h>
  42   47  
  43   48  #define NUM_RECORDS_TO_WRITE 256
  44   49  #define NUM_BYTES_TO_WRITE 65536
  45   50  
  46      -extern krwlock_t exported_lock;
  47      -
  48   51  static int nfslog_num_records_to_write = NUM_RECORDS_TO_WRITE;
  49   52  static int nfslog_num_bytes_to_write = NUM_BYTES_TO_WRITE;
  50   53  
  51   54  /*
  52   55   * This struct is used to 'hide' the details of managing the log
  53   56   * records internally to the logging code.  Allocation routines
  54   57   * are used to obtain pieces of memory for XDR encoding.  This struct
  55   58   * is a 'header' to those areas and a opaque cookie is used to pass
  56   59   * this data structure between the allocating function and the put
  57   60   * function.
↓ open down ↓ 530 lines elided ↑ open up ↑
 588  591   *
 589  592   * Returns a pointer to the beginning of the allocated memory.
 590  593   * 'cookie' is a pointer to the 'lr_alloc' struct; this will be used
 591  594   * to keep track of the encoded record and contains all the info
 592  595   * for enqueuing the record on the log buffer for later writing.
 593  596   *
 594  597   * nfslog_record_put() must be used to 'free' this record or allocation.
 595  598   */
 596  599  /* ARGSUSED */
 597  600  void *
 598      -nfslog_record_alloc(
 599      -        struct exportinfo *exi,
 600      -        int alloc_indx,
 601      -        void **cookie,
 602      -        int flags)
      601 +nfslog_record_alloc(struct exportinfo *exi, int alloc_indx, void **cookie,
      602 +    int flags)
 603  603  {
 604  604          struct lr_alloc *lrp;
 605  605  
 606  606          lrp = (struct lr_alloc *)
 607  607              kmem_cache_alloc(nfslog_mem_alloc[alloc_indx].mem_cache,
 608  608              KM_NOSLEEP);
 609  609  
 610  610          if (lrp == NULL) {
 611  611                  *cookie = NULL;
 612  612                  return (NULL);
↓ open down ↓ 32 lines elided ↑ open up ↑
 645  645   * Size is the actual size of the record that was encoded.  This is
 646  646   * passed in because the size used for the alloc was just an approximation.
 647  647   * The sync parameter is used to tell us if we need to force this record
 648  648   * to disk and if not it will be queued for later writing.
 649  649   *
 650  650   * Note that if the size parameter has a value of 0, then the record is
 651  651   * not written to the log and the associated data structures are released.
 652  652   */
 653  653  void
 654  654  nfslog_record_put(void *cookie, size_t size, bool_t sync,
 655      -        unsigned int which_buffers)
      655 +    unsigned int which_buffers)
 656  656  {
 657  657          struct lr_alloc *lrp = (struct lr_alloc *)cookie;
 658  658          struct log_buffer *lbp = lrp->lb;
 659  659  
 660  660          /*
 661  661           * If the caller has nothing to write or if there is
 662  662           * an apparent error, rele the buffer and free.
 663  663           */
 664  664          if (size == 0 || size > lrp->size) {
 665  665                  nfslog_free_logrecords(lrp);
↓ open down ↓ 95 lines elided ↑ open up ↑
 761  761          return (error);
 762  762  }
 763  763  
 764  764  
 765  765  /*
 766  766   * Take care of writing the provided log record(s) to the log file.
 767  767   * We group the log records with an iovec and use VOP_WRITE to append
 768  768   * them to the end of the log file.
 769  769   */
 770  770  static int
 771      -nfslog_write_logrecords(struct log_file *lfp,
 772      -        struct lr_alloc *lrp_writers, int num_recs)
      771 +nfslog_write_logrecords(struct log_file *lfp, struct lr_alloc *lrp_writers,
      772 +    int num_recs)
 773  773  {
 774  774          struct uio uio;
 775  775          struct iovec *iovp;
 776  776          int size_iovecs;
 777  777          vnode_t *vp;
 778  778          struct vattr va;
 779  779          struct lr_alloc *lrp;
 780  780          int i;
 781  781          ssize_t len;
 782  782          int ioflag = FAPPEND;
↓ open down ↓ 371 lines elided ↑ open up ↑
1154 1154                   * Do the work synchronously
1155 1155                   */
1156 1156                  nfslog_do_flush(tparams);
1157 1157                  error = tparams->tp_error;
1158 1158                  kmem_free(nfsl_args->buff, nfsl_args->buff_len);
1159 1159                  kmem_free(tparams, sizeof (*tparams));
1160 1160          } else {
1161 1161                  /*
1162 1162                   * Do the work asynchronously
1163 1163                   */
1164      -                (void) thread_create(NULL, 0, nfslog_do_flush,
1165      -                    tparams, 0, &p0, TS_RUN, minclsyspri);
     1164 +                (void) zthread_create(NULL, 0, nfslog_do_flush,
     1165 +                    tparams, 0, minclsyspri);
1166 1166          }
1167 1167  
1168 1168          return (error);
1169 1169  }
1170 1170  
1171 1171  /*
1172 1172   * This is where buffer flushing would occur, but there is no buffering
1173 1173   * at this time.
1174 1174   * Possibly rename the log buffer for processing.
1175 1175   * Sets tparams->ta_error equal to the value of the error that occurred,
↓ open down ↓ 66 lines elided ↑ open up ↑
1242 1242  
1243 1243  out:
1244 1244          if ((args->directive & NFSL_SYNC) == 0) {
1245 1245                  /*
1246 1246                   * Work was performed asynchronously, the caller is
1247 1247                   * no longer waiting for us.
1248 1248                   * Free the thread arguments and exit.
1249 1249                   */
1250 1250                  kmem_free(args->buff, args->buff_len);
1251 1251                  kmem_free(tparams, sizeof (*tparams));
1252      -                thread_exit();
1253      -                /* NOTREACHED */
     1252 +                zthread_exit();
1254 1253          }
1255 1254  
1256 1255          tparams->tp_error = error;
1257 1256  }
1258 1257  
1259 1258  /*
1260 1259   * Generate buffer_header.
1261 1260   * 'loghdr' points the the buffer_header, and *reclen
1262 1261   * contains the length of the buffer.
1263 1262   */
↓ open down ↓ 258 lines elided ↑ open up ↑
1522 1521  
1523 1522  /*
1524 1523   * This function will determine the appropriate export info struct to use
1525 1524   * and allocate a record id to be used in the written log buffer.
1526 1525   * Usually this is a straightforward operation but the existence of the
1527 1526   * multicomponent lookup and its semantics of crossing file system
1528 1527   * boundaries add to the complexity.  See the comments below...
1529 1528   */
1530 1529  struct exportinfo *
1531 1530  nfslog_get_exi(
     1531 +        nfs_export_t *ne,
1532 1532          struct exportinfo *exi,
1533 1533          struct svc_req *req,
1534 1534          caddr_t res,
1535 1535          unsigned int *nfslog_rec_id)
1536 1536  {
1537 1537          struct log_buffer *lb;
1538 1538          struct exportinfo *exi_ret = NULL;
1539 1539          fhandle_t               *fh;
1540 1540          nfs_fh3                 *fh3;
1541 1541  
↓ open down ↓ 11 lines elided ↑ open up ↑
1553 1553  
1554 1554                  /*
1555 1555                   * The caller will expect to be able to exi_rele() it,
1556 1556                   * so exi->exi_count must be incremented before it can
1557 1557                   * be returned, to make it uniform with exi_ret->exi_count
1558 1558                   */
1559 1559                  exi_hold(exi);
1560 1560                  return (exi);
1561 1561          }
1562 1562  
1563      -        if (exi != exi_public)
     1563 +        if (exi != ne->exi_public)
1564 1564                  return (NULL);
1565 1565  
1566 1566          /*
1567 1567           * Here we have an exi that is not marked for logging.
1568 1568           * It is possible that this request is a multicomponent lookup
1569 1569           * that was done from the public file handle (not logged) and
1570 1570           * the resulting file handle being returned to the client exists
1571 1571           * in a file system that is being logged.  If this is the case
1572 1572           * we need to log this multicomponent lookup to the appropriate
1573 1573           * log buffer.  This will allow for the appropriate path name
↓ open down ↓ 44 lines elided ↑ open up ↑
1618 1618   * If logrecp is null, log it, otherwise, malloc the record and return it.
1619 1619   *
1620 1620   * It is the responsibility of the caller to check whether this exportinfo
1621 1621   * has logging enabled.
1622 1622   * Note that nfslog_share_public_record() only needs to check for the
1623 1623   * existence of at least one logbuffer to which the public filehandle record
1624 1624   * needs to be logged.
1625 1625   */
1626 1626  void
1627 1627  nfslog_write_record(struct exportinfo *exi, struct svc_req *req,
1628      -        caddr_t args, caddr_t res, cred_t *cr, struct netbuf *pnb,
1629      -        unsigned int record_id, unsigned int which_buffers)
     1628 +    caddr_t args, caddr_t res, cred_t *cr, struct netbuf *pnb,
     1629 +    unsigned int record_id, unsigned int which_buffers)
1630 1630  {
1631 1631          struct nfslog_prog_disp *progtable;     /* prog struct */
1632 1632          struct nfslog_vers_disp *verstable;     /* version struct */
1633 1633          struct nfslog_proc_disp *disp = NULL;   /* proc struct */
1634 1634          int                     i, vers;
1635 1635          void                    *log_cookie;    /* for logrecord if */
1636 1636          caddr_t                 buffer;
1637 1637          XDR                     xdrs;
1638 1638          unsigned int            final_size;
1639 1639          int                     encode_ok;
↓ open down ↓ 117 lines elided ↑ open up ↑
1757 1757           * If the record_id is 0 then this is most likely a share/unshare
1758 1758           * request and it should be written synchronously to the log file.
1759 1759           */
1760 1760          nfslog_record_put(log_cookie,
1761 1761              final_size, (record_id == 0), which_buffers);
1762 1762  }
1763 1763  
1764 1764  static char *
1765 1765  get_publicfh_path(int *alloc_length)
1766 1766  {
1767      -        extern struct exportinfo *exi_public;
1768 1767          char *pubpath;
     1768 +        nfs_export_t *ne = nfs_get_export();
1769 1769  
1770      -        rw_enter(&exported_lock, RW_READER);
     1770 +        rw_enter(&ne->exported_lock, RW_READER);
1771 1771  
1772      -        *alloc_length = exi_public->exi_export.ex_pathlen + 1;
     1772 +        *alloc_length = ne->exi_public->exi_export.ex_pathlen + 1;
1773 1773          pubpath = kmem_alloc(*alloc_length, KM_SLEEP);
1774 1774  
1775      -        (void) strcpy(pubpath, exi_public->exi_export.ex_path);
     1775 +        (void) strcpy(pubpath, ne->exi_public->exi_export.ex_path);
1776 1776  
1777      -        rw_exit(&exported_lock);
     1777 +        rw_exit(&ne->exported_lock);
1778 1778  
1779 1779          return (pubpath);
1780 1780  }
1781 1781  
1782 1782  static void
1783 1783  log_public_record(struct exportinfo *exi, cred_t *cr)
1784 1784  {
1785 1785          struct svc_req  req;
1786 1786          struct netbuf   nb = {0, 0, NULL};
1787 1787          int free_length = 0;
↓ open down ↓ 75 lines elided ↑ open up ↑
1863 1863          req.rq_prog = NFSLOG_PROGRAM;
1864 1864          req.rq_vers = NFSLOG_VERSION;
1865 1865          req.rq_proc = NFSLOG_UNSHARE;
1866 1866          req.rq_cred.oa_flavor = AUTH_NONE;
1867 1867          nfslog_write_record(exi, &req,
1868 1868              (caddr_t)exi, (caddr_t)&res, cr, &nb, 0, NFSLOG_ONE_BUFFER);
1869 1869  }
1870 1870  
1871 1871  
1872 1872  void
1873      -nfslog_getfh(struct exportinfo *exi,
1874      -        fhandle *fh,
1875      -        char *fname,
1876      -        enum uio_seg seg,
1877      -        cred_t *cr)
     1873 +nfslog_getfh(struct exportinfo *exi, fhandle *fh, char *fname, enum uio_seg seg,
     1874 +    cred_t *cr)
1878 1875  {
1879 1876          struct svc_req  req;
1880 1877          int             res = 0;
1881 1878          struct netbuf   nb = {0, 0, NULL};
1882 1879          int             error = 0;
1883 1880          char            *namebuf;
1884 1881          size_t          len;
1885 1882          nfslog_getfhargs gfh;
1886 1883  
1887 1884          ASSERT(exi != NULL);
↓ open down ↓ 24 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX