1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/cred.h>
26 #include <sys/cmn_err.h>
27 #include <sys/debug.h>
28 #include <sys/systm.h>
29 #include <sys/kmem.h>
30 #include <sys/disp.h>
31 #include <sys/atomic.h>
32 #include <rpc/types.h>
33 #include <nfs/nfs.h>
34 #include <nfs/nfssys.h>
35 #include <nfs/export.h>
36 #include <nfs/rnode.h>
37 #include <rpc/auth.h>
38 #include <rpc/svc.h>
39 #include <rpc/xdr.h>
40 #include <rpc/clnt.h>
41 #include <nfs/nfs_log.h>
42
43 #define NUM_RECORDS_TO_WRITE 256
44 #define NUM_BYTES_TO_WRITE 65536
45
46 extern krwlock_t exported_lock;
47
48 static int nfslog_num_records_to_write = NUM_RECORDS_TO_WRITE;
49 static int nfslog_num_bytes_to_write = NUM_BYTES_TO_WRITE;
50
51 /*
52 * This struct is used to 'hide' the details of managing the log
53 * records internally to the logging code. Allocation routines
54 * are used to obtain pieces of memory for XDR encoding. This struct
55 * is a 'header' to those areas and a opaque cookie is used to pass
56 * this data structure between the allocating function and the put
57 * function.
58 */
59 struct lr_alloc {
60 struct lr_alloc *next; /* links for write queuing */
61 struct lr_alloc *prev;
62 #define LR_ALLOC_NOFREE 0x1 /* not present, call free */
63 int lr_flags;
64 caddr_t log_record; /* address to XDR encoding */
65 size_t size; /* final size of encoding */
66 struct kmem_cache *alloc_cache; /* keep track of cache ptr */
67 struct exportinfo *exi; /* who are we related to? */
578 kmem_free(lfp, sizeof (*lfp));
579 rfsl_log_file--;
580 }
581
582 /*
583 * Allocates a record of the size specified.
584 * 'exi' identifies the exportinfo structure being logged.
585 * 'size' indicates how much memory should be allocated
586 * 'cookie' is used to store an opaque value for the caller for later use
587 * 'flags' currently ignored.
588 *
589 * Returns a pointer to the beginning of the allocated memory.
590 * 'cookie' is a pointer to the 'lr_alloc' struct; this will be used
591 * to keep track of the encoded record and contains all the info
592 * for enqueuing the record on the log buffer for later writing.
593 *
594 * nfslog_record_put() must be used to 'free' this record or allocation.
595 */
596 /* ARGSUSED */
597 void *
598 nfslog_record_alloc(
599 struct exportinfo *exi,
600 int alloc_indx,
601 void **cookie,
602 int flags)
603 {
604 struct lr_alloc *lrp;
605
606 lrp = (struct lr_alloc *)
607 kmem_cache_alloc(nfslog_mem_alloc[alloc_indx].mem_cache,
608 KM_NOSLEEP);
609
610 if (lrp == NULL) {
611 *cookie = NULL;
612 return (NULL);
613 }
614
615 lrp->next = lrp;
616 lrp->prev = lrp;
617 lrp->lr_flags = 0;
618
619 lrp->log_record = (caddr_t)((uintptr_t)lrp +
620 (uintptr_t)sizeof (struct lr_alloc));
621 lrp->size = nfslog_mem_alloc[alloc_indx].size;
751 lbp->lb_records = NULL;
752 num_recs = lbp->lb_num_recs;
753 lbp->lb_num_recs = 0;
754 lbp->lb_size_queued = 0;
755 mutex_exit(&lbp->lb_lock);
756 error = nfslog_write_logrecords(lfp, lrp_writers, num_recs);
757
758 LOG_FILE_UNLOCK_FROM_WRITE(lfp);
759
760 nfslog_free_logrecords(lrp_writers);
761 return (error);
762 }
763
764
765 /*
766 * Take care of writing the provided log record(s) to the log file.
767 * We group the log records with an iovec and use VOP_WRITE to append
768 * them to the end of the log file.
769 */
770 static int
771 nfslog_write_logrecords(struct log_file *lfp,
772 struct lr_alloc *lrp_writers, int num_recs)
773 {
774 struct uio uio;
775 struct iovec *iovp;
776 int size_iovecs;
777 vnode_t *vp;
778 struct vattr va;
779 struct lr_alloc *lrp;
780 int i;
781 ssize_t len;
782 int ioflag = FAPPEND;
783 int error = 0;
784
785 ASSERT(MUTEX_HELD(&lfp->lf_lock));
786
787 vp = lfp->lf_vp;
788
789 size_iovecs = sizeof (struct iovec) * num_recs;
790 iovp = (struct iovec *)kmem_alloc(size_iovecs, KM_NOSLEEP);
791
792 if (iovp == NULL) {
1144
1145 if (nfsl_args->buff_len != buffer_len)
1146 return (EFAULT);
1147 }
1148
1149 LOGGING_DPRINT((10, "nfsl_flush: Flushing %s buffer(s)\n",
1150 nfsl_args->directive & NFSL_ALL ? "all" : nfsl_args->buff));
1151
1152 if (nfsl_args->directive & NFSL_SYNC) {
1153 /*
1154 * Do the work synchronously
1155 */
1156 nfslog_do_flush(tparams);
1157 error = tparams->tp_error;
1158 kmem_free(nfsl_args->buff, nfsl_args->buff_len);
1159 kmem_free(tparams, sizeof (*tparams));
1160 } else {
1161 /*
1162 * Do the work asynchronously
1163 */
1164 (void) thread_create(NULL, 0, nfslog_do_flush,
1165 tparams, 0, &p0, TS_RUN, minclsyspri);
1166 }
1167
1168 return (error);
1169 }
1170
1171 /*
1172 * This is where buffer flushing would occur, but there is no buffering
1173 * at this time.
1174 * Possibly rename the log buffer for processing.
1175 * Sets tparams->ta_error equal to the value of the error that occurred,
1176 * 0 otherwise.
1177 * Returns ENOENT if the buffer is not found.
1178 */
1179 static void
1180 nfslog_do_flush(struct flush_thread_params *tparams)
1181 {
1182 struct nfsl_flush_args *args;
1183 struct log_buffer *lbp, *nlbp;
1184 int error = ENOENT;
1185 int found = 0;
1232 buf_inprog_len = strlen(args->buff) +
1233 strlen(LOG_INPROG_STRING) + 1;
1234 buf_inprog = (caddr_t)kmem_alloc(buf_inprog_len, KM_SLEEP);
1235 (void) sprintf(buf_inprog, "%s%s",
1236 args->buff, LOG_INPROG_STRING);
1237
1238 error = nfslog_logfile_rename(buf_inprog, args->buff);
1239
1240 kmem_free(buf_inprog, buf_inprog_len);
1241 }
1242
1243 out:
1244 if ((args->directive & NFSL_SYNC) == 0) {
1245 /*
1246 * Work was performed asynchronously, the caller is
1247 * no longer waiting for us.
1248 * Free the thread arguments and exit.
1249 */
1250 kmem_free(args->buff, args->buff_len);
1251 kmem_free(tparams, sizeof (*tparams));
1252 thread_exit();
1253 /* NOTREACHED */
1254 }
1255
1256 tparams->tp_error = error;
1257 }
1258
1259 /*
1260 * Generate buffer_header.
1261 * 'loghdr' points the the buffer_header, and *reclen
1262 * contains the length of the buffer.
1263 */
1264 static void
1265 create_buffer_header(caddr_t *loghdr, size_t *reclen, size_t *freesize)
1266 {
1267 timestruc_t now;
1268 nfslog_buffer_header lh;
1269 XDR xdrs;
1270 unsigned int final_size;
1271
1272
1273 /* pick some size that will hold the buffer_header */
1512 nfslog_vers_disptable},
1513
1514 {NFSLOG_PROGRAM, NFSLOG_VERSMIN,
1515 (sizeof (nfslog_nfslog_vers_disptable) /
1516 sizeof (nfslog_nfslog_vers_disptable[0])),
1517 nfslog_nfslog_vers_disptable},
1518 };
1519
1520 static int nfslog_dispatch_table_arglen = sizeof (nfslog_dispatch_table) /
1521 sizeof (nfslog_dispatch_table[0]);
1522
1523 /*
1524 * This function will determine the appropriate export info struct to use
1525 * and allocate a record id to be used in the written log buffer.
1526 * Usually this is a straightforward operation but the existence of the
1527 * multicomponent lookup and its semantics of crossing file system
1528 * boundaries add to the complexity. See the comments below...
1529 */
1530 struct exportinfo *
1531 nfslog_get_exi(
1532 struct exportinfo *exi,
1533 struct svc_req *req,
1534 caddr_t res,
1535 unsigned int *nfslog_rec_id)
1536 {
1537 struct log_buffer *lb;
1538 struct exportinfo *exi_ret = NULL;
1539 fhandle_t *fh;
1540 nfs_fh3 *fh3;
1541
1542 if (exi == NULL)
1543 return (NULL);
1544
1545 /*
1546 * If the exi is marked for logging, allocate a record id and return
1547 */
1548 if (exi->exi_export.ex_flags & EX_LOG) {
1549 lb = exi->exi_logbuffer;
1550
1551 /* obtain the unique record id for the caller */
1552 *nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
1553
1554 /*
1555 * The caller will expect to be able to exi_rele() it,
1556 * so exi->exi_count must be incremented before it can
1557 * be returned, to make it uniform with exi_ret->exi_count
1558 */
1559 exi_hold(exi);
1560 return (exi);
1561 }
1562
1563 if (exi != exi_public)
1564 return (NULL);
1565
1566 /*
1567 * Here we have an exi that is not marked for logging.
1568 * It is possible that this request is a multicomponent lookup
1569 * that was done from the public file handle (not logged) and
1570 * the resulting file handle being returned to the client exists
1571 * in a file system that is being logged. If this is the case
1572 * we need to log this multicomponent lookup to the appropriate
1573 * log buffer. This will allow for the appropriate path name
1574 * mapping to occur at user level.
1575 */
1576 if (req->rq_prog == NFS_PROGRAM) {
1577 switch (req->rq_vers) {
1578 case NFS_V3:
1579 if ((req->rq_proc == NFSPROC3_LOOKUP) &&
1580 (((LOOKUP3res *)res)->status == NFS3_OK)) {
1581 fh3 = &((LOOKUP3res *)res)->res_u.ok.object;
1582 exi_ret = checkexport(&fh3->fh3_fsid,
1583 FH3TOXFIDP(fh3));
1747 alloc_indx++;
1748 }
1749
1750 } while (encode_ok == FALSE);
1751
1752
1753 /*
1754 * Take the final log record and put it in the log file.
1755 * This may be queued to the file internally and written
1756 * later unless the last parameter is TRUE.
1757 * If the record_id is 0 then this is most likely a share/unshare
1758 * request and it should be written synchronously to the log file.
1759 */
1760 nfslog_record_put(log_cookie,
1761 final_size, (record_id == 0), which_buffers);
1762 }
1763
1764 static char *
1765 get_publicfh_path(int *alloc_length)
1766 {
1767 extern struct exportinfo *exi_public;
1768 char *pubpath;
1769
1770 rw_enter(&exported_lock, RW_READER);
1771
1772 *alloc_length = exi_public->exi_export.ex_pathlen + 1;
1773 pubpath = kmem_alloc(*alloc_length, KM_SLEEP);
1774
1775 (void) strcpy(pubpath, exi_public->exi_export.ex_path);
1776
1777 rw_exit(&exported_lock);
1778
1779 return (pubpath);
1780 }
1781
1782 static void
1783 log_public_record(struct exportinfo *exi, cred_t *cr)
1784 {
1785 struct svc_req req;
1786 struct netbuf nb = {0, 0, NULL};
1787 int free_length = 0;
1788 diropargs3 args;
1789 LOOKUP3res res;
1790
1791 bzero(&req, sizeof (req));
1792 req.rq_prog = NFSLOG_PROGRAM;
1793 req.rq_vers = NFSLOG_VERSION;
1794 req.rq_proc = NFSLOG_LOOKUP;
1795 req.rq_cred.oa_flavor = AUTH_NONE;
1796
1797 bzero(&args, sizeof (diropargs3));
1853 nfslog_unshare_record(struct exportinfo *exi, cred_t *cr)
1854 {
1855 struct svc_req req;
1856 int res = 0;
1857 struct netbuf nb = {0, 0, NULL};
1858
1859 ASSERT(exi != NULL);
1860 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1861
1862 bzero(&req, sizeof (req));
1863 req.rq_prog = NFSLOG_PROGRAM;
1864 req.rq_vers = NFSLOG_VERSION;
1865 req.rq_proc = NFSLOG_UNSHARE;
1866 req.rq_cred.oa_flavor = AUTH_NONE;
1867 nfslog_write_record(exi, &req,
1868 (caddr_t)exi, (caddr_t)&res, cr, &nb, 0, NFSLOG_ONE_BUFFER);
1869 }
1870
1871
1872 void
1873 nfslog_getfh(struct exportinfo *exi,
1874 fhandle *fh,
1875 char *fname,
1876 enum uio_seg seg,
1877 cred_t *cr)
1878 {
1879 struct svc_req req;
1880 int res = 0;
1881 struct netbuf nb = {0, 0, NULL};
1882 int error = 0;
1883 char *namebuf;
1884 size_t len;
1885 nfslog_getfhargs gfh;
1886
1887 ASSERT(exi != NULL);
1888 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1889
1890 bzero(&req, sizeof (req));
1891 req.rq_prog = NFSLOG_PROGRAM;
1892 req.rq_vers = NFSLOG_VERSION;
1893 req.rq_proc = NFSLOG_GETFH;
1894 req.rq_cred.oa_flavor = AUTH_NONE;
1895
1896 namebuf = kmem_alloc(MAXPATHLEN + 4, KM_SLEEP);
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 2018 Nexenta Systems, Inc.
28 */
29
30 #include <sys/cred.h>
31 #include <sys/cmn_err.h>
32 #include <sys/debug.h>
33 #include <sys/systm.h>
34 #include <sys/kmem.h>
35 #include <sys/disp.h>
36 #include <sys/atomic.h>
37 #include <rpc/types.h>
38 #include <nfs/nfs.h>
39 #include <nfs/nfssys.h>
40 #include <nfs/export.h>
41 #include <nfs/rnode.h>
42 #include <rpc/auth.h>
43 #include <rpc/svc.h>
44 #include <rpc/xdr.h>
45 #include <rpc/clnt.h>
46 #include <nfs/nfs_log.h>
47
48 #define NUM_RECORDS_TO_WRITE 256
49 #define NUM_BYTES_TO_WRITE 65536
50
51 static int nfslog_num_records_to_write = NUM_RECORDS_TO_WRITE;
52 static int nfslog_num_bytes_to_write = NUM_BYTES_TO_WRITE;
53
54 /*
55 * This struct is used to 'hide' the details of managing the log
56 * records internally to the logging code. Allocation routines
57 * are used to obtain pieces of memory for XDR encoding. This struct
58 * is a 'header' to those areas and a opaque cookie is used to pass
59 * this data structure between the allocating function and the put
60 * function.
61 */
62 struct lr_alloc {
63 struct lr_alloc *next; /* links for write queuing */
64 struct lr_alloc *prev;
65 #define LR_ALLOC_NOFREE 0x1 /* not present, call free */
66 int lr_flags;
67 caddr_t log_record; /* address to XDR encoding */
68 size_t size; /* final size of encoding */
69 struct kmem_cache *alloc_cache; /* keep track of cache ptr */
70 struct exportinfo *exi; /* who are we related to? */
581 kmem_free(lfp, sizeof (*lfp));
582 rfsl_log_file--;
583 }
584
585 /*
586 * Allocates a record of the size specified.
587 * 'exi' identifies the exportinfo structure being logged.
588 * 'size' indicates how much memory should be allocated
589 * 'cookie' is used to store an opaque value for the caller for later use
590 * 'flags' currently ignored.
591 *
592 * Returns a pointer to the beginning of the allocated memory.
593 * 'cookie' is a pointer to the 'lr_alloc' struct; this will be used
594 * to keep track of the encoded record and contains all the info
595 * for enqueuing the record on the log buffer for later writing.
596 *
597 * nfslog_record_put() must be used to 'free' this record or allocation.
598 */
599 /* ARGSUSED */
600 void *
601 nfslog_record_alloc(struct exportinfo *exi, int alloc_indx, void **cookie,
602 int flags)
603 {
604 struct lr_alloc *lrp;
605
606 lrp = (struct lr_alloc *)
607 kmem_cache_alloc(nfslog_mem_alloc[alloc_indx].mem_cache,
608 KM_NOSLEEP);
609
610 if (lrp == NULL) {
611 *cookie = NULL;
612 return (NULL);
613 }
614
615 lrp->next = lrp;
616 lrp->prev = lrp;
617 lrp->lr_flags = 0;
618
619 lrp->log_record = (caddr_t)((uintptr_t)lrp +
620 (uintptr_t)sizeof (struct lr_alloc));
621 lrp->size = nfslog_mem_alloc[alloc_indx].size;
751 lbp->lb_records = NULL;
752 num_recs = lbp->lb_num_recs;
753 lbp->lb_num_recs = 0;
754 lbp->lb_size_queued = 0;
755 mutex_exit(&lbp->lb_lock);
756 error = nfslog_write_logrecords(lfp, lrp_writers, num_recs);
757
758 LOG_FILE_UNLOCK_FROM_WRITE(lfp);
759
760 nfslog_free_logrecords(lrp_writers);
761 return (error);
762 }
763
764
765 /*
766 * Take care of writing the provided log record(s) to the log file.
767 * We group the log records with an iovec and use VOP_WRITE to append
768 * them to the end of the log file.
769 */
770 static int
771 nfslog_write_logrecords(struct log_file *lfp, struct lr_alloc *lrp_writers,
772 int num_recs)
773 {
774 struct uio uio;
775 struct iovec *iovp;
776 int size_iovecs;
777 vnode_t *vp;
778 struct vattr va;
779 struct lr_alloc *lrp;
780 int i;
781 ssize_t len;
782 int ioflag = FAPPEND;
783 int error = 0;
784
785 ASSERT(MUTEX_HELD(&lfp->lf_lock));
786
787 vp = lfp->lf_vp;
788
789 size_iovecs = sizeof (struct iovec) * num_recs;
790 iovp = (struct iovec *)kmem_alloc(size_iovecs, KM_NOSLEEP);
791
792 if (iovp == NULL) {
1144
1145 if (nfsl_args->buff_len != buffer_len)
1146 return (EFAULT);
1147 }
1148
1149 LOGGING_DPRINT((10, "nfsl_flush: Flushing %s buffer(s)\n",
1150 nfsl_args->directive & NFSL_ALL ? "all" : nfsl_args->buff));
1151
1152 if (nfsl_args->directive & NFSL_SYNC) {
1153 /*
1154 * Do the work synchronously
1155 */
1156 nfslog_do_flush(tparams);
1157 error = tparams->tp_error;
1158 kmem_free(nfsl_args->buff, nfsl_args->buff_len);
1159 kmem_free(tparams, sizeof (*tparams));
1160 } else {
1161 /*
1162 * Do the work asynchronously
1163 */
1164 (void) zthread_create(NULL, 0, nfslog_do_flush,
1165 tparams, 0, minclsyspri);
1166 }
1167
1168 return (error);
1169 }
1170
1171 /*
1172 * This is where buffer flushing would occur, but there is no buffering
1173 * at this time.
1174 * Possibly rename the log buffer for processing.
1175 * Sets tparams->ta_error equal to the value of the error that occurred,
1176 * 0 otherwise.
1177 * Returns ENOENT if the buffer is not found.
1178 */
1179 static void
1180 nfslog_do_flush(struct flush_thread_params *tparams)
1181 {
1182 struct nfsl_flush_args *args;
1183 struct log_buffer *lbp, *nlbp;
1184 int error = ENOENT;
1185 int found = 0;
1232 buf_inprog_len = strlen(args->buff) +
1233 strlen(LOG_INPROG_STRING) + 1;
1234 buf_inprog = (caddr_t)kmem_alloc(buf_inprog_len, KM_SLEEP);
1235 (void) sprintf(buf_inprog, "%s%s",
1236 args->buff, LOG_INPROG_STRING);
1237
1238 error = nfslog_logfile_rename(buf_inprog, args->buff);
1239
1240 kmem_free(buf_inprog, buf_inprog_len);
1241 }
1242
1243 out:
1244 if ((args->directive & NFSL_SYNC) == 0) {
1245 /*
1246 * Work was performed asynchronously, the caller is
1247 * no longer waiting for us.
1248 * Free the thread arguments and exit.
1249 */
1250 kmem_free(args->buff, args->buff_len);
1251 kmem_free(tparams, sizeof (*tparams));
1252 zthread_exit();
1253 }
1254
1255 tparams->tp_error = error;
1256 }
1257
1258 /*
1259 * Generate buffer_header.
1260 * 'loghdr' points the the buffer_header, and *reclen
1261 * contains the length of the buffer.
1262 */
1263 static void
1264 create_buffer_header(caddr_t *loghdr, size_t *reclen, size_t *freesize)
1265 {
1266 timestruc_t now;
1267 nfslog_buffer_header lh;
1268 XDR xdrs;
1269 unsigned int final_size;
1270
1271
1272 /* pick some size that will hold the buffer_header */
1511 nfslog_vers_disptable},
1512
1513 {NFSLOG_PROGRAM, NFSLOG_VERSMIN,
1514 (sizeof (nfslog_nfslog_vers_disptable) /
1515 sizeof (nfslog_nfslog_vers_disptable[0])),
1516 nfslog_nfslog_vers_disptable},
1517 };
1518
1519 static int nfslog_dispatch_table_arglen = sizeof (nfslog_dispatch_table) /
1520 sizeof (nfslog_dispatch_table[0]);
1521
1522 /*
1523 * This function will determine the appropriate export info struct to use
1524 * and allocate a record id to be used in the written log buffer.
1525 * Usually this is a straightforward operation but the existence of the
1526 * multicomponent lookup and its semantics of crossing file system
1527 * boundaries add to the complexity. See the comments below...
1528 */
1529 struct exportinfo *
1530 nfslog_get_exi(
1531 nfs_export_t *ne,
1532 struct exportinfo *exi,
1533 struct svc_req *req,
1534 caddr_t res,
1535 unsigned int *nfslog_rec_id)
1536 {
1537 struct log_buffer *lb;
1538 struct exportinfo *exi_ret = NULL;
1539 fhandle_t *fh;
1540 nfs_fh3 *fh3;
1541
1542 if (exi == NULL)
1543 return (NULL);
1544
1545 /*
1546 * If the exi is marked for logging, allocate a record id and return
1547 */
1548 if (exi->exi_export.ex_flags & EX_LOG) {
1549 lb = exi->exi_logbuffer;
1550
1551 /* obtain the unique record id for the caller */
1552 *nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
1553
1554 /*
1555 * The caller will expect to be able to exi_rele() it,
1556 * so exi->exi_count must be incremented before it can
1557 * be returned, to make it uniform with exi_ret->exi_count
1558 */
1559 exi_hold(exi);
1560 return (exi);
1561 }
1562
1563 if (exi != ne->exi_public)
1564 return (NULL);
1565
1566 /*
1567 * Here we have an exi that is not marked for logging.
1568 * It is possible that this request is a multicomponent lookup
1569 * that was done from the public file handle (not logged) and
1570 * the resulting file handle being returned to the client exists
1571 * in a file system that is being logged. If this is the case
1572 * we need to log this multicomponent lookup to the appropriate
1573 * log buffer. This will allow for the appropriate path name
1574 * mapping to occur at user level.
1575 */
1576 if (req->rq_prog == NFS_PROGRAM) {
1577 switch (req->rq_vers) {
1578 case NFS_V3:
1579 if ((req->rq_proc == NFSPROC3_LOOKUP) &&
1580 (((LOOKUP3res *)res)->status == NFS3_OK)) {
1581 fh3 = &((LOOKUP3res *)res)->res_u.ok.object;
1582 exi_ret = checkexport(&fh3->fh3_fsid,
1583 FH3TOXFIDP(fh3));
1747 alloc_indx++;
1748 }
1749
1750 } while (encode_ok == FALSE);
1751
1752
1753 /*
1754 * Take the final log record and put it in the log file.
1755 * This may be queued to the file internally and written
1756 * later unless the last parameter is TRUE.
1757 * If the record_id is 0 then this is most likely a share/unshare
1758 * request and it should be written synchronously to the log file.
1759 */
1760 nfslog_record_put(log_cookie,
1761 final_size, (record_id == 0), which_buffers);
1762 }
1763
1764 static char *
1765 get_publicfh_path(int *alloc_length)
1766 {
1767 char *pubpath;
1768 nfs_export_t *ne = nfs_get_export();
1769
1770 rw_enter(&ne->exported_lock, RW_READER);
1771
1772 *alloc_length = ne->exi_public->exi_export.ex_pathlen + 1;
1773 pubpath = kmem_alloc(*alloc_length, KM_SLEEP);
1774
1775 (void) strcpy(pubpath, ne->exi_public->exi_export.ex_path);
1776
1777 rw_exit(&ne->exported_lock);
1778
1779 return (pubpath);
1780 }
1781
1782 static void
1783 log_public_record(struct exportinfo *exi, cred_t *cr)
1784 {
1785 struct svc_req req;
1786 struct netbuf nb = {0, 0, NULL};
1787 int free_length = 0;
1788 diropargs3 args;
1789 LOOKUP3res res;
1790
1791 bzero(&req, sizeof (req));
1792 req.rq_prog = NFSLOG_PROGRAM;
1793 req.rq_vers = NFSLOG_VERSION;
1794 req.rq_proc = NFSLOG_LOOKUP;
1795 req.rq_cred.oa_flavor = AUTH_NONE;
1796
1797 bzero(&args, sizeof (diropargs3));
1853 nfslog_unshare_record(struct exportinfo *exi, cred_t *cr)
1854 {
1855 struct svc_req req;
1856 int res = 0;
1857 struct netbuf nb = {0, 0, NULL};
1858
1859 ASSERT(exi != NULL);
1860 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1861
1862 bzero(&req, sizeof (req));
1863 req.rq_prog = NFSLOG_PROGRAM;
1864 req.rq_vers = NFSLOG_VERSION;
1865 req.rq_proc = NFSLOG_UNSHARE;
1866 req.rq_cred.oa_flavor = AUTH_NONE;
1867 nfslog_write_record(exi, &req,
1868 (caddr_t)exi, (caddr_t)&res, cr, &nb, 0, NFSLOG_ONE_BUFFER);
1869 }
1870
1871
1872 void
1873 nfslog_getfh(struct exportinfo *exi, fhandle *fh, char *fname, enum uio_seg seg,
1874 cred_t *cr)
1875 {
1876 struct svc_req req;
1877 int res = 0;
1878 struct netbuf nb = {0, 0, NULL};
1879 int error = 0;
1880 char *namebuf;
1881 size_t len;
1882 nfslog_getfhargs gfh;
1883
1884 ASSERT(exi != NULL);
1885 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1886
1887 bzero(&req, sizeof (req));
1888 req.rq_prog = NFSLOG_PROGRAM;
1889 req.rq_vers = NFSLOG_VERSION;
1890 req.rq_proc = NFSLOG_GETFH;
1891 req.rq_cred.oa_flavor = AUTH_NONE;
1892
1893 namebuf = kmem_alloc(MAXPATHLEN + 4, KM_SLEEP);
|