xref: /freebsd/sys/fs/smbfs/smbfs_vfsops.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
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