67 #include <sys/modctl.h>
68 #include <sys/ddi.h>
69 #include <sys/pathname.h>
70 #include <sys/bootconf.h>
71 #include <sys/dumphdr.h>
72 #include <sys/dc_ki.h>
73 #include <sys/poll.h>
74 #include <sys/sunddi.h>
75 #include <sys/sysmacros.h>
76 #include <sys/zone.h>
77 #include <sys/policy.h>
78 #include <sys/ctfs.h>
79 #include <sys/objfs.h>
80 #include <sys/console.h>
81 #include <sys/reboot.h>
82 #include <sys/attr.h>
83 #include <sys/zio.h>
84 #include <sys/spa.h>
85 #include <sys/lofi.h>
86 #include <sys/bootprops.h>
87
88 #include <vm/page.h>
89
90 #include <fs/fs_subr.h>
91 /* Private interfaces to create vopstats-related data structures */
92 extern void initialize_vopstats(vopstats_t *);
93 extern vopstats_t *get_fstype_vopstats(struct vfs *, struct vfssw *);
94 extern vsk_anchor_t *get_vskstat_anchor(struct vfs *);
95
96 static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int);
97 static void vfs_setmntopt_nolock(mntopts_t *, const char *,
98 const char *, int, int);
99 static int vfs_optionisset_nolock(const mntopts_t *, const char *, char **);
100 static void vfs_freemnttab(struct vfs *);
101 static void vfs_freeopt(mntopt_t *);
102 static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *);
103 static void vfs_swapopttbl(mntopts_t *, mntopts_t *);
104 static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int);
105 static void vfs_createopttbl_extend(mntopts_t *, const char *,
106 const mntopts_t *);
199 { MNTOPT_NONBMAND, nonbmand_cancel, NULL, 0,
200 (void *)0 },
201 { MNTOPT_EXEC, exec_cancel, NULL, 0,
202 (void *)0 },
203 { MNTOPT_NOEXEC, noexec_cancel, NULL, 0,
204 (void *)0 },
205 };
206
207 const mntopts_t vfs_mntopts = {
208 sizeof (mntopts) / sizeof (mntopt_t),
209 (mntopt_t *)&mntopts[0]
210 };
211
212 /*
213 * File system operation dispatch functions.
214 */
215
216 int
217 fsop_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
218 {
219 return (*(vfsp)->vfs_op->vfs_mount)(vfsp, mvp, uap, cr);
220 }
221
222 int
223 fsop_unmount(vfs_t *vfsp, int flag, cred_t *cr)
224 {
225 return (*(vfsp)->vfs_op->vfs_unmount)(vfsp, flag, cr);
226 }
227
228 int
229 fsop_root(vfs_t *vfsp, vnode_t **vpp)
230 {
231 refstr_t *mntpt;
232 int ret = (*(vfsp)->vfs_op->vfs_root)(vfsp, vpp);
233 /*
234 * Make sure this root has a path. With lofs, it is possible to have
235 * a NULL mountpoint.
236 */
237 if (ret == 0 && vfsp->vfs_mntpt != NULL && (*vpp)->v_path == NULL) {
238 mntpt = vfs_getmntpoint(vfsp);
239 vn_setpath_str(*vpp, refstr_value(mntpt),
240 strlen(refstr_value(mntpt)));
241 refstr_rele(mntpt);
242 }
243
244 return (ret);
245 }
246
247 int
248 fsop_statfs(vfs_t *vfsp, statvfs64_t *sp)
249 {
250 return (*(vfsp)->vfs_op->vfs_statvfs)(vfsp, sp);
251 }
252
253 int
254 fsop_sync(vfs_t *vfsp, short flag, cred_t *cr)
255 {
256 return (*(vfsp)->vfs_op->vfs_sync)(vfsp, flag, cr);
257 }
258
259 int
260 fsop_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
261 {
262 /*
263 * In order to handle system attribute fids in a manner
264 * transparent to the underlying fs, we embed the fid for
265 * the sysattr parent object in the sysattr fid and tack on
266 * some extra bytes that only the sysattr layer knows about.
267 *
268 * This guarantees that sysattr fids are larger than other fids
269 * for this vfs. If the vfs supports the sysattr view interface
270 * (as indicated by VFSFT_SYSATTR_VIEWS), we cannot have a size
271 * collision with XATTR_FIDSZ.
272 */
273 if (vfs_has_feature(vfsp, VFSFT_SYSATTR_VIEWS) &&
274 fidp->fid_len == XATTR_FIDSZ)
275 return (xattr_dir_vget(vfsp, vpp, fidp));
276
277 return (*(vfsp)->vfs_op->vfs_vget)(vfsp, vpp, fidp);
278 }
279
280 int
281 fsop_mountroot(vfs_t *vfsp, enum whymountroot reason)
282 {
283 return (*(vfsp)->vfs_op->vfs_mountroot)(vfsp, reason);
284 }
285
286 void
287 fsop_freefs(vfs_t *vfsp)
288 {
289 (*(vfsp)->vfs_op->vfs_freevfs)(vfsp);
290 }
291
292 int
293 fsop_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
294 {
295 return ((*(vfsp)->vfs_op->vfs_vnstate)(vfsp, vp, nstate));
296 }
297
511 return (vfs_getops(vfsp)->vfs_sync != fs_sync);
512 }
513
514 /*
515 * Initialize a vfs structure.
516 */
517 void
518 vfs_init(vfs_t *vfsp, vfsops_t *op, void *data)
519 {
520 /* Other initialization has been moved to vfs_alloc() */
521 vfsp->vfs_count = 0;
522 vfsp->vfs_next = vfsp;
523 vfsp->vfs_prev = vfsp;
524 vfsp->vfs_zone_next = vfsp;
525 vfsp->vfs_zone_prev = vfsp;
526 vfsp->vfs_lofi_minor = 0;
527 sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL);
528 vfsimpl_setup(vfsp);
529 vfsp->vfs_data = (data);
530 vfs_setops((vfsp), (op));
531 }
532
533 /*
534 * Allocate and initialize the vfs implementation private data
535 * structure, vfs_impl_t.
536 */
537 void
538 vfsimpl_setup(vfs_t *vfsp)
539 {
540 int i;
541
542 if (vfsp->vfs_implp != NULL) {
543 return;
544 }
545
546 vfsp->vfs_implp = kmem_alloc(sizeof (vfs_impl_t), KM_SLEEP);
547 /* Note that these are #define'd in vfs.h */
548 vfsp->vfs_vskap = NULL;
549 vfsp->vfs_fstypevsp = NULL;
550
1768 if ((error == 0) && (copyout_error == 0)) {
1769 if (!remount) {
1770 /*
1771 * Don't call get_vskstat_anchor() while holding
1772 * locks since it allocates memory and calls
1773 * VFS_STATVFS(). For NFS, the latter can generate
1774 * an over-the-wire call.
1775 */
1776 vskap = get_vskstat_anchor(vfsp);
1777 /* Only take the lock if we have something to do */
1778 if (vskap != NULL) {
1779 vfs_lock_wait(vfsp);
1780 if (vfsp->vfs_flag & VFS_STATS) {
1781 vfsp->vfs_vskap = vskap;
1782 }
1783 vfs_unlock(vfsp);
1784 }
1785 }
1786 /* Return vfsp to caller. */
1787 *vfspp = vfsp;
1788 }
1789 errout:
1790 vfs_freeopttbl(&mnt_mntopts);
1791 if (resource != NULL)
1792 kmem_free(resource, strlen(resource) + 1);
1793 if (mountpt != NULL)
1794 kmem_free(mountpt, strlen(mountpt) + 1);
1795 /*
1796 * It is possible we errored prior to adding to mount in progress
1797 * table. Must free vnode we acquired with successful lookupname.
1798 */
1799 if (addmip)
1800 VN_RELE(bvp);
1801 if (delmip)
1802 vfs_delmip(vfsp);
1803 ASSERT(vswp != NULL);
1804 vfs_unrefvfssw(vswp);
1805 if (inargs != opts)
1806 kmem_free(inargs, MAX_MNTOPT_STR);
1807 if (copyout_error) {
4302 /*
4303 * One would be tempted to assert that "vfsp->vfs_count == 0".
4304 * The problem is that this gets called out of domount() with
4305 * a partially initialized vfs and a vfs_count of 1. This is
4306 * also called from vfs_rele() with a vfs_count of 0. We can't
4307 * call VFS_RELE() from domount() if VFS_MOUNT() hasn't successfully
4308 * returned. This is because VFS_MOUNT() fully initializes the
4309 * vfs structure and its associated data. VFS_RELE() will call
4310 * VFS_FREEVFS() which may panic the system if the data structures
4311 * aren't fully initialized from a successful VFS_MOUNT()).
4312 */
4313
4314 /* If FEM was in use, make sure everything gets cleaned up */
4315 if (vfsp->vfs_femhead) {
4316 ASSERT(vfsp->vfs_femhead->femh_list == NULL);
4317 mutex_destroy(&vfsp->vfs_femhead->femh_lock);
4318 kmem_free(vfsp->vfs_femhead, sizeof (*(vfsp->vfs_femhead)));
4319 vfsp->vfs_femhead = NULL;
4320 }
4321
4322 if (vfsp->vfs_implp)
4323 vfsimpl_teardown(vfsp);
4324 sema_destroy(&vfsp->vfs_reflock);
4325 kmem_cache_free(vfs_cache, vfsp);
4326 }
4327
4328 /*
4329 * Increments the vfs reference count by one atomically.
4330 */
4331 void
4332 vfs_hold(vfs_t *vfsp)
4333 {
4334 atomic_add_32(&vfsp->vfs_count, 1);
4335 ASSERT(vfsp->vfs_count != 0);
4336 }
4337
4338 /*
4339 * Decrements the vfs reference count by one atomically. When
4340 * vfs reference count becomes zero, it calls the file system
4341 * specific vfs_freevfs() to free up the resources.
4342 */
4343 void
4344 vfs_rele(vfs_t *vfsp)
4345 {
4346 ASSERT(vfsp->vfs_count != 0);
4347 if (atomic_add_32_nv(&vfsp->vfs_count, -1) == 0) {
4348 VFS_FREEVFS(vfsp);
4349 lofi_remove(vfsp);
4350 if (vfsp->vfs_zone)
4351 zone_rele_ref(&vfsp->vfs_implp->vi_zone_ref,
4352 ZONE_REF_VFS);
4353 vfs_freemnttab(vfsp);
4354 vfs_free(vfsp);
4355 }
4356 }
4357
4358 /*
4359 * Generic operations vector support.
4360 *
4361 * This is used to build operations vectors for both the vfs and vnode.
4362 * It's normally called only when a file system is loaded.
4363 *
4364 * There are many possible algorithms for this, including the following:
4365 *
4366 * (1) scan the list of known operations; for each, see if the file system
4367 * includes an entry for it, and fill it in as appropriate.
|
67 #include <sys/modctl.h>
68 #include <sys/ddi.h>
69 #include <sys/pathname.h>
70 #include <sys/bootconf.h>
71 #include <sys/dumphdr.h>
72 #include <sys/dc_ki.h>
73 #include <sys/poll.h>
74 #include <sys/sunddi.h>
75 #include <sys/sysmacros.h>
76 #include <sys/zone.h>
77 #include <sys/policy.h>
78 #include <sys/ctfs.h>
79 #include <sys/objfs.h>
80 #include <sys/console.h>
81 #include <sys/reboot.h>
82 #include <sys/attr.h>
83 #include <sys/zio.h>
84 #include <sys/spa.h>
85 #include <sys/lofi.h>
86 #include <sys/bootprops.h>
87 #include <sys/fsh.h>
88 #include <sys/fsh_impl.h>
89
90 #include <vm/page.h>
91
92 #include <fs/fs_subr.h>
93 /* Private interfaces to create vopstats-related data structures */
94 extern void initialize_vopstats(vopstats_t *);
95 extern vopstats_t *get_fstype_vopstats(struct vfs *, struct vfssw *);
96 extern vsk_anchor_t *get_vskstat_anchor(struct vfs *);
97
98 static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int);
99 static void vfs_setmntopt_nolock(mntopts_t *, const char *,
100 const char *, int, int);
101 static int vfs_optionisset_nolock(const mntopts_t *, const char *, char **);
102 static void vfs_freemnttab(struct vfs *);
103 static void vfs_freeopt(mntopt_t *);
104 static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *);
105 static void vfs_swapopttbl(mntopts_t *, mntopts_t *);
106 static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int);
107 static void vfs_createopttbl_extend(mntopts_t *, const char *,
108 const mntopts_t *);
201 { MNTOPT_NONBMAND, nonbmand_cancel, NULL, 0,
202 (void *)0 },
203 { MNTOPT_EXEC, exec_cancel, NULL, 0,
204 (void *)0 },
205 { MNTOPT_NOEXEC, noexec_cancel, NULL, 0,
206 (void *)0 },
207 };
208
209 const mntopts_t vfs_mntopts = {
210 sizeof (mntopts) / sizeof (mntopt_t),
211 (mntopt_t *)&mntopts[0]
212 };
213
214 /*
215 * File system operation dispatch functions.
216 */
217
218 int
219 fsop_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
220 {
221 return (fsh_mount(vfsp, mvp, uap, cr));
222 }
223
224 int
225 fsop_unmount(vfs_t *vfsp, int flag, cred_t *cr)
226 {
227 return (fsh_unmount(vfsp, flag, cr));
228 }
229
230 int
231 fsop_root(vfs_t *vfsp, vnode_t **vpp)
232 {
233 refstr_t *mntpt;
234 int ret = fsh_root(vfsp, vpp);
235 /*
236 * Make sure this root has a path. With lofs, it is possible to have
237 * a NULL mountpoint.
238 */
239 if (ret == 0 && vfsp->vfs_mntpt != NULL && (*vpp)->v_path == NULL) {
240 mntpt = vfs_getmntpoint(vfsp);
241 vn_setpath_str(*vpp, refstr_value(mntpt),
242 strlen(refstr_value(mntpt)));
243 refstr_rele(mntpt);
244 }
245
246 return (ret);
247 }
248
249 int
250 fsop_statfs(vfs_t *vfsp, statvfs64_t *sp)
251 {
252 return (fsh_statfs(vfsp, sp));
253 }
254
255 int
256 fsop_sync(vfs_t *vfsp, short flag, cred_t *cr)
257 {
258 return (*(vfsp)->vfs_op->vfs_sync)(vfsp, flag, cr);
259 }
260
261 int
262 fsop_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
263 {
264 /*
265 * In order to handle system attribute fids in a manner
266 * transparent to the underlying fs, we embed the fid for
267 * the sysattr parent object in the sysattr fid and tack on
268 * some extra bytes that only the sysattr layer knows about.
269 *
270 * This guarantees that sysattr fids are larger than other fids
271 * for this vfs. If the vfs supports the sysattr view interface
272 * (as indicated by VFSFT_SYSATTR_VIEWS), we cannot have a size
273 * collision with XATTR_FIDSZ.
274 */
275 if (vfs_has_feature(vfsp, VFSFT_SYSATTR_VIEWS) &&
276 fidp->fid_len == XATTR_FIDSZ)
277 return (xattr_dir_vget(vfsp, vpp, fidp));
278
279 return (fsh_vget(vfsp, vpp, fidp));
280 }
281
282 int
283 fsop_mountroot(vfs_t *vfsp, enum whymountroot reason)
284 {
285 return (*(vfsp)->vfs_op->vfs_mountroot)(vfsp, reason);
286 }
287
288 void
289 fsop_freefs(vfs_t *vfsp)
290 {
291 (*(vfsp)->vfs_op->vfs_freevfs)(vfsp);
292 }
293
294 int
295 fsop_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
296 {
297 return ((*(vfsp)->vfs_op->vfs_vnstate)(vfsp, vp, nstate));
298 }
299
513 return (vfs_getops(vfsp)->vfs_sync != fs_sync);
514 }
515
516 /*
517 * Initialize a vfs structure.
518 */
519 void
520 vfs_init(vfs_t *vfsp, vfsops_t *op, void *data)
521 {
522 /* Other initialization has been moved to vfs_alloc() */
523 vfsp->vfs_count = 0;
524 vfsp->vfs_next = vfsp;
525 vfsp->vfs_prev = vfsp;
526 vfsp->vfs_zone_next = vfsp;
527 vfsp->vfs_zone_prev = vfsp;
528 vfsp->vfs_lofi_minor = 0;
529 sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL);
530 vfsimpl_setup(vfsp);
531 vfsp->vfs_data = (data);
532 vfs_setops((vfsp), (op));
533 vfsp->vfs_fshrecord = fsh_fsrec_create();
534 }
535
536 /*
537 * Allocate and initialize the vfs implementation private data
538 * structure, vfs_impl_t.
539 */
540 void
541 vfsimpl_setup(vfs_t *vfsp)
542 {
543 int i;
544
545 if (vfsp->vfs_implp != NULL) {
546 return;
547 }
548
549 vfsp->vfs_implp = kmem_alloc(sizeof (vfs_impl_t), KM_SLEEP);
550 /* Note that these are #define'd in vfs.h */
551 vfsp->vfs_vskap = NULL;
552 vfsp->vfs_fstypevsp = NULL;
553
1771 if ((error == 0) && (copyout_error == 0)) {
1772 if (!remount) {
1773 /*
1774 * Don't call get_vskstat_anchor() while holding
1775 * locks since it allocates memory and calls
1776 * VFS_STATVFS(). For NFS, the latter can generate
1777 * an over-the-wire call.
1778 */
1779 vskap = get_vskstat_anchor(vfsp);
1780 /* Only take the lock if we have something to do */
1781 if (vskap != NULL) {
1782 vfs_lock_wait(vfsp);
1783 if (vfsp->vfs_flag & VFS_STATS) {
1784 vfsp->vfs_vskap = vskap;
1785 }
1786 vfs_unlock(vfsp);
1787 }
1788 }
1789 /* Return vfsp to caller. */
1790 *vfspp = vfsp;
1791 fsh_exec_create_callbacks(vfsp);
1792 }
1793 errout:
1794 vfs_freeopttbl(&mnt_mntopts);
1795 if (resource != NULL)
1796 kmem_free(resource, strlen(resource) + 1);
1797 if (mountpt != NULL)
1798 kmem_free(mountpt, strlen(mountpt) + 1);
1799 /*
1800 * It is possible we errored prior to adding to mount in progress
1801 * table. Must free vnode we acquired with successful lookupname.
1802 */
1803 if (addmip)
1804 VN_RELE(bvp);
1805 if (delmip)
1806 vfs_delmip(vfsp);
1807 ASSERT(vswp != NULL);
1808 vfs_unrefvfssw(vswp);
1809 if (inargs != opts)
1810 kmem_free(inargs, MAX_MNTOPT_STR);
1811 if (copyout_error) {
4306 /*
4307 * One would be tempted to assert that "vfsp->vfs_count == 0".
4308 * The problem is that this gets called out of domount() with
4309 * a partially initialized vfs and a vfs_count of 1. This is
4310 * also called from vfs_rele() with a vfs_count of 0. We can't
4311 * call VFS_RELE() from domount() if VFS_MOUNT() hasn't successfully
4312 * returned. This is because VFS_MOUNT() fully initializes the
4313 * vfs structure and its associated data. VFS_RELE() will call
4314 * VFS_FREEVFS() which may panic the system if the data structures
4315 * aren't fully initialized from a successful VFS_MOUNT()).
4316 */
4317
4318 /* If FEM was in use, make sure everything gets cleaned up */
4319 if (vfsp->vfs_femhead) {
4320 ASSERT(vfsp->vfs_femhead->femh_list == NULL);
4321 mutex_destroy(&vfsp->vfs_femhead->femh_lock);
4322 kmem_free(vfsp->vfs_femhead, sizeof (*(vfsp->vfs_femhead)));
4323 vfsp->vfs_femhead = NULL;
4324 }
4325
4326 /* FSH cleanup */
4327 fsh_fsrec_destroy(vfsp->vfs_fshrecord);
4328 vfsp->vfs_fshrecord = NULL;
4329
4330 if (vfsp->vfs_implp)
4331 vfsimpl_teardown(vfsp);
4332 sema_destroy(&vfsp->vfs_reflock);
4333 kmem_cache_free(vfs_cache, vfsp);
4334 }
4335
4336 /*
4337 * Increments the vfs reference count by one atomically.
4338 */
4339 void
4340 vfs_hold(vfs_t *vfsp)
4341 {
4342 atomic_add_32(&vfsp->vfs_count, 1);
4343 ASSERT(vfsp->vfs_count != 0);
4344 }
4345
4346 /*
4347 * Decrements the vfs reference count by one atomically. When
4348 * vfs reference count becomes zero, it calls the file system
4349 * specific vfs_freevfs() to free up the resources.
4350 */
4351 void
4352 vfs_rele(vfs_t *vfsp)
4353 {
4354 ASSERT(vfsp->vfs_count != 0);
4355 if (atomic_add_32_nv(&vfsp->vfs_count, -1) == 0) {
4356 fsh_exec_destroy_callbacks(vfsp);
4357 VFS_FREEVFS(vfsp);
4358 lofi_remove(vfsp);
4359 if (vfsp->vfs_zone)
4360 zone_rele_ref(&vfsp->vfs_implp->vi_zone_ref,
4361 ZONE_REF_VFS);
4362 vfs_freemnttab(vfsp);
4363 vfs_free(vfsp);
4364 }
4365 }
4366
4367 /*
4368 * Generic operations vector support.
4369 *
4370 * This is used to build operations vectors for both the vfs and vnode.
4371 * It's normally called only when a file system is loaded.
4372 *
4373 * There are many possible algorithms for this, including the following:
4374 *
4375 * (1) scan the list of known operations; for each, see if the file system
4376 * includes an entry for it, and fill it in as appropriate.
|