2 * Portions Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
8 #include <afs/sysincludes.h> /* Standard vendor system headers */
9 #include <afsincludes.h> /* Afs-based standard headers */
10 #include <afs/afs_stats.h> /* statistics */
11 #include <sys/malloc.h>
12 #include <sys/namei.h>
14 #ifndef AFS_DARWIN80_ENV
15 #include <sys/syscall.h>
17 #include <sys/sysctl.h>
18 #include "../afs/sysctl.h"
21 #define M_UFSMNT M_TEMP /* DARWIN80 MALLOC doesn't look at the type anyway */
24 struct vcache
*afs_globalVp
= 0;
25 struct mount
*afs_globalVFS
= 0;
35 afs_fhtovp(struct mount
*mp
, struct fid
*fhp
, struct vnode
**vpp
)
41 afs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
46 #ifdef AFS_DARWIN80_ENV
47 #define CTX_TYPE vfs_context_t
48 #define CTX_PROC_CONVERT(C) vfs_context_proc((C))
49 #define STATFS_TYPE struct vfsstatfs
51 #define CTX_TYPE struct proc *
52 #define CTX_PROC_CONVERT(C) (C)
53 #define STATFS_TYPE struct statfs
54 #define vfs_statfs(VFS) &(VFS)->mnt_stat
56 #define PROC_DECL(out,in) struct proc *out = CTX_PROC_CONVERT(in)
59 afs_start(struct mount
*mp
, int flags
, CTX_TYPE p
)
61 return (0); /* nothing to do. ? */
65 afs_statfs(struct mount
*mp
, STATFS_TYPE
*abp
, CTX_TYPE ctx
);
66 #ifdef AFS_DARWIN80_ENV
68 afs_mount(struct mount
*mp
, vnode_t
*devvp
, user_addr_t data
, vfs_context_t ctx
)
71 afs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct nameidata
*ndp
, CTX_TYPE ctx
)
74 /* ndp contains the mounted-from device. Just ignore it.
75 * we also don't care about our proc struct. */
78 #ifdef AFS_DARWIN80_ENV
79 struct vfsioattr ioattr
;
80 /* vfs_statfs advertised as RO, but isn't */
81 /* new api will be needed to initialize this information (nfs needs to
82 set mntfromname too) */
84 STATFS_TYPE
*mnt_stat
= vfs_statfs(mp
);
90 AFS_STATCNT(afs_mount
);
92 if (data
== 0 && afs_globalVFS
) { /* Don't allow remounts. */
98 #ifdef AFS_DARWIN80_ENV
99 vfs_ioattr(mp
, &ioattr
);
100 ioattr
.io_devblocksize
= (16 * 32768);
101 vfs_setioattr(mp
, &ioattr
);
102 /* f_iosize is handled in VFS_GETATTR */
104 mp
->vfs_bsize
= 8192;
105 mp
->mnt_stat
.f_iosize
= 8192;
109 #ifndef AFS_DARWIN80_ENV
110 (void)copyinstr(path
, mp
->mnt_stat
.f_mntonname
, MNAMELEN
- 1, &size
);
111 memset(mp
->mnt_stat
.f_mntonname
+ size
, 0, MNAMELEN
- size
);
113 memset(mnt_stat
->f_mntfromname
, 0, MNAMELEN
);
116 strcpy(mnt_stat
->f_mntfromname
, "AFS");
117 /* null terminated string "AFS" will fit, just leave it be. */
118 vfs_setfsprivate(mp
, NULL
);
120 struct VenusFid
*rootFid
= NULL
;
122 char volName
[MNAMELEN
];
124 (void)copyinstr(data
, volName
, MNAMELEN
- 1, &size
);
125 memset(volName
+ size
, 0, MNAMELEN
- size
);
127 if (volName
[0] == 0) {
128 strcpy(mnt_stat
->f_mntfromname
, "AFS");
129 vfs_setfsprivate(mp
, &afs_rootFid
);
131 struct cell
*localcell
= afs_GetPrimaryCell(READ_LOCK
);
132 if (localcell
== NULL
) {
137 /* Set the volume identifier to "AFS:volume.name" */
138 snprintf(mnt_stat
->f_mntfromname
, MNAMELEN
- 1, "AFS:%s",
141 afs_GetVolumeByName(volName
, localcell
->cellNum
, 1,
142 (struct vrequest
*)0, READ_LOCK
);
145 int volid
= (tvp
->roVol
? tvp
->roVol
: tvp
->volume
);
146 MALLOC(rootFid
, struct VenusFid
*, sizeof(*rootFid
), M_UFSMNT
,
148 rootFid
->Cell
= localcell
->cellNum
;
149 rootFid
->Fid
.Volume
= volid
;
150 rootFid
->Fid
.Vnode
= 1;
151 rootFid
->Fid
.Unique
= 1;
157 vfs_setfsprivate(mp
, &rootFid
);
160 #ifdef AFS_DARWIN80_ENV
161 afs_vfs_typenum
=vfs_typenum(mp
);
162 vfs_setauthopaque(mp
);
163 vfs_setauthopaqueaccess(mp
);
165 strcpy(mp
->mnt_stat
.f_fstypename
, "afs");
168 (void)afs_statfs(mp
, mnt_stat
, ctx
);
173 afs_unmount(struct mount
*mp
, int flags
, CTX_TYPE ctx
)
175 void *mdata
= vfs_fsprivate(mp
);
177 AFS_STATCNT(afs_unmount
);
179 if (mdata
!= (qaddr_t
) - 1) {
181 vfs_setfsprivate(mp
, (qaddr_t
) - 1);
182 FREE(mdata
, M_UFSMNT
);
184 if (flags
& MNT_FORCE
) {
186 #ifdef AFS_DARWIN80_ENV
187 afs_PutVCache(afs_globalVp
);
190 vrele(AFSTOV(afs_globalVp
));
196 vflush(mp
, NULLVP
, FORCECLOSE
/*0*/);
205 vfs_clearflags(mp
, MNT_LOCAL
);
213 #ifdef AFS_DARWIN80_ENV
215 afs_root(struct mount
*mp
, struct vnode
**vpp
, vfs_context_t ctx
)
218 afs_root(struct mount
*mp
, struct vnode
**vpp
)
221 void *mdata
= vfs_fsprivate(mp
);
223 struct vrequest treq
;
224 struct vcache
*tvp
= 0;
227 #ifdef AFS_DARWIN80_ENV
228 struct ucred
*cr
= vfs_context_ucred(ctx
);
230 struct proc
*p
= current_proc();
232 struct ucred
*cr
= &_cr
;
235 _cr
= *p
->p_cred
->pc_ucred
;
239 AFS_STATCNT(afs_root
);
242 if (mdata
== NULL
&& afs_globalVp
243 && (afs_globalVp
->f
.states
& CStatd
)) {
247 } else if (mdata
== (qaddr_t
) - 1) {
250 struct VenusFid
*rootFid
= (mdata
== NULL
)
251 ? &afs_rootFid
: (struct VenusFid
*)mdata
;
253 if (!(error
= afs_InitReq(&treq
, cr
)) && !(error
= afs_CheckInit())) {
254 tvp
= afs_GetVCache(rootFid
, &treq
, NULL
, NULL
);
255 #ifdef AFS_DARWIN80_ENV
258 error
= afs_darwin_finalizevnode(tvp
, NULL
, NULL
, 1, 0);
263 /* re-acquire the usecount that finalizevnode disposed of */
264 vnode_ref(AFSTOV(tvp
));
267 /* we really want this to stay around */
274 if (tvp
!= afs_globalVp
) {
275 /* someone else got there before us! */
288 #ifndef AFS_DARWIN80_ENV /* KPI callers don't need a usecount reference */
291 vn_lock(AFSTOV(tvp
), LK_EXCLUSIVE
| LK_RETRY
, p
);
296 #ifdef AFS_DARWIN80_ENV
297 /* This iocount is for the caller. the initial iocount
298 * is for the eventual afs_PutVCache. for mdata != null,
299 * there will not be a PutVCache, so the caller gets the
300 * initial (from GetVCache or finalizevnode) iocount
302 vnode_get(AFSTOV(tvp
));
311 #ifndef AFS_DARWIN80_ENV
312 AFSTOV(tvp
)->v_flag
|= VROOT
;
313 AFSTOV(tvp
)->v_vfsp
= mp
;
317 afs_Trace2(afs_iclSetp
, CM_TRACE_VFSROOT
, ICL_TYPE_POINTER
, *vpp
,
318 ICL_TYPE_INT32
, error
);
323 #ifndef AFS_DARWIN80_ENV /* vget vfsop never had this prototype AFAIK */
325 afs_vget(struct mount
*mp
, int lfl
, struct vnode
*vp
)
328 //printf("vget called. help!\n");
329 if (vp
->v_usecount
< 0) {
330 vprint("bad usecount", vp
);
333 error
= vget(vp
, lfl
, current_proc());
335 insmntque(vp
, mp
); /* take off free list */
339 int afs_vfs_vget(struct mount
*mp
, void *ino
, struct vnode
**vpp
)
341 return ENOENT
; /* cannot implement */
347 afs_statfs(struct mount
*mp
, STATFS_TYPE
*abp
, CTX_TYPE ctx
)
349 STATFS_TYPE
*sysstat
= vfs_statfs(mp
);
351 AFS_STATCNT(afs_statfs
);
353 #ifdef AFS_DARWIN80_ENV
354 abp
->f_iosize
= (256 * 1024);
355 abp
->f_bsize
= vfs_devblocksize(mp
);
357 abp
->f_bsize
= mp
->vfs_bsize
;
358 abp
->f_iosize
= mp
->vfs_bsize
;
361 abp
->f_type
= MOUNT_AFS
;
364 abp
->f_blocks
= abp
->f_bfree
= abp
->f_bavail
= abp
->f_files
=
365 abp
->f_ffree
= AFS_VFS_FAKEFREE
;
367 if (abp
!= sysstat
) {
368 abp
->f_fsid
.val
[0] = sysstat
->f_fsid
.val
[0];
369 abp
->f_fsid
.val
[1] = sysstat
->f_fsid
.val
[1];
370 #ifndef AFS_DARWIN80_ENV
371 abp
->f_type
= vfs_typenum(mp
);
373 memcpy((caddr_t
) & abp
->f_mntonname
[0],
374 (caddr_t
) sysstat
->f_mntonname
, MNAMELEN
);
375 memcpy((caddr_t
) & abp
->f_mntfromname
[0],
376 (caddr_t
) sysstat
->f_mntfromname
, MNAMELEN
);
383 #ifdef AFS_DARWIN80_ENV
385 afs_vfs_getattr(struct mount
*mp
, struct vfs_attr
*outattrs
,
386 vfs_context_t context
)
388 VFSATTR_RETURN(outattrs
, f_bsize
, vfs_devblocksize(mp
));
389 VFSATTR_RETURN(outattrs
, f_iosize
, vfs_devblocksize(mp
));
390 VFSATTR_RETURN(outattrs
, f_blocks
, 2000000);
391 VFSATTR_RETURN(outattrs
, f_bfree
, 2000000);
392 VFSATTR_RETURN(outattrs
, f_bavail
, 2000000);
393 VFSATTR_RETURN(outattrs
, f_files
, 2000000);
394 VFSATTR_RETURN(outattrs
, f_ffree
, 2000000);
395 if ( VFSATTR_IS_ACTIVE(outattrs
, f_capabilities
) )
397 vol_capabilities_attr_t
*vcapattrptr
;
398 vcapattrptr
= &outattrs
->f_capabilities
;
399 vcapattrptr
->capabilities
[VOL_CAPABILITIES_FORMAT
] =
400 VOL_CAP_FMT_SYMBOLICLINKS
|
401 VOL_CAP_FMT_HARDLINKS
|
402 VOL_CAP_FMT_ZERO_RUNS
|
403 VOL_CAP_FMT_CASE_SENSITIVE
|
404 VOL_CAP_FMT_CASE_PRESERVING
|
405 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
406 VOL_CAP_FMT_2TB_FILESIZE
|
407 VOL_CAP_FMT_FAST_STATFS
;
408 vcapattrptr
->capabilities
[VOL_CAPABILITIES_INTERFACES
] =
409 VOL_CAP_INT_ADVLOCK
|
411 vcapattrptr
->capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0;
412 vcapattrptr
->capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0;
414 /* Capabilities we know about: */
415 vcapattrptr
->valid
[VOL_CAPABILITIES_FORMAT
] =
416 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
417 VOL_CAP_FMT_SYMBOLICLINKS
|
418 VOL_CAP_FMT_HARDLINKS
|
419 VOL_CAP_FMT_JOURNAL
|
420 VOL_CAP_FMT_JOURNAL_ACTIVE
|
421 VOL_CAP_FMT_NO_ROOT_TIMES
|
422 VOL_CAP_FMT_SPARSE_FILES
|
423 VOL_CAP_FMT_ZERO_RUNS
|
424 VOL_CAP_FMT_CASE_SENSITIVE
|
425 VOL_CAP_FMT_CASE_PRESERVING
|
426 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
427 VOL_CAP_FMT_2TB_FILESIZE
|
428 VOL_CAP_FMT_FAST_STATFS
;
429 vcapattrptr
->valid
[VOL_CAPABILITIES_INTERFACES
] =
430 VOL_CAP_INT_SEARCHFS
|
431 VOL_CAP_INT_ATTRLIST
|
432 VOL_CAP_INT_NFSEXPORT
|
433 VOL_CAP_INT_READDIRATTR
|
434 VOL_CAP_INT_EXCHANGEDATA
|
435 VOL_CAP_INT_COPYFILE
|
436 VOL_CAP_INT_ALLOCATE
|
437 VOL_CAP_INT_VOL_RENAME
|
438 VOL_CAP_INT_ADVLOCK
|
440 vcapattrptr
->valid
[VOL_CAPABILITIES_RESERVED1
] = 0;
441 vcapattrptr
->valid
[VOL_CAPABILITIES_RESERVED2
] = 0;
443 VFSATTR_SET_SUPPORTED(outattrs
, f_capabilities
);
449 #ifdef AFS_DARWIN80_ENV
451 afs_sync(struct mount
*mp
, int waitfor
, CTX_TYPE ctx
)
454 afs_sync(struct mount
*mp
, int waitfor
, struct ucred
*cred
, struct proc
*p
)
460 u_int32_t afs_darwin_realmodes
= 0;
461 u_int32_t afs_darwin_fsevents
= 0;
462 extern int AFSDOBULK
;
465 afs_sysctl_int(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
,
466 user_addr_t newp
, size_t newlen
, u_int32_t
*object
)
468 #ifdef AFS_DARWIN80_ENV
471 if (oldp
!= USER_ADDR_NULL
&& oldlenp
== NULL
)
473 if (oldp
&& *oldlenp
< sizeof(u_int32_t
))
475 if (newp
&& newlen
!= sizeof(u_int32_t
))
477 *oldlenp
= sizeof(u_int32_t
);
479 if ((error
= copyout(object
,
480 oldp
, sizeof(u_int32_t
)))) {
485 return copyin(newp
, object
, sizeof(u_int32_t
));
488 return sysctl_int(oldp
, oldlenp
, newp
, newlen
,
493 #ifdef AFS_DARWIN80_ENV
495 afs_sysctl(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
,
496 user_addr_t newp
, size_t newlen
, vfs_context_t context
)
499 afs_sysctl(int *name
, u_int namelen
, void *oldp
, size_t *oldlenp
,
500 void *newp
, size_t newlen
, struct proc
*p
)
505 /* nothing defined */
511 case AFS_SC_DARWIN_ALL
:
513 case AFS_SC_DARWIN_ALL_REALMODES
:
514 return afs_sysctl_int(name
, namelen
, oldp
, oldlenp
,
515 newp
, newlen
, &afs_darwin_realmodes
);
516 case AFS_SC_DARWIN_ALL_FSEVENTS
:
517 return afs_sysctl_int(name
, namelen
, oldp
, oldlenp
,
518 newp
, newlen
, &afs_darwin_fsevents
);
519 case AFS_SC_DARWIN_ALL_BULKSTAT
:
520 return afs_sysctl_int(name
, namelen
, oldp
, oldlenp
,
521 newp
, newlen
, &AFSDOBULK
);
524 /* darwin version specific sysctl's goes here */
532 extern int vfs_opv_numops
; /* The total number of defined vnode operations */
533 extern struct vnodeopv_desc afs_vnodeop_opv_desc
;
535 afs_init(struct vfsconf
*vfc
)
537 #ifndef AFS_DARWIN80_ENV /* vfs_fsadd does all this junk */
539 int (**opv_desc_vector
) ();
540 struct vnodeopv_entry_desc
*opve_descp
;
544 MALLOC(afs_vnodeop_p
, PFI
*, vfs_opv_numops
* sizeof(PFI
), M_TEMP
,
547 memset(afs_vnodeop_p
, 0, vfs_opv_numops
* sizeof(PFI
));
549 opv_desc_vector
= afs_vnodeop_p
;
550 for (j
= 0; afs_vnodeop_opv_desc
.opv_desc_ops
[j
].opve_op
; j
++) {
551 opve_descp
= &(afs_vnodeop_opv_desc
.opv_desc_ops
[j
]);
554 * Sanity check: is this operation listed
555 * in the list of operations? We check this
556 * by seeing if its offest is zero. Since
557 * the default routine should always be listed
558 * first, it should be the only one with a zero
559 * offset. Any other operation with a zero
560 * offset is probably not listed in
561 * vfs_op_descs, and so is probably an error.
563 * A panic here means the layer programmer
564 * has committed the all-too common bug
565 * of adding a new operation to the layer's
566 * list of vnode operations but
567 * not adding the operation to the system-wide
568 * list of supported operations.
570 if (opve_descp
->opve_op
->vdesc_offset
== 0
571 && opve_descp
->opve_op
->vdesc_offset
!= VOFFSET(vop_default
)) {
572 printf("afs_init: operation %s not listed in %s.\n",
573 opve_descp
->opve_op
->vdesc_name
, "vfs_op_descs");
574 panic("load_afs: bad operation");
577 * Fill in this entry.
579 opv_desc_vector
[opve_descp
->opve_op
->vdesc_offset
] =
580 opve_descp
->opve_impl
;
584 * Finally, go back and replace unfilled routines
585 * with their default. (Sigh, an O(n^3) algorithm. I
586 * could make it better, but that'd be work, and n is small.)
590 * Force every operations vector to have a default routine.
592 opv_desc_vector
= afs_vnodeop_p
;
593 if (opv_desc_vector
[VOFFSET(vop_default
)] == NULL
) {
594 panic("afs_init: operation vector without default routine.");
596 for (j
= 0; j
< vfs_opv_numops
; j
++)
597 if (opv_desc_vector
[j
] == NULL
)
598 opv_desc_vector
[j
] = opv_desc_vector
[VOFFSET(vop_default
)];
603 struct vfsops afs_vfsops
= {
608 #ifdef AFS_DARWIN80_ENV
616 #ifdef AFS_DARWIN80_ENV
625 #ifdef AFS_DARWIN80_ENV