1d167cf6fSWarner Losh /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3d63027b6SPedro F. Giffuni *
4d122d784SJoel Dahl * Copyright (c) 2000-2001 Boris Popov
5681a5bbeSBoris Popov * All rights reserved.
6681a5bbeSBoris Popov *
7681a5bbeSBoris Popov * Redistribution and use in source and binary forms, with or without
8681a5bbeSBoris Popov * modification, are permitted provided that the following conditions
9681a5bbeSBoris Popov * are met:
10681a5bbeSBoris Popov * 1. Redistributions of source code must retain the above copyright
11681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer.
12681a5bbeSBoris Popov * 2. Redistributions in binary form must reproduce the above copyright
13681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer in the
14681a5bbeSBoris Popov * documentation and/or other materials provided with the distribution.
15681a5bbeSBoris Popov *
16681a5bbeSBoris Popov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17681a5bbeSBoris Popov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18681a5bbeSBoris Popov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19681a5bbeSBoris Popov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20681a5bbeSBoris Popov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21681a5bbeSBoris Popov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22681a5bbeSBoris Popov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23681a5bbeSBoris Popov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24681a5bbeSBoris Popov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25681a5bbeSBoris Popov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26681a5bbeSBoris Popov * SUCH DAMAGE.
27681a5bbeSBoris Popov */
28681a5bbeSBoris Popov
29681a5bbeSBoris Popov #include <sys/param.h>
30681a5bbeSBoris Popov #include <sys/systm.h>
31681a5bbeSBoris Popov #include <sys/proc.h>
32681a5bbeSBoris Popov #include <sys/bio.h>
33681a5bbeSBoris Popov #include <sys/buf.h>
34681a5bbeSBoris Popov #include <sys/kernel.h>
35681a5bbeSBoris Popov #include <sys/sysctl.h>
36681a5bbeSBoris Popov #include <sys/vnode.h>
37681a5bbeSBoris Popov #include <sys/mount.h>
38681a5bbeSBoris Popov #include <sys/stat.h>
39681a5bbeSBoris Popov #include <sys/malloc.h>
4053f09e72SSheldon Hearn #include <sys/module.h>
417947229fSRobert Watson #include <sys/sx.h>
42681a5bbeSBoris Popov
43681a5bbeSBoris Popov #include <netsmb/smb.h>
44681a5bbeSBoris Popov #include <netsmb/smb_conn.h>
45681a5bbeSBoris Popov #include <netsmb/smb_subr.h>
46681a5bbeSBoris Popov #include <netsmb/smb_dev.h>
47681a5bbeSBoris Popov
48681a5bbeSBoris Popov #include <fs/smbfs/smbfs.h>
49681a5bbeSBoris Popov #include <fs/smbfs/smbfs_node.h>
50681a5bbeSBoris Popov #include <fs/smbfs/smbfs_subr.h>
51681a5bbeSBoris Popov
52f70f851cSPoul-Henning Kamp static int smbfs_debuglevel = 0;
53681a5bbeSBoris Popov
54681a5bbeSBoris Popov static int smbfs_version = SMBFS_VERSION;
55681a5bbeSBoris Popov
567029da5cSPawel Biernacki SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
577029da5cSPawel Biernacki "SMB/CIFS filesystem");
58681a5bbeSBoris Popov SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, "");
59681a5bbeSBoris Popov SYSCTL_INT(_vfs_smbfs, OID_AUTO, debuglevel, CTLFLAG_RW, &smbfs_debuglevel, 0, "");
60681a5bbeSBoris Popov
617652131bSPoul-Henning Kamp static vfs_init_t smbfs_init;
627652131bSPoul-Henning Kamp static vfs_uninit_t smbfs_uninit;
63d14c8441SPoul-Henning Kamp static vfs_cmount_t smbfs_cmount;
64d14c8441SPoul-Henning Kamp static vfs_mount_t smbfs_mount;
657652131bSPoul-Henning Kamp static vfs_root_t smbfs_root;
667652131bSPoul-Henning Kamp static vfs_quotactl_t smbfs_quotactl;
677652131bSPoul-Henning Kamp static vfs_statfs_t smbfs_statfs;
687652131bSPoul-Henning Kamp static vfs_unmount_t smbfs_unmount;
69681a5bbeSBoris Popov
70681a5bbeSBoris Popov static struct vfsops smbfs_vfsops = {
717652131bSPoul-Henning Kamp .vfs_init = smbfs_init,
72d14c8441SPoul-Henning Kamp .vfs_cmount = smbfs_cmount,
73d14c8441SPoul-Henning Kamp .vfs_mount = smbfs_mount,
747652131bSPoul-Henning Kamp .vfs_quotactl = smbfs_quotactl,
757652131bSPoul-Henning Kamp .vfs_root = smbfs_root,
767652131bSPoul-Henning Kamp .vfs_statfs = smbfs_statfs,
777652131bSPoul-Henning Kamp .vfs_sync = vfs_stdsync,
787652131bSPoul-Henning Kamp .vfs_uninit = smbfs_uninit,
797652131bSPoul-Henning Kamp .vfs_unmount = smbfs_unmount,
80681a5bbeSBoris Popov };
81681a5bbeSBoris Popov
82681a5bbeSBoris Popov VFS_SET(smbfs_vfsops, smbfs, VFCF_NETWORK);
83681a5bbeSBoris Popov
84681a5bbeSBoris Popov MODULE_DEPEND(smbfs, netsmb, NSMB_VERSION, NSMB_VERSION, NSMB_VERSION);
85c4f02a89SMax Khon MODULE_DEPEND(smbfs, libiconv, 1, 1, 2);
8653f09e72SSheldon Hearn MODULE_DEPEND(smbfs, libmchain, 1, 1, 1);
87681a5bbeSBoris Popov
88756a5412SGleb Smirnoff uma_zone_t smbfs_pbuf_zone;
89681a5bbeSBoris Popov
90681a5bbeSBoris Popov static int
smbfs_cmount(struct mntarg * ma,void * data,uint64_t flags)91cc672d35SKirk McKusick smbfs_cmount(struct mntarg *ma, void * data, uint64_t flags)
92681a5bbeSBoris Popov {
93d14c8441SPoul-Henning Kamp struct smbfs_args args;
94681a5bbeSBoris Popov int error;
9564042a76SPoul-Henning Kamp
960430a5e2SDag-Erling Smørgrav error = copyin(data, &args, sizeof(struct smbfs_args));
97681a5bbeSBoris Popov if (error)
98681a5bbeSBoris Popov return error;
99d14c8441SPoul-Henning Kamp
100681a5bbeSBoris Popov if (args.version != SMBFS_VERSION) {
101681a5bbeSBoris Popov printf("mount version mismatch: kernel=%d, mount=%d\n",
102681a5bbeSBoris Popov SMBFS_VERSION, args.version);
103681a5bbeSBoris Popov return EINVAL;
104681a5bbeSBoris Popov }
105d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "dev", "%d", args.dev);
106d14c8441SPoul-Henning Kamp ma = mount_argb(ma, args.flags & SMBFS_MOUNT_SOFT, "nosoft");
107d14c8441SPoul-Henning Kamp ma = mount_argb(ma, args.flags & SMBFS_MOUNT_INTR, "nointr");
108d14c8441SPoul-Henning Kamp ma = mount_argb(ma, args.flags & SMBFS_MOUNT_STRONG, "nostrong");
109d14c8441SPoul-Henning Kamp ma = mount_argb(ma, args.flags & SMBFS_MOUNT_HAVE_NLS, "nohave_nls");
110d14c8441SPoul-Henning Kamp ma = mount_argb(ma, !(args.flags & SMBFS_MOUNT_NO_LONG), "nolong");
111d14c8441SPoul-Henning Kamp ma = mount_arg(ma, "rootpath", args.root_path, -1);
112d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "uid", "%d", args.uid);
113d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "gid", "%d", args.gid);
114d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "file_mode", "%d", args.file_mode);
115d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "dir_mode", "%d", args.dir_mode);
116d14c8441SPoul-Henning Kamp ma = mount_argf(ma, "caseopt", "%d", args.caseopt);
117d14c8441SPoul-Henning Kamp
118d14c8441SPoul-Henning Kamp error = kernel_mount(ma, flags);
119d14c8441SPoul-Henning Kamp
120d14c8441SPoul-Henning Kamp return (error);
121d14c8441SPoul-Henning Kamp }
122d14c8441SPoul-Henning Kamp
123d14c8441SPoul-Henning Kamp static const char *smbfs_opts[] = {
12492a4d9bcSDavide Italiano "fd", "soft", "intr", "strong", "have_nls", "long",
125d14c8441SPoul-Henning Kamp "mountpoint", "rootpath", "uid", "gid", "file_mode", "dir_mode",
12643fa5bf5SCraig Rodrigues "caseopt", "errmsg", NULL
127d14c8441SPoul-Henning Kamp };
128d14c8441SPoul-Henning Kamp
129d14c8441SPoul-Henning Kamp static int
smbfs_mount(struct mount * mp)130dfd233edSAttilio Rao smbfs_mount(struct mount *mp)
131d14c8441SPoul-Henning Kamp {
132d14c8441SPoul-Henning Kamp struct smbmount *smp = NULL;
133d14c8441SPoul-Henning Kamp struct smb_vc *vcp;
134d14c8441SPoul-Henning Kamp struct smb_share *ssp = NULL;
135d14c8441SPoul-Henning Kamp struct vnode *vp;
136dfd233edSAttilio Rao struct thread *td;
13792a4d9bcSDavide Italiano struct smb_dev *dev;
138afe09751SDavide Italiano struct smb_cred *scred;
139d14c8441SPoul-Henning Kamp int error, v;
140d14c8441SPoul-Henning Kamp char *pc, *pe;
141d14c8441SPoul-Henning Kamp
14292a4d9bcSDavide Italiano dev = NULL;
143dfd233edSAttilio Rao td = curthread;
144d14c8441SPoul-Henning Kamp if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
145d14c8441SPoul-Henning Kamp return EOPNOTSUPP;
146d14c8441SPoul-Henning Kamp
14743fa5bf5SCraig Rodrigues if (vfs_filteropt(mp->mnt_optnew, smbfs_opts)) {
14843fa5bf5SCraig Rodrigues vfs_mount_error(mp, "%s", "Invalid option");
149d14c8441SPoul-Henning Kamp return (EINVAL);
15043fa5bf5SCraig Rodrigues }
151d14c8441SPoul-Henning Kamp
152afe09751SDavide Italiano scred = smbfs_malloc_scred();
153afe09751SDavide Italiano smb_makescred(scred, td, td->td_ucred);
15492a4d9bcSDavide Italiano
15592a4d9bcSDavide Italiano /* Ask userspace of `fd`, the file descriptor of this session */
15692a4d9bcSDavide Italiano if (1 != vfs_scanopt(mp->mnt_optnew, "fd", "%d", &v)) {
15792a4d9bcSDavide Italiano vfs_mount_error(mp, "No fd option");
158afe09751SDavide Italiano smbfs_free_scred(scred);
159d14c8441SPoul-Henning Kamp return (EINVAL);
16043fa5bf5SCraig Rodrigues }
16192a4d9bcSDavide Italiano error = smb_dev2share(v, SMBM_EXEC, scred, &ssp, &dev);
16292a4d9bcSDavide Italiano smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
163681a5bbeSBoris Popov if (error) {
164d14c8441SPoul-Henning Kamp printf("invalid device handle %d (%d)\n", v, error);
16592a4d9bcSDavide Italiano vfs_mount_error(mp, "invalid device handle %d %d\n", v, error);
166afe09751SDavide Italiano smbfs_free_scred(scred);
16792a4d9bcSDavide Italiano free(smp, M_SMBFSDATA);
168681a5bbeSBoris Popov return error;
169681a5bbeSBoris Popov }
170681a5bbeSBoris Popov vcp = SSTOVC(ssp);
171a4c05984SDavide Italiano smb_share_unlock(ssp);
172681a5bbeSBoris Popov mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
17377465d93SAlfred Perlstein mp->mnt_data = smp;
174681a5bbeSBoris Popov smp->sm_share = ssp;
175681a5bbeSBoris Popov smp->sm_root = NULL;
17692a4d9bcSDavide Italiano smp->sm_dev = dev;
177d14c8441SPoul-Henning Kamp if (1 != vfs_scanopt(mp->mnt_optnew,
178d14c8441SPoul-Henning Kamp "caseopt", "%d", &smp->sm_caseopt)) {
17943fa5bf5SCraig Rodrigues vfs_mount_error(mp, "Invalid caseopt");
180d14c8441SPoul-Henning Kamp error = EINVAL;
181d14c8441SPoul-Henning Kamp goto bad;
182d14c8441SPoul-Henning Kamp }
183d14c8441SPoul-Henning Kamp if (1 != vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v)) {
18443fa5bf5SCraig Rodrigues vfs_mount_error(mp, "Invalid uid");
185d14c8441SPoul-Henning Kamp error = EINVAL;
186d14c8441SPoul-Henning Kamp goto bad;
187d14c8441SPoul-Henning Kamp }
188d14c8441SPoul-Henning Kamp smp->sm_uid = v;
189d14c8441SPoul-Henning Kamp
190d14c8441SPoul-Henning Kamp if (1 != vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v)) {
19143fa5bf5SCraig Rodrigues vfs_mount_error(mp, "Invalid gid");
192d14c8441SPoul-Henning Kamp error = EINVAL;
193d14c8441SPoul-Henning Kamp goto bad;
194d14c8441SPoul-Henning Kamp }
195d14c8441SPoul-Henning Kamp smp->sm_gid = v;
196d14c8441SPoul-Henning Kamp
197d14c8441SPoul-Henning Kamp if (1 != vfs_scanopt(mp->mnt_optnew, "file_mode", "%d", &v)) {
19843fa5bf5SCraig Rodrigues vfs_mount_error(mp, "Invalid file_mode");
199d14c8441SPoul-Henning Kamp error = EINVAL;
200d14c8441SPoul-Henning Kamp goto bad;
201d14c8441SPoul-Henning Kamp }
202d14c8441SPoul-Henning Kamp smp->sm_file_mode = (v & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
203d14c8441SPoul-Henning Kamp
204d14c8441SPoul-Henning Kamp if (1 != vfs_scanopt(mp->mnt_optnew, "dir_mode", "%d", &v)) {
20543fa5bf5SCraig Rodrigues vfs_mount_error(mp, "Invalid dir_mode");
206d14c8441SPoul-Henning Kamp error = EINVAL;
207d14c8441SPoul-Henning Kamp goto bad;
208d14c8441SPoul-Henning Kamp }
209d14c8441SPoul-Henning Kamp smp->sm_dir_mode = (v & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
210d14c8441SPoul-Henning Kamp
211d14c8441SPoul-Henning Kamp vfs_flagopt(mp->mnt_optnew,
2128bfc2304STai-hwa Liang "nolong", &smp->sm_flags, SMBFS_MOUNT_NO_LONG);
213681a5bbeSBoris Popov
214681a5bbeSBoris Popov pc = mp->mnt_stat.f_mntfromname;
215681a5bbeSBoris Popov pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
216681a5bbeSBoris Popov bzero(pc, MNAMELEN);
217681a5bbeSBoris Popov *pc++ = '/';
218681a5bbeSBoris Popov *pc++ = '/';
219dc15eac0SEd Schouten pc = strchr(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
220681a5bbeSBoris Popov if (pc < pe-1) {
221681a5bbeSBoris Popov *(pc++) = '@';
222dc15eac0SEd Schouten pc = strchr(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
223681a5bbeSBoris Popov if (pc < pe - 1) {
224681a5bbeSBoris Popov *(pc++) = '/';
225681a5bbeSBoris Popov strncpy(pc, ssp->ss_name, pe - pc - 2);
226681a5bbeSBoris Popov }
227681a5bbeSBoris Popov }
228681a5bbeSBoris Popov vfs_getnewfsid(mp);
229dfd233edSAttilio Rao error = smbfs_root(mp, LK_EXCLUSIVE, &vp);
23043fa5bf5SCraig Rodrigues if (error) {
23143fa5bf5SCraig Rodrigues vfs_mount_error(mp, "smbfs_root error: %d", error);
232681a5bbeSBoris Popov goto bad;
23343fa5bf5SCraig Rodrigues }
234b249ce48SMateusz Guzik VOP_UNLOCK(vp);
2354d93c0beSJeff Roberson SMBVDEBUG("root.v_usecount = %d\n", vrefcnt(vp));
236681a5bbeSBoris Popov
23790147b75SRuslan Ermilov #ifdef DIAGNOSTIC
238681a5bbeSBoris Popov SMBERROR("mp=%p\n", mp);
239681a5bbeSBoris Popov #endif
240afe09751SDavide Italiano smbfs_free_scred(scred);
241681a5bbeSBoris Popov return error;
242681a5bbeSBoris Popov bad:
243681a5bbeSBoris Popov if (ssp)
244afe09751SDavide Italiano smb_share_put(ssp, scred);
245afe09751SDavide Italiano smbfs_free_scred(scred);
24692a4d9bcSDavide Italiano SMB_LOCK();
24792a4d9bcSDavide Italiano if (error && smp->sm_dev == dev) {
24892a4d9bcSDavide Italiano smp->sm_dev = NULL;
24992a4d9bcSDavide Italiano sdp_trydestroy(dev);
25092a4d9bcSDavide Italiano }
25192a4d9bcSDavide Italiano SMB_UNLOCK();
25292a4d9bcSDavide Italiano free(smp, M_SMBFSDATA);
253681a5bbeSBoris Popov return error;
254681a5bbeSBoris Popov }
255681a5bbeSBoris Popov
256681a5bbeSBoris Popov /* Unmount the filesystem described by mp. */
257681a5bbeSBoris Popov static int
smbfs_unmount(struct mount * mp,int mntflags)258dfd233edSAttilio Rao smbfs_unmount(struct mount *mp, int mntflags)
259681a5bbeSBoris Popov {
260dfd233edSAttilio Rao struct thread *td;
261681a5bbeSBoris Popov struct smbmount *smp = VFSTOSMBFS(mp);
262afe09751SDavide Italiano struct smb_cred *scred;
26392a4d9bcSDavide Italiano struct smb_dev *dev;
264681a5bbeSBoris Popov int error, flags;
265681a5bbeSBoris Popov
266681a5bbeSBoris Popov SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
267dfd233edSAttilio Rao td = curthread;
268681a5bbeSBoris Popov flags = 0;
269681a5bbeSBoris Popov if (mntflags & MNT_FORCE)
270681a5bbeSBoris Popov flags |= FORCECLOSE;
271578dcf0cSTim J. Robbins /*
272578dcf0cSTim J. Robbins * Keep trying to flush the vnode list for the mount while
273578dcf0cSTim J. Robbins * some are still busy and we are making progress towards
274578dcf0cSTim J. Robbins * making them not busy. This is needed because smbfs vnodes
275578dcf0cSTim J. Robbins * reference their parent directory but may appear after their
276578dcf0cSTim J. Robbins * parent in the list; one pass over the vnode list is not
277578dcf0cSTim J. Robbins * sufficient in this case.
278578dcf0cSTim J. Robbins */
279578dcf0cSTim J. Robbins do {
280578dcf0cSTim J. Robbins smp->sm_didrele = 0;
2810864ef1eSIan Dowse /* There is 1 extra root vnode reference from smbfs_mount(). */
282f257b7a5SAlfred Perlstein error = vflush(mp, 1, flags, td);
283578dcf0cSTim J. Robbins } while (error == EBUSY && smp->sm_didrele != 0);
284681a5bbeSBoris Popov if (error)
285681a5bbeSBoris Popov return error;
286afe09751SDavide Italiano scred = smbfs_malloc_scred();
287afe09751SDavide Italiano smb_makescred(scred, td, td->td_ucred);
288a4c05984SDavide Italiano error = smb_share_lock(smp->sm_share);
289fe785383SJohn Baldwin if (error)
290afe09751SDavide Italiano goto out;
291afe09751SDavide Italiano smb_share_put(smp->sm_share, scred);
29292a4d9bcSDavide Italiano SMB_LOCK();
29392a4d9bcSDavide Italiano dev = smp->sm_dev;
29492a4d9bcSDavide Italiano if (!dev)
29592a4d9bcSDavide Italiano panic("No private data for mount point");
29692a4d9bcSDavide Italiano sdp_trydestroy(dev);
29777465d93SAlfred Perlstein mp->mnt_data = NULL;
29892a4d9bcSDavide Italiano SMB_UNLOCK();
299681a5bbeSBoris Popov free(smp, M_SMBFSDATA);
300afe09751SDavide Italiano out:
301afe09751SDavide Italiano smbfs_free_scred(scred);
302681a5bbeSBoris Popov return error;
303681a5bbeSBoris Popov }
304681a5bbeSBoris Popov
305681a5bbeSBoris Popov /*
306681a5bbeSBoris Popov * Return locked root vnode of a filesystem
307681a5bbeSBoris Popov */
308681a5bbeSBoris Popov static int
smbfs_root(struct mount * mp,int flags,struct vnode ** vpp)309dfd233edSAttilio Rao smbfs_root(struct mount *mp, int flags, struct vnode **vpp)
310681a5bbeSBoris Popov {
311681a5bbeSBoris Popov struct smbmount *smp = VFSTOSMBFS(mp);
312681a5bbeSBoris Popov struct vnode *vp;
313681a5bbeSBoris Popov struct smbnode *np;
314681a5bbeSBoris Popov struct smbfattr fattr;
315dfd233edSAttilio Rao struct thread *td;
316dfd233edSAttilio Rao struct ucred *cred;
317afe09751SDavide Italiano struct smb_cred *scred;
318681a5bbeSBoris Popov int error;
319681a5bbeSBoris Popov
320dfd233edSAttilio Rao td = curthread;
321dfd233edSAttilio Rao cred = td->td_ucred;
322dfd233edSAttilio Rao
323681a5bbeSBoris Popov if (smp->sm_root) {
324681a5bbeSBoris Popov *vpp = SMBTOV(smp->sm_root);
325a92a971bSMateusz Guzik return vget(*vpp, LK_EXCLUSIVE | LK_RETRY);
326681a5bbeSBoris Popov }
327afe09751SDavide Italiano scred = smbfs_malloc_scred();
328afe09751SDavide Italiano smb_makescred(scred, td, cred);
329afe09751SDavide Italiano error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, scred);
330681a5bbeSBoris Popov if (error)
331afe09751SDavide Italiano goto out;
33280704a47SDavide Italiano error = smbfs_nget(mp, NULL, NULL, 0, &fattr, &vp);
333681a5bbeSBoris Popov if (error)
334afe09751SDavide Italiano goto out;
335e6e370a7SJeff Roberson ASSERT_VOP_LOCKED(vp, "smbfs_root");
336e6e370a7SJeff Roberson vp->v_vflag |= VV_ROOT;
337681a5bbeSBoris Popov np = VTOSMB(vp);
338681a5bbeSBoris Popov smp->sm_root = np;
339681a5bbeSBoris Popov *vpp = vp;
340afe09751SDavide Italiano out:
341afe09751SDavide Italiano smbfs_free_scred(scred);
342afe09751SDavide Italiano return error;
343681a5bbeSBoris Popov }
344681a5bbeSBoris Popov
3458e67c454STim J. Robbins /*
3468e67c454STim J. Robbins * Do operations associated with quotas, not supported
3478e67c454STim J. Robbins */
3488e67c454STim J. Robbins /* ARGSUSED */
3498e67c454STim J. Robbins static int
smbfs_quotactl(struct mount * mp,int cmd,uid_t uid,void * arg,bool * mp_busy)350b09b03a1SMateusz Guzik smbfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg, bool *mp_busy)
3518e67c454STim J. Robbins {
3528e67c454STim J. Robbins SMBVDEBUG("return EOPNOTSUPP\n");
3538e67c454STim J. Robbins return EOPNOTSUPP;
3548e67c454STim J. Robbins }
3558e67c454STim J. Robbins
356681a5bbeSBoris Popov /*ARGSUSED*/
357681a5bbeSBoris Popov int
smbfs_init(struct vfsconf * vfsp)358681a5bbeSBoris Popov smbfs_init(struct vfsconf *vfsp)
359681a5bbeSBoris Popov {
360756a5412SGleb Smirnoff
361756a5412SGleb Smirnoff smbfs_pbuf_zone = pbuf_zsecond_create("smbpbuf", nswbuf / 2);
362681a5bbeSBoris Popov SMBVDEBUG("done.\n");
363681a5bbeSBoris Popov return 0;
364681a5bbeSBoris Popov }
365681a5bbeSBoris Popov
3668e67c454STim J. Robbins /*ARGSUSED*/
3678e67c454STim J. Robbins int
smbfs_uninit(struct vfsconf * vfsp)3688e67c454STim J. Robbins smbfs_uninit(struct vfsconf *vfsp)
3698e67c454STim J. Robbins {
3708e67c454STim J. Robbins
371756a5412SGleb Smirnoff uma_zdestroy(smbfs_pbuf_zone);
3728e67c454STim J. Robbins SMBVDEBUG("done.\n");
3738e67c454STim J. Robbins return 0;
3748e67c454STim J. Robbins }
3758e67c454STim J. Robbins
376681a5bbeSBoris Popov /*
377681a5bbeSBoris Popov * smbfs_statfs call
378681a5bbeSBoris Popov */
379681a5bbeSBoris Popov int
smbfs_statfs(struct mount * mp,struct statfs * sbp)380dfd233edSAttilio Rao smbfs_statfs(struct mount *mp, struct statfs *sbp)
381681a5bbeSBoris Popov {
382dfd233edSAttilio Rao struct thread *td = curthread;
383681a5bbeSBoris Popov struct smbmount *smp = VFSTOSMBFS(mp);
384681a5bbeSBoris Popov struct smbnode *np = smp->sm_root;
385681a5bbeSBoris Popov struct smb_share *ssp = smp->sm_share;
386afe09751SDavide Italiano struct smb_cred *scred;
38714b2dc39SAndrey V. Elsukov int error;
388681a5bbeSBoris Popov
38943fa5bf5SCraig Rodrigues if (np == NULL) {
39043fa5bf5SCraig Rodrigues vfs_mount_error(mp, "np == NULL");
391681a5bbeSBoris Popov return EINVAL;
39243fa5bf5SCraig Rodrigues }
393681a5bbeSBoris Popov
394681a5bbeSBoris Popov sbp->f_iosize = SSTOVC(ssp)->vc_txmax; /* optimal transfer block size */
395afe09751SDavide Italiano scred = smbfs_malloc_scred();
396afe09751SDavide Italiano smb_makescred(scred, td, td->td_ucred);
397afe09751SDavide Italiano error = smbfs_smb_statfs(ssp, sbp, scred);
398afe09751SDavide Italiano smbfs_free_scred(scred);
39914b2dc39SAndrey V. Elsukov return (error);
400681a5bbeSBoris Popov }
401