1 | /* $NetBSD: coda_vfsops.c,v 1.84 2014/12/13 15:59:30 hannken Exp $ */ |
2 | |
3 | /* |
4 | * |
5 | * Coda: an Experimental Distributed File System |
6 | * Release 3.1 |
7 | * |
8 | * Copyright (c) 1987-1998 Carnegie Mellon University |
9 | * All Rights Reserved |
10 | * |
11 | * Permission to use, copy, modify and distribute this software and its |
12 | * documentation is hereby granted, provided that both the copyright |
13 | * notice and this permission notice appear in all copies of the |
14 | * software, derivative works or modified versions, and any portions |
15 | * thereof, and that both notices appear in supporting documentation, and |
16 | * that credit is given to Carnegie Mellon University in all documents |
17 | * and publicity pertaining to direct or indirect use of this code or its |
18 | * derivatives. |
19 | * |
20 | * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, |
21 | * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS |
22 | * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON |
23 | * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER |
24 | * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF |
25 | * ANY DERIVATIVE WORK. |
26 | * |
27 | * Carnegie Mellon encourages users of this software to return any |
28 | * improvements or extensions that they make, and to grant Carnegie |
29 | * Mellon the rights to redistribute these changes without encumbrance. |
30 | * |
31 | * @(#) cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $ |
32 | */ |
33 | |
34 | /* |
35 | * Mach Operating System |
36 | * Copyright (c) 1989 Carnegie-Mellon University |
37 | * All rights reserved. The CMU software License Agreement specifies |
38 | * the terms and conditions for use and redistribution. |
39 | */ |
40 | |
41 | /* |
42 | * This code was written for the Coda file system at Carnegie Mellon |
43 | * University. Contributers include David Steere, James Kistler, and |
44 | * M. Satyanarayanan. |
45 | */ |
46 | |
47 | #include <sys/cdefs.h> |
48 | __KERNEL_RCSID(0, "$NetBSD: coda_vfsops.c,v 1.84 2014/12/13 15:59:30 hannken Exp $" ); |
49 | |
50 | #include <sys/param.h> |
51 | #include <sys/systm.h> |
52 | #include <sys/sysctl.h> |
53 | #include <sys/malloc.h> |
54 | #include <sys/conf.h> |
55 | #include <sys/namei.h> |
56 | #include <sys/dirent.h> |
57 | #include <sys/mount.h> |
58 | #include <sys/proc.h> |
59 | #include <sys/select.h> |
60 | #include <sys/kauth.h> |
61 | #include <sys/module.h> |
62 | |
63 | #include <coda/coda.h> |
64 | #include <coda/cnode.h> |
65 | #include <coda/coda_vfsops.h> |
66 | #include <coda/coda_venus.h> |
67 | #include <coda/coda_subr.h> |
68 | #include <coda/coda_opstats.h> |
69 | /* for VN_RDEV */ |
70 | #include <miscfs/specfs/specdev.h> |
71 | #include <miscfs/genfs/genfs.h> |
72 | |
73 | MODULE(MODULE_CLASS_VFS, coda, "vcoda" ); |
74 | |
75 | #define ENTRY if(coda_vfsop_print_entry) myprintf(("Entered %s\n",__func__)) |
76 | |
77 | extern struct vnode *coda_ctlvp; |
78 | extern struct coda_mntinfo coda_mnttbl[NVCODA]; /* indexed by minor device number */ |
79 | |
80 | /* structure to keep statistics of internally generated/satisfied calls */ |
81 | |
82 | struct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE]; |
83 | |
84 | #define MARK_ENTRY(op) (coda_vfsopstats[op].entries++) |
85 | #define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++) |
86 | #define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++) |
87 | #define MRAK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++) |
88 | |
89 | extern const struct cdevsw vcoda_cdevsw; |
90 | extern const struct vnodeopv_desc coda_vnodeop_opv_desc; |
91 | |
92 | const struct vnodeopv_desc * const coda_vnodeopv_descs[] = { |
93 | &coda_vnodeop_opv_desc, |
94 | NULL, |
95 | }; |
96 | |
97 | struct vfsops coda_vfsops = { |
98 | .vfs_name = MOUNT_CODA, |
99 | .vfs_min_mount_data = 256, |
100 | /* This is the pathname, unlike every other fs */ |
101 | .vfs_mount = coda_mount, |
102 | .vfs_start = coda_start, |
103 | .vfs_unmount = coda_unmount, |
104 | .vfs_root = coda_root, |
105 | .vfs_quotactl = (void *)eopnotsupp, |
106 | .vfs_statvfs = coda_nb_statvfs, |
107 | .vfs_sync = coda_sync, |
108 | .vfs_vget = coda_vget, |
109 | .vfs_loadvnode = coda_loadvnode, |
110 | .vfs_fhtovp = (void *)eopnotsupp, |
111 | .vfs_vptofh = (void *)eopnotsupp, |
112 | .vfs_init = coda_init, |
113 | .vfs_done = coda_done, |
114 | .vfs_mountroot = (void *)eopnotsupp, |
115 | .vfs_snapshot = (void *)eopnotsupp, |
116 | .vfs_extattrctl = vfs_stdextattrctl, |
117 | .vfs_suspendctl = (void *)eopnotsupp, |
118 | .vfs_renamelock_enter = genfs_renamelock_enter, |
119 | .vfs_renamelock_exit = genfs_renamelock_exit, |
120 | .vfs_fsync = (void *)eopnotsupp, |
121 | .vfs_opv_descs = coda_vnodeopv_descs |
122 | }; |
123 | |
124 | static int |
125 | coda_modcmd(modcmd_t cmd, void *arg) |
126 | { |
127 | |
128 | switch (cmd) { |
129 | case MODULE_CMD_INIT: |
130 | return vfs_attach(&coda_vfsops); |
131 | case MODULE_CMD_FINI: |
132 | return vfs_detach(&coda_vfsops); |
133 | default: |
134 | return ENOTTY; |
135 | } |
136 | } |
137 | |
138 | int |
139 | coda_vfsopstats_init(void) |
140 | { |
141 | int i; |
142 | |
143 | for (i=0;i<CODA_VFSOPS_SIZE;i++) { |
144 | coda_vfsopstats[i].opcode = i; |
145 | coda_vfsopstats[i].entries = 0; |
146 | coda_vfsopstats[i].sat_intrn = 0; |
147 | coda_vfsopstats[i].unsat_intrn = 0; |
148 | coda_vfsopstats[i].gen_intrn = 0; |
149 | } |
150 | |
151 | return 0; |
152 | } |
153 | |
154 | /* |
155 | * cfs mount vfsop |
156 | * Set up mount info record and attach it to vfs struct. |
157 | */ |
158 | /*ARGSUSED*/ |
159 | int |
160 | coda_mount(struct mount *vfsp, /* Allocated and initialized by mount(2) */ |
161 | const char *path, /* path covered: ignored by the fs-layer */ |
162 | void *data, /* Need to define a data type for this in netbsd? */ |
163 | size_t *data_len) |
164 | { |
165 | struct lwp *l = curlwp; |
166 | struct vnode *dvp; |
167 | struct cnode *cp; |
168 | dev_t dev; |
169 | struct coda_mntinfo *mi; |
170 | struct vnode *rtvp; |
171 | const struct cdevsw *cdev; |
172 | CodaFid rootfid = INVAL_FID; |
173 | CodaFid ctlfid = CTL_FID; |
174 | int error; |
175 | |
176 | if (data == NULL) |
177 | return EINVAL; |
178 | if (vfsp->mnt_flag & MNT_GETARGS) |
179 | return EINVAL; |
180 | ENTRY; |
181 | |
182 | coda_vfsopstats_init(); |
183 | coda_vnodeopstats_init(); |
184 | |
185 | MARK_ENTRY(CODA_MOUNT_STATS); |
186 | if (CODA_MOUNTED(vfsp)) { |
187 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
188 | return(EBUSY); |
189 | } |
190 | |
191 | /* Validate mount device. Similar to getmdev(). */ |
192 | |
193 | /* |
194 | * XXX: coda passes the mount device as the entire mount args, |
195 | * All other fs pass a structure contining a pointer. |
196 | * In order to get sys_mount() to do the copyin() we've set a |
197 | * fixed default size for the filename buffer. |
198 | */ |
199 | /* Ensure that namei() doesn't run off the filename buffer */ |
200 | ((char *)data)[*data_len - 1] = 0; |
201 | error = namei_simple_kernel((char *)data, NSM_FOLLOW_NOEMULROOT, |
202 | &dvp); |
203 | |
204 | if (error) { |
205 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
206 | return (error); |
207 | } |
208 | if (dvp->v_type != VCHR) { |
209 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
210 | vrele(dvp); |
211 | return(ENXIO); |
212 | } |
213 | dev = dvp->v_rdev; |
214 | vrele(dvp); |
215 | cdev = cdevsw_lookup(dev); |
216 | if (cdev == NULL) { |
217 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
218 | return(ENXIO); |
219 | } |
220 | |
221 | /* |
222 | * See if the device table matches our expectations. |
223 | */ |
224 | if (cdev != &vcoda_cdevsw) |
225 | { |
226 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
227 | return(ENXIO); |
228 | } |
229 | |
230 | if (minor(dev) >= NVCODA) { |
231 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
232 | return(ENXIO); |
233 | } |
234 | |
235 | /* |
236 | * Initialize the mount record and link it to the vfs struct |
237 | */ |
238 | mi = &coda_mnttbl[minor(dev)]; |
239 | |
240 | if (!VC_OPEN(&mi->mi_vcomm)) { |
241 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
242 | return(ENODEV); |
243 | } |
244 | |
245 | /* No initialization (here) of mi_vcomm! */ |
246 | vfsp->mnt_data = mi; |
247 | vfsp->mnt_stat.f_fsidx.__fsid_val[0] = 0; |
248 | vfsp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CODA); |
249 | vfsp->mnt_stat.f_fsid = vfsp->mnt_stat.f_fsidx.__fsid_val[0]; |
250 | vfsp->mnt_stat.f_namemax = CODA_MAXNAMLEN; |
251 | mi->mi_vfsp = vfsp; |
252 | |
253 | /* |
254 | * Make a root vnode to placate the Vnode interface, but don't |
255 | * actually make the CODA_ROOT call to venus until the first call |
256 | * to coda_root in case a server is down while venus is starting. |
257 | */ |
258 | cp = make_coda_node(&rootfid, vfsp, VDIR); |
259 | rtvp = CTOV(cp); |
260 | rtvp->v_vflag |= VV_ROOT; |
261 | |
262 | cp = make_coda_node(&ctlfid, vfsp, VCHR); |
263 | |
264 | coda_ctlvp = CTOV(cp); |
265 | |
266 | /* Add vfs and rootvp to chain of vfs hanging off mntinfo */ |
267 | mi->mi_vfsp = vfsp; |
268 | mi->mi_rootvp = rtvp; |
269 | |
270 | /* set filesystem block size */ |
271 | vfsp->mnt_stat.f_bsize = 8192; /* XXX -JJK */ |
272 | vfsp->mnt_stat.f_frsize = 8192; /* XXX -JJK */ |
273 | |
274 | /* error is currently guaranteed to be zero, but in case some |
275 | code changes... */ |
276 | CODADEBUG(1, |
277 | myprintf(("coda_mount returned %d\n" ,error));); |
278 | if (error) |
279 | MARK_INT_FAIL(CODA_MOUNT_STATS); |
280 | else |
281 | MARK_INT_SAT(CODA_MOUNT_STATS); |
282 | |
283 | return set_statvfs_info("/coda" , UIO_SYSSPACE, "CODA" , UIO_SYSSPACE, |
284 | vfsp->mnt_op->vfs_name, vfsp, l); |
285 | } |
286 | |
287 | int |
288 | coda_start(struct mount *vfsp, int flags) |
289 | { |
290 | ENTRY; |
291 | vftomi(vfsp)->mi_started = 1; |
292 | return (0); |
293 | } |
294 | |
295 | int |
296 | coda_unmount(struct mount *vfsp, int mntflags) |
297 | { |
298 | struct coda_mntinfo *mi = vftomi(vfsp); |
299 | int active, error = 0; |
300 | |
301 | ENTRY; |
302 | MARK_ENTRY(CODA_UMOUNT_STATS); |
303 | if (!CODA_MOUNTED(vfsp)) { |
304 | MARK_INT_FAIL(CODA_UMOUNT_STATS); |
305 | return(EINVAL); |
306 | } |
307 | |
308 | if (mi->mi_vfsp == vfsp) { /* We found the victim */ |
309 | if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp))) |
310 | return (EBUSY); /* Venus is still running */ |
311 | |
312 | #ifdef DEBUG |
313 | printf("coda_unmount: ROOT: vp %p, cp %p\n" , mi->mi_rootvp, VTOC(mi->mi_rootvp)); |
314 | #endif |
315 | mi->mi_started = 0; |
316 | |
317 | vrele(mi->mi_rootvp); |
318 | vrele(coda_ctlvp); |
319 | |
320 | active = coda_kill(vfsp, NOT_DOWNCALL); |
321 | mi->mi_rootvp->v_vflag &= ~VV_ROOT; |
322 | error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE); |
323 | printf("coda_unmount: active = %d, vflush active %d\n" , active, error); |
324 | error = 0; |
325 | |
326 | /* I'm going to take this out to allow lookups to go through. I'm |
327 | * not sure it's important anyway. -- DCS 2/2/94 |
328 | */ |
329 | /* vfsp->VFS_DATA = NULL; */ |
330 | |
331 | /* No more vfsp's to hold onto */ |
332 | mi->mi_vfsp = NULL; |
333 | mi->mi_rootvp = NULL; |
334 | |
335 | if (error) |
336 | MARK_INT_FAIL(CODA_UMOUNT_STATS); |
337 | else |
338 | MARK_INT_SAT(CODA_UMOUNT_STATS); |
339 | |
340 | return(error); |
341 | } |
342 | return (EINVAL); |
343 | } |
344 | |
345 | /* |
346 | * find root of cfs |
347 | */ |
348 | int |
349 | coda_root(struct mount *vfsp, struct vnode **vpp) |
350 | { |
351 | struct coda_mntinfo *mi = vftomi(vfsp); |
352 | int error; |
353 | struct lwp *l = curlwp; /* XXX - bnoble */ |
354 | CodaFid VFid; |
355 | static const CodaFid invalfid = INVAL_FID; |
356 | |
357 | ENTRY; |
358 | MARK_ENTRY(CODA_ROOT_STATS); |
359 | |
360 | if (vfsp == mi->mi_vfsp) { |
361 | if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid, sizeof(CodaFid))) |
362 | { /* Found valid root. */ |
363 | *vpp = mi->mi_rootvp; |
364 | /* On Mach, this is vref. On NetBSD, VOP_LOCK */ |
365 | vref(*vpp); |
366 | vn_lock(*vpp, LK_EXCLUSIVE); |
367 | MARK_INT_SAT(CODA_ROOT_STATS); |
368 | return(0); |
369 | } |
370 | } |
371 | |
372 | error = venus_root(vftomi(vfsp), l->l_cred, l->l_proc, &VFid); |
373 | |
374 | if (!error) { |
375 | struct cnode *cp = VTOC(mi->mi_rootvp); |
376 | |
377 | /* |
378 | * Save the new rootfid in the cnode, and rekey the cnode |
379 | * with the new fid key. |
380 | */ |
381 | error = vcache_rekey_enter(vfsp, mi->mi_rootvp, |
382 | &invalfid, sizeof(CodaFid), &VFid, sizeof(CodaFid)); |
383 | if (error) |
384 | goto exit; |
385 | cp->c_fid = VFid; |
386 | vcache_rekey_exit(vfsp, mi->mi_rootvp, |
387 | &invalfid, sizeof(CodaFid), &cp->c_fid, sizeof(CodaFid)); |
388 | |
389 | *vpp = mi->mi_rootvp; |
390 | vref(*vpp); |
391 | vn_lock(*vpp, LK_EXCLUSIVE); |
392 | MARK_INT_SAT(CODA_ROOT_STATS); |
393 | goto exit; |
394 | } else if (error == ENODEV || error == EINTR) { |
395 | /* Gross hack here! */ |
396 | /* |
397 | * If Venus fails to respond to the CODA_ROOT call, coda_call returns |
398 | * ENODEV. Return the uninitialized root vnode to allow vfs |
399 | * operations such as unmount to continue. Without this hack, |
400 | * there is no way to do an unmount if Venus dies before a |
401 | * successful CODA_ROOT call is done. All vnode operations |
402 | * will fail. |
403 | */ |
404 | *vpp = mi->mi_rootvp; |
405 | vref(*vpp); |
406 | vn_lock(*vpp, LK_EXCLUSIVE); |
407 | MARK_INT_FAIL(CODA_ROOT_STATS); |
408 | error = 0; |
409 | goto exit; |
410 | } else { |
411 | CODADEBUG( CODA_ROOT, myprintf(("error %d in CODA_ROOT\n" , error)); ); |
412 | MARK_INT_FAIL(CODA_ROOT_STATS); |
413 | |
414 | goto exit; |
415 | } |
416 | exit: |
417 | return(error); |
418 | } |
419 | |
420 | /* |
421 | * Get file system statistics. |
422 | */ |
423 | int |
424 | coda_nb_statvfs(struct mount *vfsp, struct statvfs *sbp) |
425 | { |
426 | struct lwp *l = curlwp; |
427 | struct coda_statfs fsstat; |
428 | int error; |
429 | |
430 | ENTRY; |
431 | MARK_ENTRY(CODA_STATFS_STATS); |
432 | if (!CODA_MOUNTED(vfsp)) { |
433 | /* MARK_INT_FAIL(CODA_STATFS_STATS); */ |
434 | return(EINVAL); |
435 | } |
436 | |
437 | /* XXX - what to do about f_flags, others? --bnoble */ |
438 | /* Below This is what AFS does |
439 | #define NB_SFS_SIZ 0x895440 |
440 | */ |
441 | /* Note: Normal fs's have a bsize of 0x400 == 1024 */ |
442 | |
443 | error = venus_statfs(vftomi(vfsp), l->l_cred, l, &fsstat); |
444 | |
445 | if (!error) { |
446 | sbp->f_bsize = 8192; /* XXX */ |
447 | sbp->f_frsize = 8192; /* XXX */ |
448 | sbp->f_iosize = 8192; /* XXX */ |
449 | sbp->f_blocks = fsstat.f_blocks; |
450 | sbp->f_bfree = fsstat.f_bfree; |
451 | sbp->f_bavail = fsstat.f_bavail; |
452 | sbp->f_bresvd = 0; |
453 | sbp->f_files = fsstat.f_files; |
454 | sbp->f_ffree = fsstat.f_ffree; |
455 | sbp->f_favail = fsstat.f_ffree; |
456 | sbp->f_fresvd = 0; |
457 | copy_statvfs_info(sbp, vfsp); |
458 | } |
459 | |
460 | MARK_INT_SAT(CODA_STATFS_STATS); |
461 | return(error); |
462 | } |
463 | |
464 | /* |
465 | * Flush any pending I/O. |
466 | */ |
467 | int |
468 | coda_sync(struct mount *vfsp, int waitfor, |
469 | kauth_cred_t cred) |
470 | { |
471 | ENTRY; |
472 | MARK_ENTRY(CODA_SYNC_STATS); |
473 | MARK_INT_SAT(CODA_SYNC_STATS); |
474 | return(0); |
475 | } |
476 | |
477 | int |
478 | coda_vget(struct mount *vfsp, ino_t ino, |
479 | struct vnode **vpp) |
480 | { |
481 | ENTRY; |
482 | return (EOPNOTSUPP); |
483 | } |
484 | |
485 | int |
486 | coda_loadvnode(struct mount *mp, struct vnode *vp, |
487 | const void *key, size_t key_len, const void **new_key) |
488 | { |
489 | CodaFid fid; |
490 | struct cnode *cp; |
491 | extern int (**coda_vnodeop_p)(void *); |
492 | |
493 | KASSERT(key_len == sizeof(CodaFid)); |
494 | memcpy(&fid, key, key_len); |
495 | |
496 | cp = kmem_zalloc(sizeof(*cp), KM_SLEEP); |
497 | mutex_init(&cp->c_lock, MUTEX_DEFAULT, IPL_NONE); |
498 | cp->c_fid = fid; |
499 | cp->c_vnode = vp; |
500 | vp->v_op = coda_vnodeop_p; |
501 | vp->v_tag = VT_CODA; |
502 | vp->v_type = VNON; |
503 | vp->v_data = cp; |
504 | |
505 | *new_key = &cp->c_fid; |
506 | |
507 | return 0; |
508 | } |
509 | |
510 | /* |
511 | * fhtovp is now what vget used to be in 4.3-derived systems. For |
512 | * some silly reason, vget is now keyed by a 32 bit ino_t, rather than |
513 | * a type-specific fid. |
514 | */ |
515 | int |
516 | coda_fhtovp(struct mount *vfsp, struct fid *fhp, struct mbuf *nam, |
517 | struct vnode **vpp, int *exflagsp, |
518 | kauth_cred_t *creadanonp) |
519 | { |
520 | struct cfid *cfid = (struct cfid *)fhp; |
521 | struct cnode *cp = 0; |
522 | int error; |
523 | struct lwp *l = curlwp; /* XXX -mach */ |
524 | CodaFid VFid; |
525 | int vtype; |
526 | |
527 | ENTRY; |
528 | |
529 | MARK_ENTRY(CODA_VGET_STATS); |
530 | /* Check for vget of control object. */ |
531 | if (IS_CTL_FID(&cfid->cfid_fid)) { |
532 | *vpp = coda_ctlvp; |
533 | vref(coda_ctlvp); |
534 | MARK_INT_SAT(CODA_VGET_STATS); |
535 | return(0); |
536 | } |
537 | |
538 | error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, l->l_cred, l->l_proc, &VFid, &vtype); |
539 | |
540 | if (error) { |
541 | CODADEBUG(CODA_VGET, myprintf(("vget error %d\n" ,error));) |
542 | *vpp = (struct vnode *)0; |
543 | } else { |
544 | CODADEBUG(CODA_VGET, |
545 | myprintf(("vget: %s type %d result %d\n" , |
546 | coda_f2s(&VFid), vtype, error)); ) |
547 | |
548 | cp = make_coda_node(&VFid, vfsp, vtype); |
549 | *vpp = CTOV(cp); |
550 | } |
551 | return(error); |
552 | } |
553 | |
554 | int |
555 | coda_vptofh(struct vnode *vnp, struct fid *fidp) |
556 | { |
557 | ENTRY; |
558 | return (EOPNOTSUPP); |
559 | } |
560 | |
561 | void |
562 | coda_init(void) |
563 | { |
564 | ENTRY; |
565 | } |
566 | |
567 | void |
568 | coda_done(void) |
569 | { |
570 | ENTRY; |
571 | } |
572 | |
573 | SYSCTL_SETUP(sysctl_vfs_coda_setup, "sysctl vfs.coda subtree setup" ) |
574 | { |
575 | |
576 | sysctl_createv(clog, 0, NULL, NULL, |
577 | CTLFLAG_PERMANENT, |
578 | CTLTYPE_NODE, "coda" , |
579 | SYSCTL_DESCR("code vfs options" ), |
580 | NULL, 0, NULL, 0, |
581 | CTL_VFS, 18, CTL_EOL); |
582 | /* |
583 | * XXX the "18" above could be dynamic, thereby eliminating |
584 | * one more instance of the "number to vfs" mapping problem, |
585 | * but "18" is the order as taken from sys/mount.h |
586 | */ |
587 | |
588 | /* |
589 | sysctl_createv(clog, 0, NULL, NULL, |
590 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
591 | CTLTYPE_INT, "clusterread", |
592 | SYSCTL_DESCR( anyone? ), |
593 | NULL, 0, &doclusterread, 0, |
594 | CTL_VFS, 18, FFS_CLUSTERREAD, CTL_EOL); |
595 | */ |
596 | } |
597 | |
598 | /* |
599 | * To allow for greater ease of use, some vnodes may be orphaned when |
600 | * Venus dies. Certain operations should still be allowed to go |
601 | * through, but without propagating orphan-ness. So this function will |
602 | * get a new vnode for the file from the current run of Venus. |
603 | */ |
604 | |
605 | int |
606 | getNewVnode(struct vnode **vpp) |
607 | { |
608 | struct cfid cfid; |
609 | struct coda_mntinfo *mi = vftomi((*vpp)->v_mount); |
610 | |
611 | ENTRY; |
612 | |
613 | cfid.cfid_len = (short)sizeof(CodaFid); |
614 | cfid.cfid_fid = VTOC(*vpp)->c_fid; /* Structure assignment. */ |
615 | /* XXX ? */ |
616 | |
617 | /* We're guessing that if set, the 1st element on the list is a |
618 | * valid vnode to use. If not, return ENODEV as venus is dead. |
619 | */ |
620 | if (mi->mi_vfsp == NULL) |
621 | return ENODEV; |
622 | |
623 | return coda_fhtovp(mi->mi_vfsp, (struct fid*)&cfid, NULL, vpp, |
624 | NULL, NULL); |
625 | } |
626 | |
627 | #include <ufs/ufs/quota.h> |
628 | #include <ufs/ufs/ufsmount.h> |
629 | /* get the mount structure corresponding to a given device. Assume |
630 | * device corresponds to a UFS. Return NULL if no device is found. |
631 | */ |
632 | struct mount *devtomp(dev_t dev) |
633 | { |
634 | struct mount *mp; |
635 | |
636 | mutex_enter(&mountlist_lock); |
637 | TAILQ_FOREACH(mp, &mountlist, mnt_list) { |
638 | if ((!strcmp(mp->mnt_op->vfs_name, MOUNT_UFS)) && |
639 | ((VFSTOUFS(mp))->um_dev == (dev_t) dev)) { |
640 | /* mount corresponds to UFS and the device matches one we want */ |
641 | break; |
642 | } |
643 | } |
644 | mutex_exit(&mountlist_lock); |
645 | return mp; |
646 | } |
647 | |