VirtualBox

source: vbox/trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c@ 88189

最後變更 在這個檔案從88189是 88189,由 vboxsync 提交於 4 年 前

Some small Solaris-specific build warning fixes:

Additions/solaris/DRM: Remove unused global variable 'g_pDip' from vboxvideo_drm.c.

Additions/solaris/SharedFolders: Add additional #ifdef/#endif around sffs_print() to silence warning: 'sffs_print' defined but not used

IPRT/coredump-solaris: Remove unnecessary and incorrect tag from the ELFWRITENOTE structure declaration which the compiler flags as 'declaration of 'ELFWRITENOTE' shadows a previous local'.

IPRT/thread-posix.cpp: Only call 'Assert((uintptr_t)Self != NIL_RTNATIVETHREAD)' on non-Solaris platforms since the size of pthread_t is implementation-dependent and on Solaris sizeof(pthread_t) = 4 whereas on Linux/MacOS/FreeBSD it is 8. The compiler thus flags this on Solaris as 'comparison is always true due to limited range of data type'.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 14.3 KB
 
1/* $Id: vboxfs_vfs.c 88189 2021-03-18 11:07:36Z vboxsync $ */
2/** @file
3 * VirtualBox File System for Solaris Guests, VFS implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#include <VBox/log.h>
28#include <VBox/version.h>
29
30#include <sys/types.h>
31#include <sys/mntent.h>
32#include <sys/param.h>
33#include <sys/modctl.h>
34#include <sys/mount.h>
35#include <sys/policy.h>
36#include <sys/atomic.h>
37#include <sys/sysmacros.h>
38#include <sys/ddi.h>
39#include <sys/sunddi.h>
40#include <sys/vfs.h>
41#if !defined(VBOX_VFS_SOLARIS_10U6)
42# include <sys/vfs_opreg.h>
43#endif
44#include <sys/pathname.h>
45#include <sys/cmn_err.h>
46#undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
47
48#include "vboxfs_prov.h"
49#include "vboxfs_vnode.h"
50#include "vboxfs_vfs.h"
51#include "vboxfs.h"
52
53
54#define VBOXSOLQUOTE2(x) #x
55#define VBOXSOLQUOTE(x) VBOXSOLQUOTE2(x)
56/** The module name. */
57#define DEVICE_NAME "vboxfs"
58/** The module description as seen in 'modinfo'. */
59#define DEVICE_DESC "VirtualBox ShrdFS"
60
61
62/*
63 * Shared Folders filesystem implementation of the Solaris VFS interfaces.
64 * Much of this is cookie cutter code for Solaris filesystem implementation.
65 */
66
67/* forward declarations */
68static int sffs_init(int fstype, char *name);
69static int sffs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *);
70static int sffs_unmount(vfs_t *vfsp, int flag, cred_t *cr);
71static int sffs_root(vfs_t *vfsp, vnode_t **vpp);
72static int sffs_statvfs(vfs_t *vfsp, statvfs64_t *sbp);
73
74static mntopt_t sffs_options[] = {
75 /* Option Cancels Opt Arg Flags Data */
76 {"uid", NULL, NULL, MO_HASVALUE, NULL},
77 {"gid", NULL, NULL, MO_HASVALUE, NULL},
78 {"dmode", NULL, NULL, MO_HASVALUE, NULL},
79 {"fmode", NULL, NULL, MO_HASVALUE, NULL},
80 {"dmask", NULL, NULL, MO_HASVALUE, NULL},
81 {"fmask", NULL, NULL, MO_HASVALUE, NULL},
82 {"stat_ttl", NULL, NULL, MO_HASVALUE, NULL},
83 {"fsync", NULL, NULL, 0, NULL},
84 {"tag", NULL, NULL, MO_HASVALUE, NULL}
85};
86
87static mntopts_t sffs_options_table = {
88 sizeof (sffs_options) / sizeof (mntopt_t),
89 sffs_options
90};
91
92static vfsdef_t sffs_vfsdef = {
93 VFSDEF_VERSION,
94 DEVICE_NAME,
95 sffs_init,
96 VSW_HASPROTO,
97 &sffs_options_table
98};
99
100static int sffs_fstype;
101static int sffs_major; /* major number for device */
102
103kmutex_t sffs_minor_lock;
104int sffs_minor; /* minor number for device */
105
106/*
107 * Module linkage information
108 */
109static struct modlfs modlfs = {
110 &mod_fsops,
111 DEVICE_DESC " " VBOX_VERSION_STRING "r" VBOXSOLQUOTE(VBOX_SVN_REV),
112 &sffs_vfsdef
113};
114
115static struct modlinkage modlinkage = {
116 MODREV_1, &modlfs, NULL
117};
118
119static sfp_connection_t *sfprov = NULL;
120
121int
122_init()
123{
124 return (mod_install(&modlinkage));
125}
126
127int
128_info(struct modinfo *modinfop)
129{
130 return (mod_info(&modlinkage, modinfop));
131}
132
133
134int
135_fini()
136{
137 int error;
138
139 error = mod_remove(&modlinkage);
140 if (error)
141 return (error);
142
143 /*
144 * Tear down the operations vectors
145 */
146 sffs_vnode_fini();
147 (void) vfs_freevfsops_by_type(sffs_fstype);
148
149 /*
150 * close connection to the provider
151 */
152 sfprov_disconnect(sfprov);
153 return (0);
154}
155
156
157static int
158sffs_init(int fstype, char *name)
159{
160#if defined(VBOX_VFS_SOLARIS_10U6)
161 static const fs_operation_def_t sffs_vfsops_template[] = {
162 VFSNAME_MOUNT, sffs_mount,
163 VFSNAME_UNMOUNT, sffs_unmount,
164 VFSNAME_ROOT, sffs_root,
165 VFSNAME_STATVFS, sffs_statvfs,
166 NULL, NULL
167 };
168#else
169 static const fs_operation_def_t sffs_vfsops_template[] = {
170 VFSNAME_MOUNT, { .vfs_mount = sffs_mount },
171 VFSNAME_UNMOUNT, { .vfs_unmount = sffs_unmount },
172 VFSNAME_ROOT, { .vfs_root = sffs_root },
173 VFSNAME_STATVFS, { .vfs_statvfs = sffs_statvfs },
174 NULL, NULL
175 };
176#endif
177 int error;
178
179 ASSERT(fstype != 0);
180 sffs_fstype = fstype;
181 LogFlowFunc(("sffs_init() name=%s\n", name));
182
183 /*
184 * This may seem a silly way to do things for now. But the code
185 * is structured to easily allow it to be used on other hypervisors
186 * which would have a different implementation of the provider.
187 * Hopefully that'll never happen. :)
188 */
189 sfprov = sfprov_connect(SFPROV_VERSION);
190 if (sfprov == NULL) {
191 cmn_err(CE_WARN, "sffs_init: couldn't init sffs provider");
192 return (ENODEV);
193 }
194
195 error = sfprov_set_show_symlinks();
196 if (error != 0) {
197 cmn_err(CE_WARN, "sffs_init: host unable to show symlinks, "
198 "rc=%d\n", error);
199 }
200
201 error = vfs_setfsops(fstype, sffs_vfsops_template, NULL);
202 if (error != 0) {
203 cmn_err(CE_WARN, "sffs_init: bad vfs ops template");
204 return (error);
205 }
206
207 error = sffs_vnode_init();
208 if (error != 0) {
209 (void) vfs_freevfsops_by_type(fstype);
210 cmn_err(CE_WARN, "sffs_init: bad vnode ops template");
211 return (error);
212 }
213
214 if ((sffs_major = getudev()) == (major_t)-1) {
215 cmn_err(CE_WARN, "sffs_init: Can't get unique device number.");
216 sffs_major = 0;
217 }
218 mutex_init(&sffs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
219 return (0);
220}
221
222/*
223 * wrapper for pn_get
224 */
225static int
226sf_pn_get(char *rawpath, struct mounta *uap, char **outpath)
227{
228 pathname_t path;
229 int error;
230
231 error = pn_get(rawpath, (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE :
232 UIO_USERSPACE, &path);
233 if (error) {
234 LogFlowFunc(("pn_get(%s) failed\n", rawpath));
235 return (error);
236 }
237 *outpath = kmem_alloc(path.pn_pathlen + 1, KM_SLEEP);
238 strcpy(*outpath, path.pn_path);
239 pn_free(&path);
240 return (0);
241}
242
243#ifdef DEBUG_ramshankar
244static void
245sffs_print(sffs_data_t *sffs)
246{
247 cmn_err(CE_NOTE, "sffs_data_t at 0x%p\n", sffs);
248 cmn_err(CE_NOTE, " vfs_t *sf_vfsp = 0x%p\n", sffs->sf_vfsp);
249 cmn_err(CE_NOTE, " vnode_t *sf_rootnode = 0x%p\n", sffs->sf_rootnode);
250 cmn_err(CE_NOTE, " uid_t sf_uid = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_uid);
251 cmn_err(CE_NOTE, " gid_t sf_gid = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_gid);
252 cmn_err(CE_NOTE, " mode_t sf_dmode = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_dmode);
253 cmn_err(CE_NOTE, " mode_t sf_fmode = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_fmode);
254 cmn_err(CE_NOTE, " mode_t sf_dmask = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_dmask);
255 cmn_err(CE_NOTE, " mode_t sf_fmask = 0x%lu\n", (ulong_t)sffs->sf_handle->sf_fmask);
256 cmn_err(CE_NOTE, " char *sf_share_name = %s\n", sffs->sf_share_name);
257 cmn_err(CE_NOTE, " char *sf_mntpath = %s\n", sffs->sf_mntpath);
258 cmn_err(CE_NOTE, " sfp_mount_t *sf_handle = 0x%p\n", sffs->sf_handle);
259}
260#endif
261
262static int
263sffs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
264{
265 sffs_data_t *sffs;
266 char *mount_point = NULL;
267 char *share_name = NULL;
268 int error;
269 dev_t dev;
270 uid_t uid = 0;
271 gid_t gid = 0;
272 mode_t dmode = ~0U;
273 mode_t fmode = ~0U;
274 mode_t dmask = 0;
275 mode_t fmask = 0;
276 int stat_ttl = DEF_STAT_TTL_MS;
277 int fsync = 0;
278 char *optval;
279 long val;
280 char *path;
281 sfp_mount_t *handle;
282 sfnode_t *sfnode;
283
284 /*
285 * check we have permission to do the mount
286 */
287 LogFlowFunc(("sffs_mount() started\n"));
288 error = secpolicy_fs_mount(cr, mvp, vfsp);
289 if (error != 0)
290 return (error);
291
292 /*
293 * Mount point must be a directory
294 */
295 if (mvp->v_type != VDIR)
296 return (ENOTDIR);
297
298 /*
299 * no support for remount (what is it?)
300 */
301 if (uap->flags & MS_REMOUNT)
302 return (ENOTSUP);
303
304 /*
305 * Ensure that nothing else is actively in/under the mount point
306 */
307 mutex_enter(&mvp->v_lock);
308 if ((uap->flags & MS_OVERLAY) == 0 &&
309 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
310 mutex_exit(&mvp->v_lock);
311 return (EBUSY);
312 }
313 mutex_exit(&mvp->v_lock);
314
315 /*
316 * check for read only has to be done early
317 */
318 if (uap->flags & MS_RDONLY) {
319 vfsp->vfs_flag |= VFS_RDONLY;
320 vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
321 }
322
323 /*
324 * UID to use for all files
325 */
326 if (vfs_optionisset(vfsp, "uid", &optval) &&
327 ddi_strtol(optval, NULL, 10, &val) == 0 &&
328 (uid_t)val == val)
329 uid = val;
330
331 /*
332 * GID to use for all files
333 */
334 if (vfs_optionisset(vfsp, "gid", &optval) &&
335 ddi_strtol(optval, NULL, 10, &val) == 0 &&
336 (gid_t)val == val)
337 gid = val;
338
339 /*
340 * dmode to use for all directories
341 */
342 if (vfs_optionisset(vfsp, "dmode", &optval) &&
343 ddi_strtol(optval, NULL, 8, &val) == 0 &&
344 (mode_t)val == val)
345 dmode = val;
346
347 /*
348 * fmode to use for all files
349 */
350 if (vfs_optionisset(vfsp, "fmode", &optval) &&
351 ddi_strtol(optval, NULL, 8, &val) == 0 &&
352 (mode_t)val == val)
353 fmode = val;
354
355 /*
356 * dmask to use for all directories
357 */
358 if (vfs_optionisset(vfsp, "dmask", &optval) &&
359 ddi_strtol(optval, NULL, 8, &val) == 0 &&
360 (mode_t)val == val)
361 dmask = val;
362
363 /*
364 * fmask to use for all files
365 */
366 if (vfs_optionisset(vfsp, "fmask", &optval) &&
367 ddi_strtol(optval, NULL, 8, &val) == 0 &&
368 (mode_t)val == val)
369 fmask = val;
370
371 /*
372 * umask to use for all directories & files
373 */
374 if (vfs_optionisset(vfsp, "umask", &optval) &&
375 ddi_strtol(optval, NULL, 8, &val) == 0 &&
376 (mode_t)val == val)
377 dmask = fmask = val;
378
379 /*
380 * ttl to use for stat caches
381 */
382 if (vfs_optionisset(vfsp, "stat_ttl", &optval) &&
383 ddi_strtol(optval, NULL, 10, &val) == 0 &&
384 (int)val == val)
385 {
386 stat_ttl = val;
387 }
388 else
389 vfs_setmntopt(vfsp, "stat_ttl", VBOXSOLQUOTE(DEF_STAT_TTL_MS), 0);
390
391 /*
392 * whether to honor fsync
393 */
394 if (vfs_optionisset(vfsp, "fsync", &optval))
395 fsync = 1;
396
397 /*
398 * Any unknown options are an error
399 */
400 if ((uap->flags & MS_DATA) && uap->datalen > 0) {
401 cmn_err(CE_WARN, "sffs: unknown mount options specified");
402 return (EINVAL);
403 }
404
405 /*
406 * get the mount point pathname
407 */
408 error = sf_pn_get(uap->dir, uap, &mount_point);
409 if (error)
410 return (error);
411
412 /*
413 * find what we are mounting
414 */
415 error = sf_pn_get(uap->spec, uap, &share_name);
416 if (error) {
417 kmem_free(mount_point, strlen(mount_point) + 1);
418 return (error);
419 }
420
421 /*
422 * Invoke Hypervisor mount interface before proceeding
423 */
424 error = sfprov_mount(sfprov, share_name, &handle);
425 if (error) {
426 kmem_free(share_name, strlen(share_name) + 1);
427 kmem_free(mount_point, strlen(mount_point) + 1);
428 return (error);
429 }
430
431 /*
432 * find an available minor device number for this mount
433 */
434 mutex_enter(&sffs_minor_lock);
435 do {
436 sffs_minor = (sffs_minor + 1) & L_MAXMIN32;
437 dev = makedevice(sffs_major, sffs_minor);
438 } while (vfs_devismounted(dev));
439 mutex_exit(&sffs_minor_lock);
440
441 /*
442 * allocate and fill in the sffs structure
443 */
444 sffs = kmem_alloc(sizeof (*sffs), KM_SLEEP);
445 sffs->sf_vfsp = vfsp;
446 sffs->sf_handle = handle;
447 sffs->sf_handle->sf_uid = uid;
448 sffs->sf_handle->sf_gid = gid;
449 sffs->sf_handle->sf_dmode = dmode;
450 sffs->sf_handle->sf_fmode = fmode;
451 sffs->sf_handle->sf_dmask = dmask;
452 sffs->sf_handle->sf_fmask = fmask;
453 sffs->sf_stat_ttl = stat_ttl;
454 sffs->sf_fsync = fsync;
455 sffs->sf_share_name = share_name;
456 sffs->sf_mntpath = mount_point;
457 sffs->sf_ino = 3; /* root mount point is always '3' */
458
459 /*
460 * fill in the vfs structure
461 */
462 vfsp->vfs_data = (caddr_t)sffs;
463 vfsp->vfs_fstype = sffs_fstype;
464 vfsp->vfs_dev = dev;
465 vfsp->vfs_bsize = PAGESIZE; /* HERE JOE ??? */
466 vfsp->vfs_flag |= VFS_NOTRUNC; /* HERE JOE ???? */
467 vfs_make_fsid(&vfsp->vfs_fsid, dev, sffs_fstype);
468
469 /*
470 * create the root vnode.
471 * XXX JOE What should the path be here? is "/" really right?
472 * other options?
473 */
474 path = kmem_alloc(2, KM_SLEEP);
475 strcpy(path, ".");
476 mutex_enter(&sffs_lock);
477 sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL, NULL, 0);
478 sffs->sf_rootnode = sfnode_get_vnode(sfnode);
479 sffs->sf_rootnode->v_flag |= VROOT;
480 sffs->sf_rootnode->v_vfsp = vfsp;
481 mutex_exit(&sffs_lock);
482
483 LogFlowFunc(("sffs_mount() success sffs=0x%p\n", sffs));
484#ifdef DEBUG_ramshankar
485 sffs_print(sffs);
486#endif
487 return (error);
488}
489
490static int
491sffs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
492{
493 sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data;
494 int error;
495
496 /*
497 * generic security check
498 */
499 LogFlowFunc(("sffs_unmount() of sffs=0x%p\n", sffs));
500 if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0)
501 return (error);
502
503 /*
504 * forced unmount is not supported by this file system
505 * and thus, ENOTSUP, is being returned.
506 */
507 if (flag & MS_FORCE) {
508 LogFlowFunc(("sffs_unmount(MS_FORCE) returns ENOSUP\n"));
509 return (ENOTSUP);
510 }
511
512 /*
513 * Mark the file system unmounted.
514 */
515 vfsp->vfs_flag |= VFS_UNMOUNTED;
516
517 /*
518 * Make sure nothing is still in use.
519 */
520 if (sffs_purge(sffs) != 0) {
521 vfsp->vfs_flag &= ~VFS_UNMOUNTED;
522 LogFlowFunc(("sffs_unmount() returns EBUSY\n"));
523 return (EBUSY);
524 }
525
526 /*
527 * Invoke Hypervisor unmount interface before proceeding
528 */
529 error = sfprov_unmount(sffs->sf_handle);
530 if (error != 0) {
531 /* TBD anything here? */
532 }
533
534 kmem_free(sffs->sf_share_name, strlen(sffs->sf_share_name) + 1);
535 kmem_free(sffs->sf_mntpath, strlen(sffs->sf_mntpath) + 1);
536 kmem_free(sffs, sizeof(*sffs));
537 LogFlowFunc(("sffs_unmount() done\n"));
538 return (0);
539}
540
541/*
542 * return the vnode for the root of the mounted file system
543 */
544static int
545sffs_root(vfs_t *vfsp, vnode_t **vpp)
546{
547 sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data;
548 vnode_t *vp = sffs->sf_rootnode;
549
550 VN_HOLD(vp);
551 *vpp = vp;
552 return (0);
553}
554
555/*
556 * get some stats.. fake up the rest
557 */
558static int
559sffs_statvfs(vfs_t *vfsp, statvfs64_t *sbp)
560{
561 sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data;
562 sffs_fsinfo_t fsinfo;
563 dev32_t d32;
564 int error;
565
566 bzero(sbp, sizeof(*sbp));
567 error = sfprov_get_fsinfo(sffs->sf_handle, &fsinfo);
568 if (error != 0)
569 return (error);
570
571 sbp->f_bsize = fsinfo.blksize;
572 sbp->f_frsize = fsinfo.blksize;
573
574 sbp->f_bfree = fsinfo.blksavail;
575 sbp->f_bavail = fsinfo.blksavail;
576 sbp->f_files = fsinfo.blksavail / 4; /* some kind of reasonable value */
577 sbp->f_ffree = fsinfo.blksavail / 4;
578 sbp->f_favail = fsinfo.blksavail / 4;
579
580 sbp->f_blocks = fsinfo.blksused + sbp->f_bavail;
581
582 (void) cmpldev(&d32, vfsp->vfs_dev);
583 sbp->f_fsid = d32;
584 strcpy(&sbp->f_basetype[0], "sffs");
585 sbp->f_flag |= ST_NOSUID;
586
587 if (fsinfo.readonly)
588 sbp->f_flag |= ST_RDONLY;
589
590 sbp->f_namemax = fsinfo.maxnamesize;
591 return (0);
592}
593
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette