2 * Copyright (c) 2000-2001, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: smbfs_vfsops.c,v 1.73.64.1 2005/05/27 02:35:28 lindak Exp $
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
38 * Copyright 2013, Joyent, Inc. All rights reserved.
39 * Copyright (c) 2016 by Delphix. All rights reserved.
42 #include <sys/systm.h>
46 #include <sys/vnode.h>
47 #include <sys/fs_subr.h>
48 #include <sys/sysmacros.h>
50 #include <sys/mkdev.h>
51 #include <sys/mount.h>
52 #include <sys/statvfs.h>
53 #include <sys/errno.h>
54 #include <sys/debug.h>
56 #include <sys/cmn_err.h>
57 #include <sys/modctl.h>
58 #include <sys/policy.h>
59 #include <sys/atomic.h>
62 #include <sys/mntent.h>
64 #include <sys/taskq.h>
67 #include <netsmb/smb_osdep.h>
68 #include <netsmb/smb.h>
69 #include <netsmb/smb_conn.h>
70 #include <netsmb/smb_subr.h>
71 #include <netsmb/smb_dev.h>
73 #include <smbfs/smbfs.h>
74 #include <smbfs/smbfs_node.h>
75 #include <smbfs/smbfs_subr.h>
78 * Should smbfs mount enable "-o acl" by default? There are good
79 * arguments for both. The most common use case is individual users
80 * accessing files on some SMB server, for which "noacl" is the more
81 * convenient default. A less common use case is data migration,
82 * where the "acl" option might be a desirable default. We'll make
83 * the common use case the default. This default can be changed via
84 * /etc/system, and/or set per-mount via the "acl" mount option.
86 int smbfs_default_opt_acl
= 0;
89 * How many taskq threads per-mount should we use.
90 * Just one is fine (until we do more async work).
92 int smbfs_tq_nthread
= 1;
95 * Local functions definitions.
97 int smbfsinit(int fstyp
, char *name
);
101 * SMBFS Mount options table for MS_OPTIONSTR
102 * Note: These are not all the options.
103 * Some options come in via MS_DATA.
104 * Others are generic (see vfs.c)
106 static char *intr_cancel
[] = { MNTOPT_NOINTR
, NULL
};
107 static char *nointr_cancel
[] = { MNTOPT_INTR
, NULL
};
108 static char *acl_cancel
[] = { MNTOPT_NOACL
, NULL
};
109 static char *noacl_cancel
[] = { MNTOPT_ACL
, NULL
};
110 static char *xattr_cancel
[] = { MNTOPT_NOXATTR
, NULL
};
111 static char *noxattr_cancel
[] = { MNTOPT_XATTR
, NULL
};
113 static mntopt_t mntopts
[] = {
115 * option name cancel option default arg flags
118 { MNTOPT_INTR
, intr_cancel
, NULL
, MO_DEFAULT
, 0 },
119 { MNTOPT_NOINTR
, nointr_cancel
, NULL
, 0, 0 },
120 { MNTOPT_ACL
, acl_cancel
, NULL
, 0, 0 },
121 { MNTOPT_NOACL
, noacl_cancel
, NULL
, 0, 0 },
122 { MNTOPT_XATTR
, xattr_cancel
, NULL
, MO_DEFAULT
, 0 },
123 { MNTOPT_NOXATTR
, noxattr_cancel
, NULL
, 0, 0 }
126 static mntopts_t smbfs_mntopts
= {
127 sizeof (mntopts
) / sizeof (mntopt_t
),
131 static const char fs_type_name
[FSTYPSZ
] = "smbfs";
133 static vfsdef_t vfw
= {
135 (char *)fs_type_name
,
136 smbfsinit
, /* init routine */
137 VSW_HASPROTO
|VSW_NOTZONESAFE
, /* flags */
138 &smbfs_mntopts
/* mount options table prototype */
141 static struct modlfs modlfs
= {
147 static struct modlinkage modlinkage
= {
148 MODREV_1
, (void *)&modlfs
, NULL
152 * Mutex to protect the following variables:
156 extern kmutex_t smbfs_minor_lock
;
157 extern int smbfs_major
;
158 extern int smbfs_minor
;
161 * Prevent unloads while we have mounts
163 uint32_t smbfs_mountcount
;
166 * smbfs vfs operations.
168 static int smbfs_mount(vfs_t
*, vnode_t
*, struct mounta
*, cred_t
*);
169 static int smbfs_unmount(vfs_t
*, int, cred_t
*);
170 static int smbfs_root(vfs_t
*, vnode_t
**);
171 static int smbfs_statvfs(vfs_t
*, statvfs64_t
*);
172 static int smbfs_sync(vfs_t
*, short, cred_t
*);
173 static void smbfs_freevfs(vfs_t
*);
180 * This routine is invoked automatically when the kernel module
181 * containing this routine is loaded. This allows module specific
182 * initialization to be done when the module is loaded.
190 * Check compiled-in version of "nsmb"
191 * that we're linked with. (paranoid)
193 if (nsmb_version
!= NSMB_VERSION
) {
194 cmn_err(CE_WARN
, "_init: nsmb version mismatch");
198 smbfs_mountcount
= 0;
201 * NFS calls these two in _clntinit
202 * Easier to follow this way.
204 if ((error
= smbfs_subrinit()) != 0) {
205 cmn_err(CE_WARN
, "_init: smbfs_subrinit failed");
209 if ((error
= smbfs_vfsinit()) != 0) {
210 cmn_err(CE_WARN
, "_init: smbfs_vfsinit failed");
215 if ((error
= smbfs_clntinit()) != 0) {
216 cmn_err(CE_WARN
, "_init: smbfs_clntinit failed");
222 error
= mod_install((struct modlinkage
*)&modlinkage
);
227 * Free kernel module resources that were allocated in _init
228 * and remove the linkage information into the kernel
236 * If a forcedly unmounted instance is still hanging around,
237 * we cannot allow the module to be unloaded because that would
238 * cause panics once the VFS framework decides it's time to call
239 * into VFS_FREEVFS().
241 if (smbfs_mountcount
)
244 error
= mod_remove(&modlinkage
);
249 * Free the allocated smbnodes, etc.
253 /* NFS calls these two in _clntfini */
258 * Free the ops vectors
265 * Return information about the module
268 _info(struct modinfo
*modinfop
)
270 return (mod_info((struct modlinkage
*)&modlinkage
, modinfop
));
274 * Initialize the vfs structure
279 static const struct vfsops smbfs_vfsops
= {
280 .vfs_mount
= smbfs_mount
,
281 .vfs_unmount
= smbfs_unmount
,
282 .vfs_root
= smbfs_root
,
283 .vfs_statvfs
= smbfs_statvfs
,
284 .vfs_sync
= smbfs_sync
,
285 .vfs_vget
= fs_nosys
,
286 .vfs_mountroot
= fs_nosys
,
287 .vfs_freevfs
= smbfs_freevfs
,
291 smbfsinit(int fstyp
, char *name
)
295 error
= vfs_setfsops(fstyp
, &smbfs_vfsops
);
297 zcmn_err(GLOBAL_ZONEID
, CE_WARN
,
298 "smbfsinit: bad vfs ops template");
310 (void) vfs_freevfsops_by_type(smbfsfstyp
);
314 smbfs_free_smi(smbmntinfo_t
*smi
)
319 if (smi
->smi_zone_ref
.zref_zone
!= NULL
)
320 zone_rele_ref(&smi
->smi_zone_ref
, ZONE_REF_SMBFS
);
322 if (smi
->smi_share
!= NULL
)
323 smb_share_rele(smi
->smi_share
);
325 avl_destroy(&smi
->smi_hash_avl
);
326 rw_destroy(&smi
->smi_hash_lk
);
327 cv_destroy(&smi
->smi_statvfs_cv
);
328 mutex_destroy(&smi
->smi_lock
);
330 kmem_free(smi
, sizeof (smbmntinfo_t
));
335 * Set up mount info record and attach it to vfs struct.
338 smbfs_mount(vfs_t
*vfsp
, vnode_t
*mvp
, struct mounta
*uap
, cred_t
*cr
)
340 char *data
= uap
->dataptr
;
342 smbnode_t
*rtnp
= NULL
; /* root of this fs */
343 smbmntinfo_t
*smi
= NULL
;
347 zone_t
*zone
= curproc
->p_zone
;
348 zone_t
*mntzone
= NULL
;
349 smb_share_t
*ssp
= NULL
;
353 STRUCT_DECL(smbfs_args
, args
); /* smbfs mount arguments */
355 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0)
358 if (mvp
->v_type
!= VDIR
)
364 * uap->datalen might be different from sizeof (args)
365 * in a compatible situation.
367 STRUCT_INIT(args
, get_udatamodel());
368 bzero(STRUCT_BUF(args
), SIZEOF_STRUCT(smbfs_args
, DATAMODEL_NATIVE
));
369 if (copyin(data
, STRUCT_BUF(args
), MIN(uap
->datalen
,
370 SIZEOF_STRUCT(smbfs_args
, DATAMODEL_NATIVE
))))
374 * Check mount program version
376 version
= STRUCT_FGET(args
, version
);
377 if (version
!= SMBFS_VERSION
) {
378 cmn_err(CE_WARN
, "mount version mismatch:"
379 " kernel=%d, mount=%d\n",
380 SMBFS_VERSION
, version
);
385 * Deal with re-mount requests.
387 if (uap
->flags
& MS_REMOUNT
) {
388 cmn_err(CE_WARN
, "MS_REMOUNT not implemented");
395 mutex_enter(&mvp
->v_lock
);
396 if (!(uap
->flags
& MS_OVERLAY
) &&
397 (mvp
->v_count
!= 1 || (mvp
->v_flag
& VROOT
))) {
398 mutex_exit(&mvp
->v_lock
);
401 mutex_exit(&mvp
->v_lock
);
404 * Get the "share" from the netsmb driver (ssp).
405 * It is returned with a "ref" (hold) for us.
406 * Release this hold: at errout below, or in
409 devfd
= STRUCT_FGET(args
, devfd
);
410 error
= smb_dev2share(devfd
, &ssp
);
412 cmn_err(CE_WARN
, "invalid device handle %d (%d)\n",
418 * Use "goto errout" from here on.
419 * See: ssp, smi, rtnp, mntzone
423 * Determine the zone we're being mounted into.
425 zone_hold(mntzone
= zone
); /* start with this assumption */
426 if (getzoneid() == GLOBAL_ZONEID
) {
428 mntzone
= zone_find_by_path(refstr_value(vfsp
->vfs_mntpt
));
429 ASSERT(mntzone
!= NULL
);
430 if (mntzone
!= zone
) {
437 * Stop the mount from going any further if the zone is going away.
439 if (zone_status_get(mntzone
) >= ZONE_IS_SHUTTING_DOWN
) {
444 /* Prevent unload. */
445 atomic_inc_32(&smbfs_mountcount
);
448 * Create a mount record and link it to the vfs struct.
449 * No more possiblities for errors from here on.
450 * Tear-down of this stuff is in smbfs_free_smi()
452 * Compare with NFS: nfsrootvp()
454 smi
= kmem_zalloc(sizeof (*smi
), KM_SLEEP
);
456 mutex_init(&smi
->smi_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
457 cv_init(&smi
->smi_statvfs_cv
, NULL
, CV_DEFAULT
, NULL
);
459 rw_init(&smi
->smi_hash_lk
, NULL
, RW_DEFAULT
, NULL
);
460 smbfs_init_hash_avl(&smi
->smi_hash_avl
);
462 smi
->smi_share
= ssp
;
466 * Convert the anonymous zone hold acquired via zone_hold() above
467 * into a zone reference.
469 zone_init_ref(&smi
->smi_zone_ref
);
470 zone_hold_ref(mntzone
, &smi
->smi_zone_ref
, ZONE_REF_SMBFS
);
475 * Initialize option defaults
477 smi
->smi_flags
= SMI_LLOCK
;
478 smi
->smi_acregmin
= SEC2HR(SMBFS_ACREGMIN
);
479 smi
->smi_acregmax
= SEC2HR(SMBFS_ACREGMAX
);
480 smi
->smi_acdirmin
= SEC2HR(SMBFS_ACDIRMIN
);
481 smi
->smi_acdirmax
= SEC2HR(SMBFS_ACDIRMAX
);
484 * All "generic" mount options have already been
485 * handled in vfs.c:domount() - see mntopts stuff.
486 * Query generic options using vfs_optionisset().
487 * Give ACL an adjustable system-wide default.
489 if (smbfs_default_opt_acl
||
490 vfs_optionisset(vfsp
, MNTOPT_ACL
, NULL
))
491 smi
->smi_flags
|= SMI_ACL
;
492 if (vfs_optionisset(vfsp
, MNTOPT_NOACL
, NULL
))
493 smi
->smi_flags
&= ~SMI_ACL
;
494 if (vfs_optionisset(vfsp
, MNTOPT_INTR
, NULL
))
495 smi
->smi_flags
|= SMI_INT
;
498 * Get the mount options that come in as smbfs_args,
499 * starting with args.flags (SMBFS_MF_xxx)
501 flags
= STRUCT_FGET(args
, flags
);
502 smi
->smi_uid
= STRUCT_FGET(args
, uid
);
503 smi
->smi_gid
= STRUCT_FGET(args
, gid
);
504 smi
->smi_fmode
= STRUCT_FGET(args
, file_mode
) & 0777;
505 smi
->smi_dmode
= STRUCT_FGET(args
, dir_mode
) & 0777;
508 * Hande the SMBFS_MF_xxx flags.
510 if (flags
& SMBFS_MF_NOAC
)
511 smi
->smi_flags
|= SMI_NOAC
;
512 if (flags
& SMBFS_MF_ACREGMIN
) {
513 sec
= STRUCT_FGET(args
, acregmin
);
514 if (sec
< 0 || sec
> SMBFS_ACMINMAX
)
515 sec
= SMBFS_ACMINMAX
;
516 smi
->smi_acregmin
= SEC2HR(sec
);
518 if (flags
& SMBFS_MF_ACREGMAX
) {
519 sec
= STRUCT_FGET(args
, acregmax
);
520 if (sec
< 0 || sec
> SMBFS_ACMAXMAX
)
521 sec
= SMBFS_ACMAXMAX
;
522 smi
->smi_acregmax
= SEC2HR(sec
);
524 if (flags
& SMBFS_MF_ACDIRMIN
) {
525 sec
= STRUCT_FGET(args
, acdirmin
);
526 if (sec
< 0 || sec
> SMBFS_ACMINMAX
)
527 sec
= SMBFS_ACMINMAX
;
528 smi
->smi_acdirmin
= SEC2HR(sec
);
530 if (flags
& SMBFS_MF_ACDIRMAX
) {
531 sec
= STRUCT_FGET(args
, acdirmax
);
532 if (sec
< 0 || sec
> SMBFS_ACMAXMAX
)
533 sec
= SMBFS_ACMAXMAX
;
534 smi
->smi_acdirmax
= SEC2HR(sec
);
538 * Get attributes of the remote file system,
539 * i.e. ACL support, named streams, etc.
541 smb_credinit(&scred
, cr
);
542 error
= smbfs_smb_qfsattr(smi
->smi_share
, &smi
->smi_fsa
, &scred
);
543 smb_credrele(&scred
);
545 SMBVDEBUG("smbfs_smb_qfsattr error %d\n", error
);
549 * We enable XATTR by default (via smbfs_mntopts)
550 * but if the share does not support named streams,
551 * force the NOXATTR option (also clears XATTR).
552 * Caller will set or clear VFS_XATTR after this.
554 if ((smi
->smi_fsattr
& FILE_NAMED_STREAMS
) == 0)
555 vfs_setmntopt(vfsp
, MNTOPT_NOXATTR
, NULL
, 0);
558 * Ditto ACLs (disable if not supported on this share)
560 if ((smi
->smi_fsattr
& FILE_PERSISTENT_ACLS
) == 0) {
561 vfs_setmntopt(vfsp
, MNTOPT_NOACL
, NULL
, 0);
562 smi
->smi_flags
&= ~SMI_ACL
;
566 * Assign a unique device id to the mount
568 mutex_enter(&smbfs_minor_lock
);
570 smbfs_minor
= (smbfs_minor
+ 1) & MAXMIN32
;
571 smbfs_dev
= makedevice(smbfs_major
, smbfs_minor
);
572 } while (vfs_devismounted(smbfs_dev
));
573 mutex_exit(&smbfs_minor_lock
);
575 vfsp
->vfs_dev
= smbfs_dev
;
576 vfs_make_fsid(&vfsp
->vfs_fsid
, smbfs_dev
, smbfsfstyp
);
577 vfsp
->vfs_data
= (caddr_t
)smi
;
578 vfsp
->vfs_fstype
= smbfsfstyp
;
579 vfsp
->vfs_bsize
= MAXBSIZE
;
580 vfsp
->vfs_bcount
= 0;
582 smi
->smi_vfsp
= vfsp
;
583 smbfs_zonelist_add(smi
); /* undo in smbfs_freevfs */
585 /* PSARC 2007/227 VFS Feature Registration */
586 vfs_set_feature(vfsp
, VFSFT_XVATTR
);
587 vfs_set_feature(vfsp
, VFSFT_SYSATTR_VIEWS
);
590 * Create the root vnode, which we need in unmount
591 * for the call to smbfs_check_table(), etc.
592 * Release this hold in smbfs_unmount.
594 rtnp
= smbfs_node_findcreate(smi
, "\\", 1, NULL
, 0, 0,
596 ASSERT(rtnp
!= NULL
);
597 rtnp
->r_vnode
->v_type
= VDIR
;
598 rtnp
->r_vnode
->v_flag
|= VROOT
;
599 smi
->smi_root
= rtnp
;
602 * Create a taskq for async work (i.e. putpage)
604 smi
->smi_taskq
= taskq_create_proc("smbfs",
605 smbfs_tq_nthread
, minclsyspri
,
606 smbfs_tq_nthread
, smbfs_tq_nthread
* 2,
607 zone
->zone_zsched
, TASKQ_PREPOPULATE
);
610 * NFS does other stuff here too:
611 * async worker threads
614 * End of code from NFS nfsrootvp()
619 vfsp
->vfs_data
= NULL
;
636 smbfs_unmount(vfs_t
*vfsp
, int flag
, cred_t
*cr
)
643 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
646 if ((flag
& MS_FORCE
) == 0) {
647 smbfs_rflush(vfsp
, cr
);
650 * If there are any active vnodes on this file system,
651 * (other than the root vnode) then the file system is
652 * busy and can't be umounted.
654 if (smbfs_check_table(vfsp
, smi
->smi_root
))
658 * We normally hold a ref to the root vnode, so
659 * check for references beyond the one we expect:
660 * smbmntinfo_t -> smi_root
661 * Note that NFS does not hold the root vnode.
664 smi
->smi_root
->r_vnode
->v_count
> 1)
669 * common code for both forced and non-forced
671 * Setting VFS_UNMOUNTED prevents new operations.
672 * Operations already underway may continue,
675 vfsp
->vfs_flag
|= VFS_UNMOUNTED
;
678 * If we hold the root VP (and we normally do)
679 * then it's safe to release it now.
682 rtnp
= smi
->smi_root
;
683 smi
->smi_root
= NULL
;
684 VN_RELE(rtnp
->r_vnode
); /* release root vnode */
688 * Remove all nodes from the node hash tables.
689 * This (indirectly) calls: smbfs_addfree, smbinactive,
690 * which will try to flush dirty pages, etc. so
691 * don't destroy the underlying share just yet.
693 * Also, with a forced unmount, some nodes may
694 * remain active, and those will get cleaned up
695 * after their last vn_rele.
697 smbfs_destroy_table(vfsp
);
700 * Shutdown any outstanding I/O requests on this share,
701 * and force a tree disconnect. The share object will
702 * continue to hang around until smb_share_rele().
703 * This should also cause most active nodes to be
704 * released as their operations fail with EIO.
706 smb_share_kill(smi
->smi_share
);
709 * Any async taskq work should be giving up.
710 * Wait for those to exit.
712 taskq_destroy(smi
->smi_taskq
);
715 * Delete our kstats...
717 * Doing it here, rather than waiting until
718 * smbfs_freevfs so these are not visible
721 if (smi
->smi_io_kstats
) {
722 kstat_delete(smi
->smi_io_kstats
);
723 smi
->smi_io_kstats
= NULL
;
725 if (smi
->smi_ro_kstats
) {
726 kstat_delete(smi
->smi_ro_kstats
);
727 smi
->smi_ro_kstats
= NULL
;
731 * The rest happens in smbfs_freevfs()
741 smbfs_root(vfs_t
*vfsp
, vnode_t
**vpp
)
748 if (curproc
->p_zone
!= smi
->smi_zone_ref
.zref_zone
)
751 if (smi
->smi_flags
& SMI_DEAD
|| vfsp
->vfs_flag
& VFS_UNMOUNTED
)
755 * The root vp is created in mount and held
756 * until unmount, so this is paranoia.
758 if (smi
->smi_root
== NULL
)
761 /* Just take a reference and return it. */
762 vp
= SMBTOV(smi
->smi_root
);
770 * Get file system statistics.
773 smbfs_statvfs(vfs_t
*vfsp
, statvfs64_t
*sbp
)
776 smbmntinfo_t
*smi
= VFTOSMI(vfsp
);
777 smb_share_t
*ssp
= smi
->smi_share
;
782 if (curproc
->p_zone
!= smi
->smi_zone_ref
.zref_zone
)
785 if (smi
->smi_flags
& SMI_DEAD
|| vfsp
->vfs_flag
& VFS_UNMOUNTED
)
788 mutex_enter(&smi
->smi_lock
);
791 * Use cached result if still valid.
795 if (now
< smi
->smi_statfstime
) {
801 * FS attributes are stale, so someone
802 * needs to do an OTW call to get them.
803 * Serialize here so only one thread
806 if (smi
->smi_status
& SM_STATUS_STATFS_BUSY
) {
807 smi
->smi_status
|= SM_STATUS_STATFS_WANT
;
808 if (!cv_wait_sig(&smi
->smi_statvfs_cv
, &smi
->smi_lock
)) {
809 mutex_exit(&smi
->smi_lock
);
812 /* Hope status is valid now. */
815 smi
->smi_status
|= SM_STATUS_STATFS_BUSY
;
816 mutex_exit(&smi
->smi_lock
);
819 * Do the OTW call. Note: lock NOT held.
821 smb_credinit(&scred
, NULL
);
822 bzero(&stvfs
, sizeof (stvfs
));
823 error
= smbfs_smb_statfs(ssp
, &stvfs
, &scred
);
824 smb_credrele(&scred
);
826 SMBVDEBUG("statfs error=%d\n", error
);
830 * Set a few things the OTW call didn't get.
832 stvfs
.f_frsize
= stvfs
.f_bsize
;
833 stvfs
.f_favail
= stvfs
.f_ffree
;
834 stvfs
.f_fsid
= (unsigned long)vfsp
->vfs_fsid
.val
[0];
835 bcopy(fs_type_name
, stvfs
.f_basetype
, FSTYPSZ
);
836 stvfs
.f_flag
= vf_to_stf(vfsp
->vfs_flag
);
837 stvfs
.f_namemax
= smi
->smi_fsa
.fsa_maxname
;
840 * Save the result, update lifetime
843 smi
->smi_statfstime
= now
+
844 (SM_MAX_STATFSTIME
* (hrtime_t
)NANOSEC
);
845 smi
->smi_statvfsbuf
= stvfs
; /* struct assign! */
848 mutex_enter(&smi
->smi_lock
);
849 if (smi
->smi_status
& SM_STATUS_STATFS_WANT
)
850 cv_broadcast(&smi
->smi_statvfs_cv
);
851 smi
->smi_status
&= ~(SM_STATUS_STATFS_BUSY
| SM_STATUS_STATFS_WANT
);
854 * Copy the statvfs data to caller's buf.
855 * Note: struct assignment
859 *sbp
= smi
->smi_statvfsbuf
;
860 mutex_exit(&smi
->smi_lock
);
865 * Flush dirty smbfs files for file system vfsp.
866 * If vfsp == NULL, all smbfs files are flushed.
870 smbfs_sync(vfs_t
*vfsp
, short flag
, cred_t
*cr
)
874 * SYNC_ATTR is used by fsflush() to force old filesystems like UFS
875 * to sync metadata, which they would otherwise cache indefinitely.
876 * Semantically, the only requirement is that the sync be initiated.
877 * Assume the server-side takes care of attribute sync.
879 if (flag
& SYNC_ATTR
)
884 * Flush ALL smbfs mounts in this zone.
890 smbfs_rflush(vfsp
, cr
);
896 * Initialization routine for VFS routines. Should only be called once
905 * Shutdown routine for VFS routines. Should only be called once
913 smbfs_freevfs(vfs_t
*vfsp
)
917 /* free up the resources */
921 * By this time we should have already deleted the
922 * smi kstats in the unmount code. If they are still around
925 ASSERT(smi
->smi_io_kstats
== NULL
);
927 smbfs_zonelist_remove(smi
);
932 * Allow _fini() to succeed now, if so desired.
934 atomic_dec_32(&smbfs_mountcount
);