Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/fd/fdops.c
+++ new/usr/src/uts/common/fs/fd/fdops.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 26 /* All rights reserved. */
27 27
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/param.h>
31 31 #include <sys/cmn_err.h>
32 32 #include <sys/debug.h>
33 33 #include <sys/dirent.h>
34 34 #include <sys/errno.h>
35 35 #include <sys/file.h>
36 36 #include <sys/inline.h>
37 37 #include <sys/kmem.h>
38 38 #include <sys/pathname.h>
39 39 #include <sys/resource.h>
40 40 #include <sys/statvfs.h>
41 41 #include <sys/mount.h>
42 42 #include <sys/sysmacros.h>
43 43 #include <sys/systm.h>
44 44 #include <sys/uio.h>
45 45 #include <sys/vfs.h>
46 46 #include <sys/vfs_opreg.h>
47 47 #include <sys/vnode.h>
48 48 #include <sys/cred.h>
49 49 #include <sys/mntent.h>
50 50 #include <sys/mount.h>
51 51 #include <sys/user.h>
52 52 #include <sys/t_lock.h>
53 53 #include <sys/modctl.h>
54 54 #include <sys/policy.h>
55 55 #include <fs/fs_subr.h>
56 56 #include <sys/atomic.h>
57 57 #include <sys/mkdev.h>
58 58
59 59 #define round(r) (((r)+sizeof (int)-1)&(~(sizeof (int)-1)))
60 60 #define fdtoi(n) ((n)+100)
61 61
62 62 #define FDDIRSIZE 14
63 63 struct fddirect {
64 64 short d_ino;
65 65 char d_name[FDDIRSIZE];
66 66 };
67 67
68 68 #define FDROOTINO 2
69 69 #define FDSDSIZE sizeof (struct fddirect)
70 70 #define FDNSIZE 10
71 71
72 72 static int fdfstype = 0;
73 73 static major_t fdfsmaj;
74 74 static minor_t fdfsmin;
75 75 static major_t fdrmaj;
76 76 static kmutex_t fd_minor_lock;
77 77
78 78 static int fdget(vnode_t *, char *, vnode_t **);
79 79
80 80 /* ARGSUSED */
81 81 static int
82 82 fdopen(vnode_t **vpp, int mode, cred_t *cr, caller_context_t *ct)
83 83 {
84 84 if ((*vpp)->v_type != VDIR) {
85 85 mutex_enter(&(*vpp)->v_lock);
86 86 (*vpp)->v_flag |= VDUP;
87 87 mutex_exit(&(*vpp)->v_lock);
88 88 }
89 89 return (0);
90 90 }
91 91
92 92 /* ARGSUSED */
93 93 static int
94 94 fdclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
95 95 caller_context_t *ct)
96 96 {
97 97 return (0);
98 98 }
99 99
100 100 /* ARGSUSED */
101 101 static int
102 102 fdread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
103 103 {
104 104 static struct fddirect dotbuf[] = {
105 105 { FDROOTINO, "." },
106 106 { FDROOTINO, ".." }
107 107 };
108 108 struct fddirect dirbuf;
109 109 int i, n;
110 110 int minfd, maxfd, modoff, error = 0;
111 111 int nentries;
112 112 rctl_qty_t fdno_ctl;
113 113 int endoff;
114 114
115 115 if (vp->v_type != VDIR)
116 116 return (ENOSYS);
117 117
118 118 mutex_enter(&curproc->p_lock);
119 119 fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
120 120 curproc->p_rctls, curproc);
121 121 nentries = MIN(P_FINFO(curproc)->fi_nfiles, (int)fdno_ctl);
122 122 mutex_exit(&curproc->p_lock);
123 123
124 124 endoff = (nentries + 2) * FDSDSIZE;
125 125
126 126 /*
127 127 * Fake up ".", "..", and the /dev/fd directory entries.
128 128 */
129 129 if (uiop->uio_loffset < (offset_t)0 ||
130 130 uiop->uio_loffset >= (offset_t)endoff ||
131 131 uiop->uio_resid <= 0)
132 132 return (0);
133 133 ASSERT(uiop->uio_loffset <= MAXOFF_T);
134 134 if (uiop->uio_offset < 2*FDSDSIZE) {
135 135 error = uiomove((caddr_t)dotbuf + uiop->uio_offset,
136 136 MIN(uiop->uio_resid, 2*FDSDSIZE - uiop->uio_offset),
137 137 UIO_READ, uiop);
138 138 if (uiop->uio_resid <= 0 || error)
139 139 return (error);
140 140 }
141 141 minfd = (uiop->uio_offset - 2*FDSDSIZE)/FDSDSIZE;
142 142 maxfd = (uiop->uio_offset + uiop->uio_resid - 1)/FDSDSIZE;
143 143 modoff = uiop->uio_offset % FDSDSIZE;
144 144
145 145 for (i = 0; i < FDDIRSIZE; i++)
146 146 dirbuf.d_name[i] = '\0';
147 147 for (i = minfd; i < MIN(maxfd, nentries); i++) {
148 148 n = i;
149 149 dirbuf.d_ino = fdtoi(n);
150 150 numtos((ulong_t)n, dirbuf.d_name);
151 151 error = uiomove((caddr_t)&dirbuf + modoff,
152 152 MIN(uiop->uio_resid, FDSDSIZE - modoff),
153 153 UIO_READ, uiop);
154 154 if (uiop->uio_resid <= 0 || error)
155 155 return (error);
156 156 modoff = 0;
157 157 }
158 158
159 159 return (error);
160 160 }
161 161
162 162 /* ARGSUSED */
163 163 static int
164 164 fdgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
165 165 caller_context_t *ct)
166 166 {
167 167 vfs_t *vfsp = vp->v_vfsp;
168 168 timestruc_t now;
169 169
170 170 if (vp->v_type == VDIR) {
171 171 vap->va_nlink = 2;
172 172 vap->va_size = (u_offset_t)
173 173 ((P_FINFO(curproc)->fi_nfiles + 2) * FDSDSIZE);
174 174 vap->va_mode = 0555;
175 175 vap->va_nodeid = (ino64_t)FDROOTINO;
176 176 } else {
177 177 vap->va_nlink = 1;
178 178 vap->va_size = (u_offset_t)0;
179 179 vap->va_mode = 0666;
180 180 vap->va_nodeid = (ino64_t)fdtoi(getminor(vp->v_rdev));
181 181 }
182 182 vap->va_type = vp->v_type;
183 183 vap->va_rdev = vp->v_rdev;
184 184 vap->va_blksize = vfsp->vfs_bsize;
185 185 vap->va_nblocks = (fsblkcnt64_t)0;
186 186 gethrestime(&now);
187 187 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
188 188 vap->va_uid = 0;
189 189 vap->va_gid = 0;
190 190 vap->va_fsid = vfsp->vfs_dev;
191 191 vap->va_seq = 0;
192 192 return (0);
193 193 }
194 194
195 195 /* ARGSUSED */
196 196 static int
197 197 fdaccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
198 198 {
199 199 return (0);
200 200 }
201 201
202 202 /* ARGSUSED */
203 203 static int
204 204 fdlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pnp,
205 205 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
206 206 int *direntflags, pathname_t *realpnp)
207 207 {
208 208 if (comp[0] == 0 || strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
209 209 VN_HOLD(dp);
210 210 *vpp = dp;
211 211 return (0);
212 212 }
213 213 return (fdget(dp, comp, vpp));
214 214 }
215 215
216 216 /* ARGSUSED */
217 217 static int
218 218 fdcreate(vnode_t *dvp, char *comp, vattr_t *vap, enum vcexcl excl,
219 219 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
220 220 vsecattr_t *vsecp)
221 221 {
222 222 return (fdget(dvp, comp, vpp));
223 223 }
224 224
225 225 /* ARGSUSED */
226 226 static int
227 227 fdreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp, caller_context_t *ct,
228 228 int flags)
229 229 {
230 230 /* bp holds one dirent structure */
231 231 u_offset_t bp[DIRENT64_RECLEN(FDNSIZE) / sizeof (u_offset_t)];
232 232 struct dirent64 *dirent = (struct dirent64 *)bp;
233 233 int reclen, nentries;
234 234 rctl_qty_t fdno_ctl;
235 235 int n;
236 236 int oresid;
237 237 off_t off;
238 238
239 239 if (uiop->uio_offset < 0 || uiop->uio_resid <= 0 ||
240 240 (uiop->uio_offset % FDSDSIZE) != 0)
241 241 return (ENOENT);
242 242
243 243 ASSERT(uiop->uio_loffset <= MAXOFF_T);
244 244 oresid = uiop->uio_resid;
245 245 bzero(bp, sizeof (bp));
246 246
247 247 mutex_enter(&curproc->p_lock);
248 248 fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
249 249 curproc->p_rctls, curproc);
250 250 nentries = MIN(P_FINFO(curproc)->fi_nfiles, (int)fdno_ctl);
251 251 mutex_exit(&curproc->p_lock);
252 252
253 253 while (uiop->uio_resid > 0) {
254 254 if ((off = uiop->uio_offset) == 0) { /* "." */
255 255 dirent->d_ino = (ino64_t)FDROOTINO;
256 256 dirent->d_name[0] = '.';
257 257 dirent->d_name[1] = '\0';
258 258 reclen = DIRENT64_RECLEN(1);
259 259 } else if (off == FDSDSIZE) { /* ".." */
260 260 dirent->d_ino = (ino64_t)FDROOTINO;
261 261 dirent->d_name[0] = '.';
262 262 dirent->d_name[1] = '.';
263 263 dirent->d_name[2] = '\0';
264 264 reclen = DIRENT64_RECLEN(2);
265 265 } else {
266 266 /*
267 267 * Return entries corresponding to the allowable
268 268 * number of file descriptors for this process.
269 269 */
270 270 if ((n = (off-2*FDSDSIZE)/FDSDSIZE) >= nentries)
271 271 break;
272 272 dirent->d_ino = (ino64_t)fdtoi(n);
273 273 numtos((ulong_t)n, dirent->d_name);
274 274 reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
275 275 }
276 276 dirent->d_off = (offset_t)(uiop->uio_offset + FDSDSIZE);
277 277 dirent->d_reclen = (ushort_t)reclen;
278 278
279 279 if (reclen > uiop->uio_resid) {
280 280 /*
281 281 * Error if no entries have been returned yet.
282 282 */
283 283 if (uiop->uio_resid == oresid)
284 284 return (EINVAL);
285 285 break;
286 286 }
287 287 /*
288 288 * uiomove() updates both resid and offset by the same
289 289 * amount. But we want offset to change in increments
290 290 * of FDSDSIZE, which is different from the number of bytes
291 291 * being returned to the user. So we set uio_offset
292 292 * separately, ignoring what uiomove() does.
293 293 */
294 294 if (uiomove((caddr_t)dirent, reclen, UIO_READ, uiop))
295 295 return (EFAULT);
296 296 uiop->uio_offset = off + FDSDSIZE;
297 297 }
298 298 if (eofp)
299 299 *eofp = ((uiop->uio_offset-2*FDSDSIZE)/FDSDSIZE >= nentries);
300 300 return (0);
301 301 }
302 302
303 303 /* ARGSUSED */
304 304 static void
305 305 fdinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
306 306 {
307 307 mutex_enter(&vp->v_lock);
308 308 ASSERT(vp->v_count >= 1);
309 309 if (--vp->v_count != 0) {
310 310 mutex_exit(&vp->v_lock);
↓ open down ↓ |
310 lines elided |
↑ open up ↑ |
311 311 return;
312 312 }
313 313 mutex_exit(&vp->v_lock);
314 314 vn_invalid(vp);
315 315 vn_free(vp);
316 316 }
317 317
318 318 static struct vnodeops *fd_vnodeops;
319 319
320 320 static const fs_operation_def_t fd_vnodeops_template[] = {
321 - VOPNAME_OPEN, { .vop_open = fdopen },
322 - VOPNAME_CLOSE, { .vop_close = fdclose },
323 - VOPNAME_READ, { .vop_read = fdread },
324 - VOPNAME_GETATTR, { .vop_getattr = fdgetattr },
325 - VOPNAME_ACCESS, { .vop_access = fdaccess },
326 - VOPNAME_LOOKUP, { .vop_lookup = fdlookup },
327 - VOPNAME_CREATE, { .vop_create = fdcreate },
328 - VOPNAME_READDIR, { .vop_readdir = fdreaddir },
329 - VOPNAME_INACTIVE, { .vop_inactive = fdinactive },
330 - VOPNAME_FRLOCK, { .error = fs_error },
331 - VOPNAME_POLL, { .error = fs_error },
332 - VOPNAME_DISPOSE, { .error = fs_error },
333 - NULL, NULL
321 + { VOPNAME_OPEN, { .vop_open = fdopen } },
322 + { VOPNAME_CLOSE, { .vop_close = fdclose } },
323 + { VOPNAME_READ, { .vop_read = fdread } },
324 + { VOPNAME_GETATTR, { .vop_getattr = fdgetattr } },
325 + { VOPNAME_ACCESS, { .vop_access = fdaccess } },
326 + { VOPNAME_LOOKUP, { .vop_lookup = fdlookup } },
327 + { VOPNAME_CREATE, { .vop_create = fdcreate } },
328 + { VOPNAME_READDIR, { .vop_readdir = fdreaddir } },
329 + { VOPNAME_INACTIVE, { .vop_inactive = fdinactive } },
330 + { VOPNAME_FRLOCK, { .error = fs_error } },
331 + { VOPNAME_POLL, { .error = fs_error } },
332 + { VOPNAME_DISPOSE, { .error = fs_error } },
333 + { NULL, { NULL } }
334 334 };
335 335
336 336 static int
337 337 fdget(struct vnode *dvp, char *comp, struct vnode **vpp)
338 338 {
339 339 int n = 0;
340 340 struct vnode *vp;
341 341
342 342 while (*comp) {
343 343 if (*comp < '0' || *comp > '9')
344 344 return (ENOENT);
345 345 n = 10 * n + *comp++ - '0';
346 346 }
347 347 vp = vn_alloc(KM_SLEEP);
348 348 vp->v_type = VCHR;
349 349 vp->v_vfsp = dvp->v_vfsp;
350 350 vn_setops(vp, fd_vnodeops);
351 351 vp->v_data = NULL;
352 352 vp->v_flag = VNOMAP;
353 353 vp->v_rdev = makedevice(fdrmaj, n);
354 354 vn_exists(vp);
355 355 *vpp = vp;
356 356 return (0);
357 357 }
358 358
359 359 /*
360 360 * fdfs is mounted on /dev/fd, however, there are two interesting
361 361 * possibilities - two threads racing to do the same mount (protected
362 362 * by vfs locking), and two threads mounting fdfs in different places.
363 363 */
364 364 /*ARGSUSED*/
365 365 static int
366 366 fdmount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
367 367 {
368 368 struct vnode *vp;
369 369
370 370 if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
371 371 return (EPERM);
372 372 if (mvp->v_type != VDIR)
373 373 return (ENOTDIR);
374 374
375 375 mutex_enter(&mvp->v_lock);
376 376 if ((uap->flags & MS_OVERLAY) == 0 &&
377 377 (mvp->v_count > 1 || (mvp->v_flag & VROOT))) {
378 378 mutex_exit(&mvp->v_lock);
379 379 return (EBUSY);
380 380 }
381 381 mutex_exit(&mvp->v_lock);
382 382
383 383 /*
384 384 * Having the resource be anything but "fd" doesn't make sense
385 385 */
386 386 vfs_setresource(vfsp, "fd", 0);
387 387
388 388 vp = vn_alloc(KM_SLEEP);
389 389 vp->v_vfsp = vfsp;
390 390 vn_setops(vp, fd_vnodeops);
391 391 vp->v_type = VDIR;
392 392 vp->v_data = NULL;
393 393 vp->v_flag |= VROOT;
394 394 vfsp->vfs_fstype = fdfstype;
395 395 vfsp->vfs_data = (char *)vp;
396 396 mutex_enter(&fd_minor_lock);
397 397 do {
398 398 fdfsmin = (fdfsmin + 1) & L_MAXMIN32;
399 399 vfsp->vfs_dev = makedevice(fdfsmaj, fdfsmin);
400 400 } while (vfs_devismounted(vfsp->vfs_dev));
401 401 mutex_exit(&fd_minor_lock);
402 402 vfs_make_fsid(&vfsp->vfs_fsid, vfsp->vfs_dev, fdfstype);
403 403 vfsp->vfs_bsize = 1024;
404 404 return (0);
405 405 }
406 406
407 407 /* ARGSUSED */
408 408 static int
409 409 fdunmount(vfs_t *vfsp, int flag, cred_t *cr)
410 410 {
411 411 vnode_t *rvp;
412 412
413 413 if (secpolicy_fs_unmount(cr, vfsp) != 0)
414 414 return (EPERM);
415 415
416 416 /*
417 417 * forced unmount is not supported by this file system
418 418 * and thus, ENOTSUP, is being returned.
419 419 */
420 420 if (flag & MS_FORCE)
421 421 return (ENOTSUP);
422 422
423 423 rvp = (vnode_t *)vfsp->vfs_data;
424 424 if (rvp->v_count > 1)
425 425 return (EBUSY);
426 426
427 427 VN_RELE(rvp);
428 428 return (0);
429 429 }
430 430
431 431 /* ARGSUSED */
432 432 static int
433 433 fdroot(vfs_t *vfsp, vnode_t **vpp)
434 434 {
435 435 vnode_t *vp = (vnode_t *)vfsp->vfs_data;
436 436
437 437 VN_HOLD(vp);
438 438 *vpp = vp;
439 439 return (0);
440 440 }
441 441
442 442 /*
443 443 * No locking required because I held the root vnode before calling this
444 444 * function so the vfs won't disappear on me. To be more explicit:
445 445 * fdvrootp->v_count will be greater than 1 so fdunmount will just return.
446 446 */
447 447 static int
448 448 fdstatvfs(struct vfs *vfsp, struct statvfs64 *sp)
449 449 {
450 450 dev32_t d32;
451 451 rctl_qty_t fdno_ctl;
452 452
453 453 mutex_enter(&curproc->p_lock);
454 454 fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
455 455 curproc->p_rctls, curproc);
456 456 mutex_exit(&curproc->p_lock);
457 457
458 458 bzero(sp, sizeof (*sp));
459 459 sp->f_bsize = 1024;
460 460 sp->f_frsize = 1024;
461 461 sp->f_blocks = (fsblkcnt64_t)0;
462 462 sp->f_bfree = (fsblkcnt64_t)0;
463 463 sp->f_bavail = (fsblkcnt64_t)0;
464 464 sp->f_files = (fsfilcnt64_t)
465 465 (MIN(P_FINFO(curproc)->fi_nfiles, fdno_ctl + 2));
466 466 sp->f_ffree = (fsfilcnt64_t)0;
467 467 sp->f_favail = (fsfilcnt64_t)0;
468 468 (void) cmpldev(&d32, vfsp->vfs_dev);
469 469 sp->f_fsid = d32;
470 470 (void) strcpy(sp->f_basetype, vfssw[fdfstype].vsw_name);
471 471 sp->f_flag = vf_to_stf(vfsp->vfs_flag);
↓ open down ↓ |
128 lines elided |
↑ open up ↑ |
472 472 sp->f_namemax = FDNSIZE;
473 473 (void) strcpy(sp->f_fstr, "/dev/fd");
474 474 (void) strcpy(&sp->f_fstr[8], "/dev/fd");
475 475 return (0);
476 476 }
477 477
478 478 int
479 479 fdinit(int fstype, char *name)
480 480 {
481 481 static const fs_operation_def_t fd_vfsops_template[] = {
482 - VFSNAME_MOUNT, { .vfs_mount = fdmount },
483 - VFSNAME_UNMOUNT, { .vfs_unmount = fdunmount },
484 - VFSNAME_ROOT, { .vfs_root = fdroot },
485 - VFSNAME_STATVFS, { .vfs_statvfs = fdstatvfs },
486 - NULL, NULL
482 + { VFSNAME_MOUNT, { .vfs_mount = fdmount } },
483 + { VFSNAME_UNMOUNT, { .vfs_unmount = fdunmount } },
484 + { VFSNAME_ROOT, { .vfs_root = fdroot } },
485 + { VFSNAME_STATVFS, { .vfs_statvfs = fdstatvfs } },
486 + { NULL, { NULL } }
487 487 };
488 488 int error;
489 489
490 490 fdfstype = fstype;
491 491 ASSERT(fdfstype != 0);
492 492
493 493 /*
494 494 * Associate VFS ops vector with this fstype.
495 495 */
496 496 error = vfs_setfsops(fstype, fd_vfsops_template, NULL);
497 497 if (error != 0) {
498 498 cmn_err(CE_WARN, "fdinit: bad vnode ops template");
499 499 return (error);
500 500 }
501 501
502 502 error = vn_make_ops(name, fd_vnodeops_template, &fd_vnodeops);
503 503 if (error != 0) {
504 504 (void) vfs_freevfsops_by_type(fstype);
505 505 cmn_err(CE_WARN, "fdinit: bad vnode ops template");
506 506 return (error);
507 507 }
508 508
509 509 /*
510 510 * Assign unique "device" numbers (reported by stat(2)).
511 511 */
512 512 fdfsmaj = getudev();
513 513 fdrmaj = getudev();
514 514 if (fdfsmaj == (major_t)-1 || fdrmaj == (major_t)-1) {
515 515 cmn_err(CE_WARN, "fdinit: can't get unique device numbers");
516 516 if (fdfsmaj == (major_t)-1)
517 517 fdfsmaj = 0;
518 518 if (fdrmaj == (major_t)-1)
519 519 fdrmaj = 0;
520 520 }
521 521 mutex_init(&fd_minor_lock, NULL, MUTEX_DEFAULT, NULL);
522 522 return (0);
523 523 }
524 524
525 525 /*
526 526 * FDFS Mount options table
527 527 */
528 528 static char *rw_cancel[] = { MNTOPT_RO, NULL };
529 529
530 530 static mntopt_t mntopts[] = {
531 531 /*
532 532 * option name cancel option default arg flags
533 533 */
534 534 { MNTOPT_RW, rw_cancel, NULL, MO_DEFAULT,
535 535 (void *)MNTOPT_NOINTR },
536 536 { MNTOPT_IGNORE, NULL, NULL, 0,
537 537 (void *)0 },
538 538 };
539 539
540 540 static mntopts_t fdfs_mntopts = {
541 541 sizeof (mntopts) / sizeof (mntopt_t),
542 542 mntopts
543 543 };
544 544
545 545 static vfsdef_t vfw = {
546 546 VFSDEF_VERSION,
547 547 "fd",
548 548 fdinit,
549 549 VSW_HASPROTO | VSW_ZMOUNT,
550 550 &fdfs_mntopts
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
551 551 };
552 552
553 553 static struct modlfs modlfs = {
554 554 &mod_fsops,
555 555 "filesystem for fd",
556 556 &vfw
557 557 };
558 558
559 559 static struct modlinkage modlinkage = {
560 560 MODREV_1,
561 - &modlfs,
562 - NULL
561 + { &modlfs, NULL }
563 562 };
564 563
565 564 int
566 565 _init(void)
567 566 {
568 567 return (mod_install(&modlinkage));
569 568 }
570 569
571 570 int
572 571 _info(struct modinfo *modinfop)
573 572 {
574 573 return (mod_info(&modlinkage, modinfop));
575 574 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX