2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
15 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "h/syscallargs.h"
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* afs statistics */
22 #include "rx/rx_globals.h"
24 struct VenusFid afs_rootFid;
25 afs_int32 afs_waitForever=0;
26 short afs_waitForeverCount = 0;
27 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
29 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
30 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
31 struct AFS_UCRED **acred)
33 /* Prototypes for pioctl routines */
36 DECL_PIOCTL(PStoreBehind);
41 DECL_PIOCTL(PGetFileCell);
42 DECL_PIOCTL(PGetWSCell);
43 DECL_PIOCTL(PGetUserCell);
44 DECL_PIOCTL(PSetTokens);
45 DECL_PIOCTL(PGetVolumeStatus);
46 DECL_PIOCTL(PSetVolumeStatus);
48 DECL_PIOCTL(PNewStatMount);
49 DECL_PIOCTL(PGetTokens);
51 DECL_PIOCTL(PMariner);
52 DECL_PIOCTL(PCheckServers);
53 DECL_PIOCTL(PCheckVolNames);
54 DECL_PIOCTL(PCheckAuth);
55 DECL_PIOCTL(PFindVolume);
56 DECL_PIOCTL(PViceAccess);
57 DECL_PIOCTL(PSetCacheSize);
58 DECL_PIOCTL(PGetCacheSize);
59 DECL_PIOCTL(PRemoveCallBack);
60 DECL_PIOCTL(PNewCell);
61 DECL_PIOCTL(PNewAlias);
62 DECL_PIOCTL(PListCells);
63 DECL_PIOCTL(PListAliases);
64 DECL_PIOCTL(PRemoveMount);
65 DECL_PIOCTL(PVenusLogging);
66 DECL_PIOCTL(PGetCellStatus);
67 DECL_PIOCTL(PSetCellStatus);
68 DECL_PIOCTL(PFlushVolumeData);
69 DECL_PIOCTL(PGetVnodeXStatus);
70 DECL_PIOCTL(PSetSysName);
71 DECL_PIOCTL(PSetSPrefs);
72 DECL_PIOCTL(PSetSPrefs33);
73 DECL_PIOCTL(PGetSPrefs);
74 DECL_PIOCTL(PExportAfs);
76 DECL_PIOCTL(PTwiddleRx);
77 DECL_PIOCTL(PGetInitParams);
78 DECL_PIOCTL(PGetRxkcrypt);
79 DECL_PIOCTL(PSetRxkcrypt);
80 DECL_PIOCTL(PGetCPrefs);
81 DECL_PIOCTL(PSetCPrefs);
82 DECL_PIOCTL(PFlushMount);
83 DECL_PIOCTL(PRxStatProc);
84 DECL_PIOCTL(PRxStatPeer);
85 DECL_PIOCTL(PPrefetchFromTape);
86 DECL_PIOCTL(PResidencyCmd);
88 /* Prototypes for private routines */
89 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
90 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
91 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
92 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
93 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
94 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
97 static int (*(VpioctlSw[]))() = {
102 PGetVolumeStatus, /* 4 */
103 PSetVolumeStatus, /* 5 */
108 PCheckServers, /* 10 */
109 PCheckVolNames, /* 11 */
111 PBogus, /* 13 -- used to be quick check time */
113 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
114 PBogus, /* 16 -- used to be testing code */
115 PNoop, /* 17 -- used to be enable group */
116 PNoop, /* 18 -- used to be disable group */
117 PBogus, /* 19 -- used to be list group */
118 PViceAccess, /* 20 */
119 PUnlog, /* 21 -- unlog *is* unpag in this system */
120 PGetFID, /* 22 -- get file ID */
121 PBogus, /* 23 -- used to be waitforever */
122 PSetCacheSize, /* 24 */
123 PRemoveCallBack, /* 25 -- flush only the callback */
126 PRemoveMount, /* 28 -- delete mount point */
127 PNewStatMount, /* 29 -- new style mount point stat */
128 PGetFileCell, /* 30 -- get cell name for input file */
129 PGetWSCell, /* 31 -- get cell name for workstation */
130 PMariner, /* 32 - set/get mariner host */
131 PGetUserCell, /* 33 -- get cell name for user */
132 PVenusLogging, /* 34 -- Enable/Disable logging */
133 PGetCellStatus, /* 35 */
134 PSetCellStatus, /* 36 */
135 PFlushVolumeData, /* 37 -- flush all data from a volume */
136 PSetSysName, /* 38 - Set system name */
137 PExportAfs, /* 39 - Export Afs to remote nfs clients */
138 PGetCacheSize, /* 40 - get cache size and usage */
139 PGetVnodeXStatus, /* 41 - get vcache's special status */
140 PSetSPrefs33, /* 42 - Set CM Server preferences... */
141 PGetSPrefs, /* 43 - Get CM Server preferences... */
142 PGag, /* 44 - turn off/on all CM messages */
143 PTwiddleRx, /* 45 - adjust some RX params */
144 PSetSPrefs, /* 46 - Set CM Server preferences... */
145 PStoreBehind, /* 47 - set degree of store behind to be done */
146 PGCPAGs, /* 48 - disable automatic pag gc-ing */
147 PGetInitParams, /* 49 - get initial cm params */
148 PGetCPrefs, /* 50 - get client interface addresses */
149 PSetCPrefs, /* 51 - set client interface addresses */
150 PFlushMount, /* 52 - flush mount symlink data */
151 PRxStatProc, /* 53 - control process RX statistics */
152 PRxStatPeer, /* 54 - control peer RX statistics */
153 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
154 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
155 PBogus, /* 57 -- arla: set file prio */
156 PBogus, /* 58 -- arla: fallback getfh */
157 PBogus, /* 59 -- arla: fallback fhopen */
158 PBogus, /* 60 -- arla: controls xfsdebug */
159 PBogus, /* 61 -- arla: controls arla debug */
160 PBogus, /* 62 -- arla: debug interface */
161 PBogus, /* 63 -- arla: print xfs status */
162 PBogus, /* 64 -- arla: force cache check */
163 PBogus, /* 65 -- arla: break callback */
164 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
165 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
166 PBogus, /* 68 -- arla: fetch stats */
169 static int (*(CpioctlSw[]))() = {
171 PNewAlias, /* 1 -- create new cell alias */
172 PListAliases, /* 2 -- list cell aliases */
175 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
176 int afs_nobody = NFS_NOBODY;
179 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
181 dst->in = (char *)(unsigned long)src->in;
182 dst->out = (char *)(unsigned long)src->out;
183 dst->in_size = src->in_size;
184 dst->out_size = src->out_size;
188 * If you need to change copyin_afs_ioctl(), you may also need to change
193 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
197 #if defined(AFS_HPUX_64BIT_ENV)
198 struct afs_ioctl32 dst32;
200 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
202 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
204 afs_ioctl32_to_afs_ioctl(&dst32, dst);
207 #endif /* defined(AFS_HPUX_64BIT_ENV) */
209 #if defined(AFS_SUN57_64BIT_ENV)
210 struct afs_ioctl32 dst32;
212 if (get_udatamodel() == DATAMODEL_ILP32) {
213 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
215 afs_ioctl32_to_afs_ioctl(&dst32, dst);
218 #endif /* defined(AFS_SUN57_64BIT_ENV) */
220 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
221 struct afs_ioctl32 dst32;
223 if (!ABI_IS_64BIT(get_current_abi()))
225 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
227 afs_ioctl32_to_afs_ioctl(&dst32, dst);
230 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
232 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) && !defined(AFS_AMD64_LINUX20_ENV)
233 struct afs_ioctl32 dst32;
235 #ifdef AFS_SPARC64_LINUX24_ENV
236 if (current->thread.flags & SPARC_FLAG_32BIT)
237 #elif AFS_SPARC64_LINUX20_ENV
238 if (current->tss.flags & SPARC_FLAG_32BIT)
240 #error Not done for this linux type
241 #endif /* AFS_SPARC64_LINUX20_ENV */
243 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
245 afs_ioctl32_to_afs_ioctl(&dst32, dst);
248 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
250 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
254 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
256 register afs_int32 code;
259 AFS_STATCNT(HandleIoctl);
261 switch(acom & 0xff) {
263 avc->states |= CSafeStore;
267 /* case 2 used to be abort store, but this is no longer provided,
268 since it is impossible to implement under normal Unix.
272 /* return the name of the cell this file is open on */
273 register struct cell *tcell;
274 register afs_int32 i;
276 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
278 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
280 if (i > adata->out_size) {
281 /* 0 means we're not interested in the output */
282 if (adata->out_size != 0) code = EFAULT;
286 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
288 afs_PutCell(tcell, READ_LOCK);
294 case 49: /* VIOC_GETINITPARAMS */
295 if (adata->out_size < sizeof(struct cm_initparams)) {
299 AFS_COPYOUT(&cm_initParams, adata->out,
300 sizeof(struct cm_initparams), code);
312 return code; /* so far, none implemented */
317 /* For aix we don't temporarily bypass ioctl(2) but rather do our
318 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
319 * is now called from afs_gn_ioctl.
321 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
323 struct afs_ioctl data;
326 AFS_STATCNT(afs_ioctl);
327 if (((cmd >> 8) & 0xff) == 'V') {
328 /* This is a VICEIOCTL call */
329 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
332 error = HandleIoctl(tvc, cmd, &data);
335 /* No-op call; just return. */
339 #endif /* AFS_AIX_ENV */
341 #if defined(AFS_SGI_ENV)
342 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
348 struct afs_ioctl data;
354 AFS_STATCNT(afs_ioctl);
355 if (((cmd >> 8) & 0xff) == 'V') {
356 /* This is a VICEIOCTL call */
357 error = copyin_afs_ioctl(arg, &data);
360 locked = ISAFS_GLOCK();
363 error = HandleIoctl(tvc, cmd, &data);
368 /* No-op call; just return. */
372 #endif /* AFS_SGI_ENV */
374 /* unlike most calls here, this one uses u.u_error to return error conditions,
375 since this is really an intercepted chapter 2 call, rather than a vnode
378 /* AFS_HPUX102 and up uses VNODE ioctl instead */
379 #ifndef AFS_HPUX102_ENV
380 #if !defined(AFS_SGI_ENV)
384 kioctl(fdes, com, arg, ext, arg2, arg3)
385 #else /* __64BIT__ */
386 kioctl32(fdes, com, arg, ext, arg2, arg3)
387 #endif /* __64BIT__ */
390 kioctl(fdes, com, arg, ext)
401 } u_uap, *uap = &u_uap;
403 #if defined(AFS_SUN5_ENV)
405 struct afs_ioctl_sys {
411 afs_xioctl (uap, rvp)
412 struct afs_ioctl_sys *uap;
415 #elif defined(AFS_OSF_ENV)
416 afs_xioctl (p, args, retval)
425 } *uap = (struct a *)args;
426 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
434 afs_xioctl(p, uap, retval)
436 register struct ioctl_args *uap;
439 #elif defined(AFS_LINUX22_ENV)
440 struct afs_ioctl_sys {
444 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
445 unsigned int com, unsigned long arg)
447 struct afs_ioctl_sys ua, *uap = &ua;
449 int afs_xioctl (void)
455 } *uap = (struct a *)u.u_ap;
456 #endif /* AFS_SUN5_ENV */
458 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
460 #elif !defined(AFS_LINUX22_ENV)
461 register struct file *fd;
463 #if defined(AFS_XBSD_ENV)
464 register struct filedesc *fdp;
466 register struct vcache *tvc;
467 register int ioctlDone = 0, code = 0;
469 AFS_STATCNT(afs_xioctl);
470 #if defined(AFS_XBSD_ENV)
472 if ((u_int)uap->fd >= fdp->fd_nfiles ||
473 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
475 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
478 #if defined(AFS_DARWIN_ENV)
479 if ((code=fdgetf(p, uap->fd, &fd)))
482 #ifdef AFS_LINUX22_ENV
495 if (setuerror(getf(uap->fd, &fd))) {
501 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
503 #else /* AFS_OSF_ENV */
505 #if defined(AFS_SUN57_ENV)
507 if (!fd) return(EBADF);
508 #elif defined(AFS_SUN54_ENV)
510 if (!fd) return(EBADF);
512 if (code = getf(uap->fd, &fd)) {
518 if (!fd) return(EBADF);
525 /* first determine whether this is any sort of vnode */
526 #if defined(AFS_LINUX22_ENV)
531 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
533 if (fd->f_type == DTYPE_VNODE) {
535 /* good, this is a vnode; next see if it is an AFS vnode */
536 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
537 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
538 #elif defined(AFS_OBSD_ENV)
539 tvc = IsAfsVnode((struct vnode *) fd->f_data) ?
540 VTOAFS((struct vnode *) fd->f_data) : NULL;
542 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
544 #endif /* AFS_LINUX22_ENV */
545 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
547 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
548 if (!tvc) { /* shouldn't happen with held gnodes */
553 /* This is an AFS vnode */
554 if (((uap->com >> 8) & 0xff) == 'V') {
555 register struct afs_ioctl *datap;
557 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
558 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
560 osi_FreeSmallSpace(datap);
562 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
565 #if defined(AFS_SUN5_ENV)
580 #else /* AFS_OSF_ENV */
584 #ifdef AFS_LINUX22_ENV
594 code = HandleIoctl(tvc, uap->com, datap);
595 osi_FreeSmallSpace(datap);
609 #if defined(AFS_LINUX22_ENV)
621 code = okioctl(fdes, com, arg, ext, arg2, arg3);
622 #else /* __64BIT__ */
623 code = okioctl32(fdes, com, arg, ext, arg2, arg3);
624 #endif /* __64BIT__ */
625 #else /* !AFS_AIX51_ENV */
626 code = okioctl(fdes, com, arg, ext);
627 #endif /* AFS_AIX51_ENV */
629 #else /* !AFS_AIX41_ENV */
631 okioctl(fdes, com, arg, ext);
632 #elif defined(AFS_SUN5_ENV)
633 #if defined(AFS_SUN57_ENV)
635 #elif defined(AFS_SUN54_ENV)
640 code = ioctl(uap, rvp);
641 #elif defined(AFS_FBSD_ENV)
642 return ioctl(p, uap);
643 #elif defined(AFS_OBSD_ENV)
644 code = sys_ioctl(p, uap, retval);
645 #elif defined(AFS_DARWIN_ENV)
646 return ioctl(p, uap, retval);
647 #elif defined(AFS_OSF_ENV)
648 code = ioctl(p, args, retval);
655 #elif !defined(AFS_LINUX22_ENV)
669 #ifdef AFS_LINUX22_ENV
672 #if defined(KERNEL_HAVE_UERROR)
675 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
676 return (getuerror() ? -1 : u.u_ioctlrv);
678 return getuerror() ? -1 : 0;
681 #endif /* AFS_LINUX22_ENV */
682 #endif /* AFS_SUN5_ENV */
683 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
687 #endif /* AFS_SGI_ENV */
688 #endif /* AFS_HPUX102_ENV */
690 #if defined(AFS_SGI_ENV)
691 /* "pioctl" system call entry point; just pass argument to the parameterized
700 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
704 AFS_STATCNT(afs_pioctl);
706 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
715 #elif defined(AFS_OSF_ENV)
716 afs_pioctl(p, args, retval)
726 } *uap = (struct a *) args;
728 AFS_STATCNT(afs_pioctl);
729 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
732 #elif defined(AFS_FBSD50_ENV)
734 afs_pioctl(td, args, retval)
744 } *uap = (struct a *) args;
746 AFS_STATCNT(afs_pioctl);
747 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, td->td_ucred));
750 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
752 afs_pioctl(p, args, retval)
762 } *uap = (struct a *) args;
764 AFS_STATCNT(afs_pioctl);
765 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
770 /* macro to avoid adding any more #ifdef's to pioctl code. */
771 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
772 #define PIOCTL_FREE_CRED() crfree(credp)
774 #define PIOCTL_FREE_CRED()
779 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
781 struct AFS_UCRED *credp;
783 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
784 afs_syscall_pioctl(path, com, cmarg, follow, credp)
785 struct AFS_UCRED *credp;
787 afs_syscall_pioctl(path, com, cmarg, follow)
795 struct afs_ioctl data;
796 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
797 register afs_int32 code = 0;
803 struct ucred *credp = crref(); /* don't free until done! */
805 #ifdef AFS_LINUX22_ENV
806 cred_t *credp = crref(); /* don't free until done! */
810 AFS_STATCNT(afs_syscall_pioctl);
811 if (follow) follow = 1; /* compat. with old venus */
812 code = copyin_afs_ioctl(cmarg, &data);
815 #if defined(KERNEL_HAVE_UERROR)
820 if ((com & 0xff) == PSetClientContext) {
821 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
822 return EINVAL; /* Not handling these yet. */
823 #elif defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
824 code = HandleClientContext(&data, &com, &foreigncreds, credp);
826 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
830 crfree(foreigncreds);
833 #if defined(KERNEL_HAVE_UERROR)
834 return (setuerror(code), code);
840 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
843 * We could have done without temporary setting the u.u_cred below
844 * (foreigncreds could be passed as param the pioctl modules)
845 * but calls such as afs_osi_suser() doesn't allow that since it
846 * references u.u_cred directly. We could, of course, do something
847 * like afs_osi_suser(cred) which, I think, is better since it
848 * generalizes and supports multi cred environments...
852 credp = foreigncreds;
855 tmpcred = crref(); /* XXX */
858 #if defined(AFS_HPUX101_ENV)
859 tmpcred = p_cred(u.u_procp);
860 set_p_cred(u.u_procp, foreigncreds);
863 tmpcred = OSI_GET_CURRENT_CRED();
864 OSI_SET_CURRENT_CRED(foreigncreds);
867 tmpcred = osi_curcred();
868 osi_curcred() = foreigncreds;
871 u.u_cred = foreigncreds;
872 #endif /* AFS_SGI64_ENV */
873 #endif /* AFS_HPUX101_ENV */
879 if ((com & 0xff) == 15) {
880 /* special case prefetch so entire pathname eval occurs in helper process.
881 otherwise, the pioctl call is essentially useless */
882 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
883 code = Prefetch(path, &data, follow,
884 foreigncreds ? foreigncreds : credp);
886 code = Prefetch(path, &data, follow, osi_curcred());
889 #if defined(KERNEL_HAVE_UERROR)
897 code = lookupname(path, USR, follow, NULL, &vp,
898 foreigncreds ? foreigncreds : credp);
900 #ifdef AFS_LINUX22_ENV
901 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
903 vp = (struct vnode *)dp->d_inode;
905 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
906 #endif /* AFS_LINUX22_ENV */
907 #endif /* AFS_AIX41_ENV */
911 #if defined(KERNEL_HAVE_UERROR)
919 /* now make the call if we were passed no file, or were passed an AFS file */
920 if (!vp || IsAfsVnode(vp)) {
922 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
923 * So, we must test in this part of the code. Also, must arrange to
924 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
925 * we hold gnodes, whose references hold our vcache entries.
928 gp = vp; /* remember for "put" */
929 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
934 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
938 struct ucred *cred1, *cred2;
941 cred1 = cred2 = foreigncreds;
943 cred1 = cred2 = credp;
945 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
946 if (cred1 != cred2) {
947 /* something changed the creds */
952 #if defined(AFS_HPUX101_ENV)
954 struct ucred *cred = p_cred(u.u_procp);
955 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
961 credp = OSI_GET_CURRENT_CRED();
962 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
965 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
966 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
968 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
970 #endif /* AFS_SGI_ENV */
971 #endif /* AFS_HPUX101_ENV */
972 #endif /* AFS_AIX41_ENV */
973 #endif /* AFS_SUN5_ENV */
975 #if defined(KERNEL_HAVE_UERROR)
978 code = EINVAL; /* not in /afs */
989 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
992 crset(tmpcred); /* restore original credentials */
994 #if defined(AFS_HPUX101_ENV)
995 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
996 #elif defined(AFS_SGI_ENV)
997 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
998 #elif !defined(AFS_SUN5_ENV)
999 osi_curcred() = tmpcred; /* restore original credentials */
1000 #endif /* AFS_HPUX101_ENV */
1001 crfree(foreigncreds);
1004 #endif /* LINUX, DARWIN, FBSD */
1006 #ifdef AFS_LINUX22_ENV
1009 AFS_RELE(vp); /* put vnode back */
1013 #if defined(KERNEL_HAVE_UERROR)
1016 return (getuerror());
1023 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
1024 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1027 struct vrequest treq;
1028 register afs_int32 code;
1029 register afs_int32 function, device;
1030 afs_int32 inSize, outSize;
1031 char *inData, *outData;
1032 int (*(*pioctlSw))();
1034 struct afs_fakestat_state fakestate;
1036 avc = avp ? VTOAFS(avp) : NULL;
1037 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1038 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1039 AFS_STATCNT(HandlePioctl);
1040 if ((code = afs_InitReq(&treq, *acred))) return code;
1041 afs_InitFakeStat(&fakestate);
1043 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1045 afs_PutFakeStat(&fakestate);
1049 device = (acom & 0xff00) >> 8;
1051 case 'V': /* Original pioctls */
1052 pioctlSw = VpioctlSw;
1053 pioctlSwSize = sizeof(VpioctlSw);
1055 case 'C': /* Coordinated/common pioctls */
1056 pioctlSw = CpioctlSw;
1057 pioctlSwSize = sizeof(CpioctlSw);
1060 afs_PutFakeStat(&fakestate);
1063 function = acom & 0xff;
1064 if (function >= (pioctlSwSize / sizeof(char *))) {
1065 afs_PutFakeStat(&fakestate);
1066 return EINVAL; /* out of range */
1068 inSize = ablob->in_size;
1069 if (inSize >= PIGGYSIZE) return E2BIG;
1070 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1072 AFS_COPYIN(ablob->in, inData, inSize, code);
1073 inData[inSize]='\0';
1077 osi_FreeLargeSpace(inData);
1078 afs_PutFakeStat(&fakestate);
1081 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1083 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1084 osi_FreeLargeSpace(inData);
1085 if (code == 0 && ablob->out_size > 0) {
1086 if (outSize > ablob->out_size) outSize = ablob->out_size;
1087 if (outSize >= PIGGYSIZE) code = E2BIG;
1089 outData[outSize]='\0';
1090 AFS_COPYOUT(outData, ablob->out, outSize, code);
1093 osi_FreeLargeSpace(outData);
1094 afs_PutFakeStat(&fakestate);
1095 return afs_CheckCode(code, &treq, 41);
1098 DECL_PIOCTL(PGetFID)
1100 AFS_STATCNT(PGetFID);
1101 if (!avc) return EINVAL;
1102 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1103 *aoutSize = sizeof(struct VenusFid);
1107 DECL_PIOCTL(PSetAcl)
1109 register afs_int32 code;
1111 struct AFSOpaque acl;
1112 struct AFSVolSync tsync;
1113 struct AFSFetchStatus OutStatus;
1116 AFS_STATCNT(PSetAcl);
1119 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1122 acl.AFSOpaque_val = ain;
1124 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1126 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1128 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1129 &acl, &OutStatus, &tsync);
1135 (afs_Analyze(tconn, code, &avc->fid, areq,
1136 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1138 /* now we've forgotten all of the access info */
1139 ObtainWriteLock(&afs_xcbhash, 455);
1141 afs_DequeueCallback(avc);
1142 avc->states &= ~(CStatd | CUnique);
1143 ReleaseWriteLock(&afs_xcbhash);
1144 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1145 osi_dnlc_purgedp(avc);
1149 int afs_defaultAsynchrony = 0;
1151 DECL_PIOCTL(PStoreBehind)
1154 struct sbstruct *sbr;
1156 sbr = (struct sbstruct *)ain;
1157 if (sbr->sb_default != -1) {
1158 if (afs_osi_suser(*acred))
1159 afs_defaultAsynchrony = sbr->sb_default;
1163 if (avc && (sbr->sb_thisfile != -1)) {
1164 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1165 areq, DONT_CHECK_MODE_BITS))
1166 avc->asynchrony = sbr->sb_thisfile;
1170 *aoutSize = sizeof(struct sbstruct);
1171 sbr = (struct sbstruct *)aout;
1172 sbr->sb_default = afs_defaultAsynchrony;
1174 sbr->sb_thisfile = avc->asynchrony;
1180 DECL_PIOCTL(PGCPAGs)
1182 if (!afs_osi_suser(*acred)) {
1185 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1189 DECL_PIOCTL(PGetAcl)
1191 struct AFSOpaque acl;
1192 struct AFSVolSync tsync;
1193 struct AFSFetchStatus OutStatus;
1199 AFS_STATCNT(PGetAcl);
1200 if (!avc) return EINVAL;
1201 Fid.Volume = avc->fid.Fid.Volume;
1202 Fid.Vnode = avc->fid.Fid.Vnode;
1203 Fid.Unique = avc->fid.Fid.Unique;
1204 if (avc->states & CForeign) {
1206 * For a dfs xlator acl we have a special hack so that the
1207 * xlator will distinguish which type of acl will return. So
1208 * we currently use the top 2-bytes (vals 0-4) to tell which
1209 * type of acl to bring back. Horrible hack but this will
1210 * cause the least number of changes to code size and interfaces.
1212 if (Fid.Vnode & 0xc0000000)
1214 Fid.Vnode |= (ainSize << 30);
1216 acl.AFSOpaque_val = aout;
1218 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1221 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1223 code = RXAFS_FetchACL(tconn->id, &Fid,
1224 &acl, &OutStatus, &tsync);
1230 (afs_Analyze(tconn, code, &avc->fid, areq,
1231 AFS_STATS_FS_RPCIDX_FETCHACL,
1232 SHARED_LOCK, NULL));
1235 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1248 AFS_STATCNT(PBogus);
1252 DECL_PIOCTL(PGetFileCell)
1254 register struct cell *tcell;
1256 AFS_STATCNT(PGetFileCell);
1257 if (!avc) return EINVAL;
1258 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1259 if (!tcell) return ESRCH;
1260 strcpy(aout, tcell->cellName);
1261 afs_PutCell(tcell, READ_LOCK);
1262 *aoutSize = strlen(aout) + 1;
1266 DECL_PIOCTL(PGetWSCell)
1268 struct cell *tcell = NULL;
1270 AFS_STATCNT(PGetWSCell);
1271 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1272 return EIO; /* Inappropriate ioctl for device */
1274 tcell = afs_GetPrimaryCell(READ_LOCK);
1275 if (!tcell) /* no primary cell? */
1277 strcpy(aout, tcell->cellName);
1278 *aoutSize = strlen(aout) + 1;
1279 afs_PutCell(tcell, READ_LOCK);
1283 DECL_PIOCTL(PGetUserCell)
1285 register afs_int32 i;
1286 register struct unixuser *tu;
1287 register struct cell *tcell;
1289 AFS_STATCNT(PGetUserCell);
1290 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1291 return EIO; /* Inappropriate ioctl for device */
1293 /* return the cell name of the primary cell for this user */
1294 i = UHash(areq->uid);
1295 ObtainWriteLock(&afs_xuser,224);
1296 for(tu = afs_users[i]; tu; tu = tu->next) {
1297 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1299 ReleaseWriteLock(&afs_xuser);
1304 tcell = afs_GetCell(tu->cell, READ_LOCK);
1305 afs_PutUser(tu, WRITE_LOCK);
1306 if (!tcell) return ESRCH;
1308 strcpy(aout, tcell->cellName);
1309 afs_PutCell(tcell, READ_LOCK);
1310 *aoutSize = strlen(aout)+1; /* 1 for the null */
1314 ReleaseWriteLock(&afs_xuser);
1321 DECL_PIOCTL(PSetTokens)
1324 register struct unixuser *tu;
1325 struct ClearToken clear;
1326 register struct cell *tcell;
1329 struct vrequest treq;
1330 afs_int32 flag, set_parent_pag = 0;
1332 AFS_STATCNT(PSetTokens);
1333 if (!afs_resourceinit_flag) {
1336 memcpy((char *)&i, ain, sizeof(afs_int32));
1337 ain += sizeof(afs_int32);
1338 stp = ain; /* remember where the ticket is */
1339 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1340 if (i > MAXKTCTICKETLEN) return EINVAL;
1342 ain += i; /* skip over ticket */
1343 memcpy((char *)&i, ain, sizeof(afs_int32));
1344 ain += sizeof(afs_int32);
1345 if (i != sizeof(struct ClearToken)) {
1348 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1349 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1350 ain += sizeof(struct ClearToken);
1351 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1352 /* still stuff left? we've got primary flag and cell name. Set these */
1353 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1354 ain += sizeof(afs_int32); /* skip id field */
1355 /* rest is cell name, look it up */
1356 /* some versions of gcc appear to need != 0 in order to get this right */
1357 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1361 tcell = afs_GetCellByName(ain, READ_LOCK);
1362 if (!tcell) goto nocell;
1365 /* default to primary cell, primary id */
1366 flag = 1; /* primary id */
1367 tcell = afs_GetPrimaryCell(READ_LOCK);
1368 if (!tcell) goto nocell;
1371 afs_PutCell(tcell, READ_LOCK);
1372 if (set_parent_pag) {
1374 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1375 #if defined(AFS_DARWIN_ENV)
1376 struct proc *p = current_proc(); /* XXX */
1378 struct proc *p = curproc; /* XXX */
1380 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1381 p->p_pid, p->p_comm);
1382 if (!setpag(p, acred, -1, &pag, 1)) {
1385 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1387 if (!setpag(acred, -1, &pag, 1)) {
1390 afs_InitReq(&treq, *acred);
1394 /* now we just set the tokens */
1395 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1396 tu->vid = clear.ViceId;
1397 if (tu->stp != NULL) {
1398 afs_osi_Free(tu->stp, tu->stLen);
1400 tu->stp = (char *) afs_osi_Alloc(stLen);
1402 memcpy(tu->stp, stp, stLen);
1405 afs_stats_cmfullperf.authent.TicketUpdates++;
1406 afs_ComputePAGStats();
1407 #endif /* AFS_NOSTATS */
1408 tu->states |= UHasTokens;
1409 tu->states &= ~UTokensBad;
1410 afs_SetPrimary(tu, flag);
1411 tu->tokenTime =osi_Time();
1412 afs_ResetUserConns(tu);
1413 afs_PutUser(tu, WRITE_LOCK);
1428 DECL_PIOCTL(PGetVolumeStatus)
1431 char offLineMsg[256];
1433 register struct conn *tc;
1434 register afs_int32 code;
1435 struct VolumeStatus volstat;
1437 char *Name, *OfflineMsg, *MOTD;
1440 AFS_STATCNT(PGetVolumeStatus);
1441 if (!avc) return EINVAL;
1443 OfflineMsg = offLineMsg;
1446 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1448 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1450 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1451 &Name, &OfflineMsg, &MOTD);
1457 (afs_Analyze(tc, code, &avc->fid, areq,
1458 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1459 SHARED_LOCK, NULL));
1461 if (code) return code;
1462 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1464 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1465 cp += sizeof(VolumeStatus);
1466 strcpy(cp, volName);
1467 cp += strlen(volName)+1;
1468 strcpy(cp, offLineMsg);
1469 cp += strlen(offLineMsg)+1;
1471 cp += strlen(motd)+1;
1472 *aoutSize = (cp - aout);
1476 DECL_PIOCTL(PSetVolumeStatus)
1479 char offLineMsg[256];
1481 register struct conn *tc;
1482 register afs_int32 code;
1483 struct AFSFetchVolumeStatus volstat;
1484 struct AFSStoreVolumeStatus storeStat;
1485 register struct volume *tvp;
1489 AFS_STATCNT(PSetVolumeStatus);
1490 if (!avc) return EINVAL;
1492 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1494 if (tvp->states & (VRO | VBackup)) {
1495 afs_PutVolume(tvp, READ_LOCK);
1498 afs_PutVolume(tvp, READ_LOCK);
1501 /* Copy the junk out, using cp as a roving pointer. */
1503 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1504 cp += sizeof(AFSFetchVolumeStatus);
1505 if (strlen(cp) >= sizeof(volName))
1507 strcpy(volName, cp);
1508 cp += strlen(volName)+1;
1509 if (strlen(cp) >= sizeof(offLineMsg))
1511 strcpy(offLineMsg, cp);
1512 cp += strlen(offLineMsg)+1;
1513 if (strlen(cp) >= sizeof(motd))
1517 if (volstat.MinQuota != -1) {
1518 storeStat.MinQuota = volstat.MinQuota;
1519 storeStat.Mask |= AFS_SETMINQUOTA;
1521 if (volstat.MaxQuota != -1) {
1522 storeStat.MaxQuota = volstat.MaxQuota;
1523 storeStat.Mask |= AFS_SETMAXQUOTA;
1526 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1528 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1530 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1531 &storeStat, volName, offLineMsg, motd);
1537 (afs_Analyze(tc, code, &avc->fid, areq,
1538 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1539 SHARED_LOCK, NULL));
1541 if (code) return code;
1542 /* we are sending parms back to make compat. with prev system. should
1543 change interface later to not ask for current status, just set new status */
1545 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1546 cp += sizeof(VolumeStatus);
1547 strcpy(cp, volName);
1548 cp += strlen(volName)+1;
1549 strcpy(cp, offLineMsg);
1550 cp += strlen(offLineMsg)+1;
1552 cp += strlen(motd)+1;
1553 *aoutSize = cp - aout;
1559 AFS_STATCNT(PFlush);
1560 if (!avc) return EINVAL;
1561 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1562 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1564 ObtainWriteLock(&avc->lock,225);
1565 ObtainWriteLock(&afs_xcbhash, 456);
1566 afs_DequeueCallback(avc);
1567 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1568 ReleaseWriteLock(&afs_xcbhash);
1569 /* now find the disk cache entries */
1570 afs_TryToSmush(avc, *acred, 1);
1571 osi_dnlc_purgedp(avc);
1572 afs_symhint_inval(avc);
1573 if (avc->linkData && !(avc->states & CCore)) {
1574 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1575 avc->linkData = NULL;
1577 ReleaseWriteLock(&avc->lock);
1578 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1579 afs_BozonUnlock(&avc->pvnLock, avc);
1584 DECL_PIOCTL(PNewStatMount)
1586 register afs_int32 code;
1587 register struct vcache *tvc;
1588 register struct dcache *tdc;
1589 struct VenusFid tfid;
1591 struct sysname_info sysState;
1592 afs_size_t offset, len;
1594 AFS_STATCNT(PNewStatMount);
1595 if (!avc) return EINVAL;
1596 code = afs_VerifyVCache(avc, areq);
1597 if (code) return code;
1598 if (vType(avc) != VDIR) {
1601 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1602 if (!tdc) return ENOENT;
1603 Check_AtSys(avc, ain, &sysState, areq);
1604 ObtainReadLock(&tdc->lock);
1606 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1607 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1608 ReleaseReadLock(&tdc->lock);
1609 afs_PutDCache(tdc); /* we're done with the data */
1610 bufp = sysState.name;
1614 tfid.Cell = avc->fid.Cell;
1615 tfid.Fid.Volume = avc->fid.Fid.Volume;
1616 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1617 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1619 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1625 if (tvc->mvstat != 1) {
1630 ObtainWriteLock(&tvc->lock,226);
1631 code = afs_HandleLink(tvc, areq);
1633 if (tvc->linkData) {
1634 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1637 /* we have the data */
1638 strcpy(aout, tvc->linkData);
1639 *aoutSize = strlen(tvc->linkData)+1;
1644 ReleaseWriteLock(&tvc->lock);
1647 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1651 DECL_PIOCTL(PGetTokens)
1653 register struct cell *tcell;
1654 register afs_int32 i;
1655 register struct unixuser *tu;
1660 AFS_STATCNT(PGetTokens);
1661 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1662 return EIO; /* Inappropriate ioctl for device */
1664 /* weird interface. If input parameter is present, it is an integer and
1665 we're supposed to return the parm'th tokens for this unix uid.
1666 If not present, we just return tokens for cell 1.
1667 If counter out of bounds, return EDOM.
1668 If no tokens for the particular cell, return ENOTCONN.
1669 Also, if this mysterious parm is present, we return, along with the
1670 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1671 at the end, in that order.
1673 if ((newStyle = (ainSize > 0))) {
1674 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1676 i = UHash(areq->uid);
1677 ObtainReadLock(&afs_xuser);
1678 for(tu = afs_users[i]; tu; tu=tu->next) {
1680 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1681 if (iterator-- == 0) break; /* are we done yet? */
1685 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1690 * No need to hold a read lock on each user entry
1694 ReleaseReadLock(&afs_xuser);
1699 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1700 tu->states |= (UTokensBad | UNeedsReset);
1701 afs_PutUser(tu, READ_LOCK);
1704 /* use iterator for temp */
1706 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1707 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1708 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1709 cp += sizeof(afs_int32);
1710 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1712 iterator = sizeof(struct ClearToken);
1713 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1714 cp += sizeof(afs_int32);
1715 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1716 cp += sizeof(struct ClearToken);
1718 /* put out primary id and cell name, too */
1719 iterator = (tu->states & UPrimary ? 1 : 0);
1720 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1721 cp += sizeof(afs_int32);
1722 tcell = afs_GetCell(tu->cell, READ_LOCK);
1724 strcpy(cp, tcell->cellName);
1725 cp += strlen(tcell->cellName)+1;
1726 afs_PutCell(tcell, READ_LOCK);
1730 *aoutSize = cp - aout;
1731 afs_PutUser(tu, READ_LOCK);
1737 register afs_int32 i;
1738 register struct unixuser *tu;
1740 AFS_STATCNT(PUnlog);
1741 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1742 return EIO; /* Inappropriate ioctl for device */
1744 i = UHash(areq->uid);
1745 ObtainWriteLock(&afs_xuser,227);
1746 for(tu=afs_users[i]; tu; tu=tu->next) {
1747 if (tu->uid == areq->uid) {
1749 tu->states &= ~UHasTokens;
1750 /* security is not having to say you're sorry */
1751 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1753 ReleaseWriteLock(&afs_xuser);
1754 /* We have to drop the lock over the call to afs_ResetUserConns, since
1755 * it obtains the afs_xvcache lock. We could also keep the lock, and
1756 * modify ResetUserConns to take parm saying we obtained the lock
1757 * already, but that is overkill. By keeping the "tu" pointer
1758 * held over the released lock, we guarantee that we won't lose our
1759 * place, and that we'll pass over every user conn that existed when
1760 * we began this call.
1762 afs_ResetUserConns(tu);
1764 ObtainWriteLock(&afs_xuser,228);
1766 /* set the expire times to 0, causes
1767 * afs_GCUserData to remove this entry
1769 tu->ct.EndTimestamp = 0;
1771 #endif /* UKERNEL */
1774 ReleaseWriteLock(&afs_xuser);
1778 DECL_PIOCTL(PMariner)
1780 afs_int32 newHostAddr;
1781 afs_int32 oldHostAddr;
1783 AFS_STATCNT(PMariner);
1785 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1787 oldHostAddr = 0xffffffff; /* disabled */
1789 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1790 if (newHostAddr == 0xffffffff) {
1791 /* disable mariner operations */
1794 else if (newHostAddr) {
1796 afs_marinerHost = newHostAddr;
1798 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1799 *aoutSize = sizeof(afs_int32);
1803 DECL_PIOCTL(PCheckServers)
1805 register char *cp = 0;
1807 register struct server *ts;
1808 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1810 struct chservinfo *pcheck;
1812 AFS_STATCNT(PCheckServers);
1814 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1815 return EIO; /* Inappropriate ioctl for device */
1817 if (*lp == 0x12345678) { /* For afs3.3 version */
1818 pcheck=(struct chservinfo *)ain;
1819 if (pcheck->tinterval >= 0) {
1821 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1822 *aoutSize = sizeof(afs_int32);
1823 if (pcheck->tinterval > 0) {
1824 if (!afs_osi_suser(*acred))
1826 PROBE_INTERVAL=pcheck->tinterval;
1832 temp=pcheck->tflags;
1833 cp = pcheck->tbuffer;
1834 } else { /* For pre afs3.3 versions */
1835 memcpy((char *)&temp, ain, sizeof(afs_int32));
1836 cp = ain+sizeof(afs_int32);
1837 if (ainSize > sizeof(afs_int32))
1842 * 1: fast check, don't contact servers.
1843 * 2: local cell only.
1846 /* have cell name, too */
1847 cellp = afs_GetCellByName(cp, READ_LOCK);
1848 if (!cellp) return ENOENT;
1851 if (!cellp && (temp & 2)) {
1852 /* use local cell */
1853 cellp = afs_GetPrimaryCell(READ_LOCK);
1855 if (!(temp & 1)) { /* if not fast, call server checker routine */
1856 afs_CheckServers(1, cellp); /* check down servers */
1857 afs_CheckServers(0, cellp); /* check up servers */
1859 /* now return the current down server list */
1861 ObtainReadLock(&afs_xserver);
1862 for(i=0;i<NSERVERS;i++) {
1863 for(ts = afs_servers[i]; ts; ts=ts->next) {
1864 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1865 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1866 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1867 cp += sizeof(afs_int32);
1871 ReleaseReadLock(&afs_xserver);
1872 if (cellp) afs_PutCell(cellp, READ_LOCK);
1873 *aoutSize = cp - aout;
1877 DECL_PIOCTL(PCheckVolNames)
1879 AFS_STATCNT(PCheckVolNames);
1880 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1881 return EIO; /* Inappropriate ioctl for device */
1883 afs_CheckRootVolume();
1884 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1885 AFS_VOLCHECK_EXPIRED |
1887 AFS_VOLCHECK_MTPTS);
1891 DECL_PIOCTL(PCheckAuth)
1896 struct unixuser *tu;
1899 AFS_STATCNT(PCheckAuth);
1900 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1901 return EIO; /* Inappropriate ioctl for device */
1904 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1905 if (!tu) retValue = EACCES;
1907 /* we have a user */
1908 ObtainReadLock(&afs_xsrvAddr);
1909 ObtainReadLock(&afs_xconn);
1911 /* any tokens set? */
1912 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1913 /* all connections in cell 1 working? */
1914 for(i=0;i<NSERVERS;i++) {
1915 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1916 for (tc = sa->conns; tc; tc=tc->next) {
1917 if (tc->user == tu && (tu->states & UTokensBad))
1922 ReleaseReadLock(&afs_xsrvAddr);
1923 ReleaseReadLock(&afs_xconn);
1924 afs_PutUser(tu, READ_LOCK);
1926 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1927 *aoutSize = sizeof(afs_int32);
1931 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1934 register afs_int32 code;
1935 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1941 AFS_STATCNT(Prefetch);
1942 if (!apath) return EINVAL;
1943 tp = osi_AllocLargeSpace(1024);
1944 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1946 osi_FreeLargeSpace(tp);
1949 if (afs_BBusy()) { /* do this as late as possible */
1950 osi_FreeLargeSpace(tp);
1951 return EWOULDBLOCK; /* pretty close */
1953 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1954 (afs_size_t) 0, (afs_size_t) 0, tp);
1958 DECL_PIOCTL(PFindVolume)
1960 register struct volume *tvp;
1961 register struct server *ts;
1962 register afs_int32 i;
1965 AFS_STATCNT(PFindVolume);
1966 if (!avc) return EINVAL;
1967 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1970 for(i=0;i<MAXHOSTS;i++) {
1971 ts = tvp->serverHost[i];
1973 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1974 cp += sizeof(afs_int32);
1977 /* still room for terminating NULL, add it on */
1978 ainSize = 0; /* reuse vbl */
1979 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
1980 cp += sizeof(afs_int32);
1982 *aoutSize = cp - aout;
1983 afs_PutVolume(tvp, READ_LOCK);
1989 DECL_PIOCTL(PViceAccess)
1991 register afs_int32 code;
1994 AFS_STATCNT(PViceAccess);
1995 if (!avc) return EINVAL;
1996 code = afs_VerifyVCache(avc, areq);
1997 if (code) return code;
1998 memcpy((char *)&temp, ain, sizeof(afs_int32));
1999 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2004 DECL_PIOCTL(PSetCacheSize)
2009 AFS_STATCNT(PSetCacheSize);
2010 if (!afs_osi_suser(*acred))
2012 /* too many things are setup initially in mem cache version */
2013 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2014 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2015 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2017 if (newValue < afs_min_cache)
2018 afs_cacheBlocks = afs_min_cache;
2020 afs_cacheBlocks = newValue;
2022 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2023 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2024 afs_MaybeWakeupTruncateDaemon();
2025 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2026 afs_osi_Wait(1000, 0, 0);
2027 afs_MaybeWakeupTruncateDaemon();
2032 #define MAXGCSTATS 16
2033 DECL_PIOCTL(PGetCacheSize)
2035 afs_int32 results[MAXGCSTATS];
2037 AFS_STATCNT(PGetCacheSize);
2038 memset((char *)results, 0, sizeof(results));
2039 results[0] = afs_cacheBlocks;
2040 results[1] = afs_blocksUsed;
2041 memcpy(aout, (char *)results, sizeof(results));
2042 *aoutSize = sizeof(results);
2046 DECL_PIOCTL(PRemoveCallBack)
2048 register struct conn *tc;
2049 register afs_int32 code = 0;
2050 struct AFSCallBack CallBacks_Array[1];
2051 struct AFSCBFids theFids;
2052 struct AFSCBs theCBs;
2055 AFS_STATCNT(PRemoveCallBack);
2056 if (!avc) return EINVAL;
2057 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2058 ObtainWriteLock(&avc->lock,229);
2059 theFids.AFSCBFids_len = 1;
2060 theCBs.AFSCBs_len = 1;
2061 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2062 theCBs.AFSCBs_val = CallBacks_Array;
2063 CallBacks_Array[0].CallBackType = CB_DROPPED;
2064 if (avc->callback) {
2066 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2068 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2070 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2074 /* don't set code on failure since we wouldn't use it */
2076 (afs_Analyze(tc, code, &avc->fid, areq,
2077 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2078 SHARED_LOCK, NULL));
2080 ObtainWriteLock(&afs_xcbhash, 457);
2081 afs_DequeueCallback(avc);
2083 avc->states &= ~(CStatd | CUnique);
2084 ReleaseWriteLock(&afs_xcbhash);
2085 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2086 osi_dnlc_purgedp(avc);
2088 ReleaseWriteLock(&avc->lock);
2092 DECL_PIOCTL(PNewCell)
2094 /* create a new cell */
2095 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2096 char *newcell=0, *linkedcell=0, *tp= ain;
2097 register afs_int32 code, linkedstate=0, ls;
2098 u_short fsport = 0, vlport = 0;
2101 AFS_STATCNT(PNewCell);
2102 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2103 return EIO; /* Inappropriate ioctl for device */
2105 if (!afs_osi_suser(*acred))
2108 memcpy((char *)&magic, tp, sizeof(afs_int32));
2109 tp += sizeof(afs_int32);
2110 if (magic != 0x12345678)
2113 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2114 * server addresses while the 3.5 fs newcell command passes
2115 * MAXHOSTS. To figure out which is which, check if the cellname
2118 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2119 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2121 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2122 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2123 tp += (scount * sizeof(afs_int32));
2125 lp = (afs_int32 *)tp;
2128 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2129 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2130 tp += (3 * sizeof(afs_int32));
2132 if ((ls = *lp) & 1) {
2133 linkedcell = tp + strlen(newcell)+1;
2134 linkedstate |= CLinkedCell;
2137 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2138 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2143 DECL_PIOCTL(PNewAlias)
2145 /* create a new cell alias */
2147 register afs_int32 code;
2148 char *realName, *aliasName;
2150 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2151 return EIO; /* Inappropriate ioctl for device */
2153 if (!afs_osi_suser(*acred))
2157 tp += strlen(aliasName) + 1;
2160 code = afs_NewCellAlias(aliasName, realName);
2165 DECL_PIOCTL(PListCells)
2167 afs_int32 whichCell;
2168 register struct cell *tcell=0;
2169 register afs_int32 i;
2170 register char *cp, *tp = ain;
2172 AFS_STATCNT(PListCells);
2173 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2174 return EIO; /* Inappropriate ioctl for device */
2176 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2177 tp += sizeof(afs_int32);
2178 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2181 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2182 for(i=0;i<MAXCELLHOSTS;i++) {
2183 if (tcell->cellHosts[i] == 0) break;
2184 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2185 cp += sizeof(afs_int32);
2187 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2188 strcpy(cp, tcell->cellName);
2189 cp += strlen(tcell->cellName)+1;
2190 *aoutSize = cp - aout;
2191 afs_PutCell(tcell, READ_LOCK);
2193 if (tcell) return 0;
2197 DECL_PIOCTL(PListAliases)
2199 afs_int32 whichAlias;
2200 register struct cell_alias *tcalias=0;
2201 register char *cp, *tp = ain;
2203 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2204 return EIO; /* Inappropriate ioctl for device */
2205 if (ainSize < sizeof(afs_int32))
2208 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2209 tp += sizeof(afs_int32);
2211 tcalias = afs_GetCellAlias(whichAlias);
2214 strcpy(cp, tcalias->alias);
2215 cp += strlen(tcalias->alias)+1;
2216 strcpy(cp, tcalias->cell);
2217 cp += strlen(tcalias->cell)+1;
2218 *aoutSize = cp - aout;
2219 afs_PutCellAlias(tcalias);
2221 if (tcalias) return 0;
2225 DECL_PIOCTL(PRemoveMount)
2227 register afs_int32 code;
2229 struct sysname_info sysState;
2230 afs_size_t offset, len;
2231 register struct conn *tc;
2232 register struct dcache *tdc;
2233 register struct vcache *tvc;
2234 struct AFSFetchStatus OutDirStatus;
2235 struct VenusFid tfid;
2236 struct AFSVolSync tsync;
2240 /* "ain" is the name of the file in this dir to remove */
2242 AFS_STATCNT(PRemoveMount);
2243 if (!avc) return EINVAL;
2244 code = afs_VerifyVCache(avc, areq);
2245 if (code) return code;
2246 if (vType(avc) != VDIR) return ENOTDIR;
2248 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2249 if (!tdc) return ENOENT;
2250 Check_AtSys(avc, ain, &sysState, areq);
2251 ObtainReadLock(&tdc->lock);
2253 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2254 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2255 ReleaseReadLock(&tdc->lock);
2256 bufp = sysState.name;
2261 tfid.Cell = avc->fid.Cell;
2262 tfid.Fid.Volume = avc->fid.Fid.Volume;
2263 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2264 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2266 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2273 if (tvc->mvstat != 1) {
2279 ObtainWriteLock(&tvc->lock,230);
2280 code = afs_HandleLink(tvc, areq);
2282 if (tvc->linkData) {
2283 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2288 ReleaseWriteLock(&tvc->lock);
2289 osi_dnlc_purgedp(tvc);
2295 ObtainWriteLock(&avc->lock,231);
2296 osi_dnlc_remove(avc, bufp, tvc);
2298 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2300 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2302 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2303 bufp, &OutDirStatus, &tsync);
2309 (afs_Analyze(tc, code, &avc->fid, areq,
2310 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2311 SHARED_LOCK, NULL));
2314 if (tdc) afs_PutDCache(tdc);
2315 ReleaseWriteLock(&avc->lock);
2319 /* we have the thing in the cache */
2320 ObtainWriteLock(&tdc->lock, 661);
2321 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2322 /* we can do it locally */
2323 code = afs_dir_Delete(&tdc->f.inode, bufp);
2325 ZapDCE(tdc); /* surprise error -- invalid value */
2326 DZap(&tdc->f.inode);
2329 ReleaseWriteLock(&tdc->lock);
2330 afs_PutDCache(tdc); /* drop ref count */
2332 avc->states &= ~CUnique; /* For the dfs xlator */
2333 ReleaseWriteLock(&avc->lock);
2336 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2340 DECL_PIOCTL(PVenusLogging)
2342 return EINVAL; /* OBSOLETE */
2345 DECL_PIOCTL(PGetCellStatus)
2347 register struct cell *tcell;
2350 AFS_STATCNT(PGetCellStatus);
2351 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2352 return EIO; /* Inappropriate ioctl for device */
2354 tcell = afs_GetCellByName(ain, READ_LOCK);
2355 if (!tcell) return ENOENT;
2356 temp = tcell->states;
2357 afs_PutCell(tcell, READ_LOCK);
2358 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2359 *aoutSize = sizeof(afs_int32);
2363 DECL_PIOCTL(PSetCellStatus)
2365 register struct cell *tcell;
2368 if (!afs_osi_suser(*acred))
2370 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2371 return EIO; /* Inappropriate ioctl for device */
2373 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2374 if (!tcell) return ENOENT;
2375 memcpy((char *)&temp, ain, sizeof(afs_int32));
2377 tcell->states |= CNoSUID;
2379 tcell->states &= ~CNoSUID;
2380 afs_PutCell(tcell, WRITE_LOCK);
2384 DECL_PIOCTL(PFlushVolumeData)
2386 register afs_int32 i;
2387 register struct dcache *tdc;
2388 register struct vcache *tvc;
2389 register struct volume *tv;
2390 afs_int32 cell, volume;
2392 AFS_STATCNT(PFlushVolumeData);
2395 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2396 return EIO; /* Inappropriate ioctl for device */
2398 volume = avc->fid.Fid.Volume; /* who to zap */
2399 cell = avc->fid.Cell;
2402 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2403 * the vcaches associated with the volume.
2405 ObtainReadLock(&afs_xvcache);
2406 for(i = 0; i < VCSIZE; i++) {
2407 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2408 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2409 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2410 VN_HOLD(AFSTOV(tvc));
2412 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2418 ReleaseReadLock(&afs_xvcache);
2419 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2420 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2422 ObtainWriteLock(&tvc->lock,232);
2424 ObtainWriteLock(&afs_xcbhash, 458);
2425 afs_DequeueCallback(tvc);
2426 tvc->states &= ~(CStatd | CDirty);
2427 ReleaseWriteLock(&afs_xcbhash);
2428 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2429 osi_dnlc_purgedp(tvc);
2430 afs_TryToSmush(tvc, *acred, 1);
2431 ReleaseWriteLock(&tvc->lock);
2432 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2433 afs_BozonUnlock(&tvc->pvnLock, tvc);
2435 ObtainReadLock(&afs_xvcache);
2436 /* our tvc ptr is still good until now */
2441 ReleaseReadLock(&afs_xvcache);
2444 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2445 for(i=0;i<afs_cacheFiles;i++) {
2446 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2447 tdc = afs_GetDSlot(i, NULL);
2448 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2449 ReleaseReadLock(&tdc->tlock);
2450 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2451 if (! (afs_indexFlags[i] & IFDataMod)) {
2452 /* if the file is modified, but has a ref cnt of only 1, then
2453 someone probably has the file open and is writing into it.
2454 Better to skip flushing such a file, it will be brought back
2455 immediately on the next write anyway.
2457 If we *must* flush, then this code has to be rearranged to call
2458 afs_storeAllSegments() first */
2459 afs_FlushDCache(tdc);
2463 ReleaseReadLock(&tdc->tlock);
2465 afs_PutDCache(tdc); /* bumped by getdslot */
2467 MReleaseWriteLock(&afs_xdcache);
2469 ObtainReadLock(&afs_xvolume);
2470 for (i=0;i<NVOLS;i++) {
2471 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2472 if (tv->volume == volume) {
2473 afs_ResetVolumeInfo(tv);
2478 ReleaseReadLock(&afs_xvolume);
2480 /* probably, a user is doing this, probably, because things are screwed up.
2481 * maybe it's the dnlc's fault? */
2488 DECL_PIOCTL(PGetVnodeXStatus)
2490 register afs_int32 code;
2491 struct vcxstat stat;
2494 /* AFS_STATCNT(PGetVnodeXStatus); */
2495 if (!avc) return EINVAL;
2496 code = afs_VerifyVCache(avc, areq);
2497 if (code) return code;
2498 if (vType(avc) == VDIR)
2499 mode = PRSFS_LOOKUP;
2502 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2504 stat.fid = avc->fid;
2505 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2506 stat.lock = avc->lock;
2507 stat.parentVnode = avc->parentVnode;
2508 stat.parentUnique = avc->parentUnique;
2509 hset(stat.flushDV, avc->flushDV);
2510 hset(stat.mapDV, avc->mapDV);
2511 stat.truncPos = avc->truncPos;
2512 { /* just grab the first two - won't break anything... */
2513 struct axscache *ac;
2515 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2516 stat.randomUid[i] = ac->uid;
2517 stat.randomAccess[i] = ac->axess;
2520 stat.callback = afs_data_pointer_to_int32(avc->callback);
2521 stat.cbExpires = avc->cbExpires;
2522 stat.anyAccess = avc->anyAccess;
2523 stat.opens = avc->opens;
2524 stat.execsOrWriters = avc->execsOrWriters;
2525 stat.flockCount = avc->flockCount;
2526 stat.mvstat = avc->mvstat;
2527 stat.states = avc->states;
2528 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2529 *aoutSize = sizeof(struct vcxstat);
2534 /* We require root for local sysname changes, but not for remote */
2535 /* (since we don't really believe remote uids anyway) */
2536 /* outname[] shouldn't really be needed- this is left as an excercise */
2537 /* for the reader. */
2538 DECL_PIOCTL(PSetSysName)
2540 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2541 int setsysname, foundname=0;
2542 register struct afs_exporter *exporter;
2543 register struct unixuser *au;
2544 register afs_int32 pag, error;
2548 AFS_STATCNT(PSetSysName);
2549 if (!afs_globalVFS) {
2550 /* Afsd is NOT running; disable it */
2551 #if defined(KERNEL_HAVE_UERROR)
2552 return (setuerror(EINVAL), EINVAL);
2557 memset(inname, 0, MAXSYSNAME);
2558 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2559 ain += sizeof(afs_int32);
2563 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2565 for(cp = ain,count = 0;count < setsysname;count++) {
2566 /* won't go past end of ain since maxsysname*num < ain length */
2568 if (t >= MAXSYSNAME || t <= 0)
2570 /* check for names that can shoot us in the foot */
2571 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2577 /* inname gets first entry in case we're being a translater */
2579 memcpy(inname, ain, t+1); /* include terminating null */
2582 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2583 pag = PagInCred(*acred);
2585 return EINVAL; /* Better than panicing */
2587 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2588 return EINVAL; /* Better than panicing */
2590 if (!(exporter = au->exporter)) {
2591 afs_PutUser(au, READ_LOCK);
2592 return EINVAL; /* Better than panicing */
2594 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2596 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2598 afs_PutUser(au, READ_LOCK);
2603 afs_PutUser(au, READ_LOCK);
2606 /* Not xlating, so local case */
2607 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2608 if (!setsysname) { /* user just wants the info */
2609 strcpy(outname, afs_sysname);
2610 foundname = afs_sysnamecount;
2611 } else { /* Local guy; only root can change sysname */
2612 if (!afs_osi_suser(*acred))
2615 /* clear @sys entries from the dnlc, once afs_lookup can
2616 do lookups of @sys entries and thinks it can trust them */
2617 /* privs ok, store the entry, ... */
2618 strcpy(afs_sysname, inname);
2619 if (setsysname > 1) { /* ... or list */
2621 for(count=1; count < setsysname;++count) {
2622 if (!afs_sysnamelist[count])
2623 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2625 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2629 afs_sysnamecount = setsysname;
2633 cp = aout; /* not changing so report back the count and ... */
2634 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2635 cp += sizeof(afs_int32);
2637 strcpy(cp, outname); /* ... the entry, ... */
2638 cp += strlen(outname)+1;
2639 for(count=1; count < foundname; ++count) { /* ... or list. */
2640 /* Note: we don't support @sys lists for exporters */
2641 if (!afs_sysnamelist[count])
2642 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2643 t = strlen(afs_sysnamelist[count]);
2644 if (t >= MAXSYSNAME)
2645 osi_Panic("PSetSysName: sysname entry garbled\n");
2646 strcpy(cp, afs_sysnamelist[count]);
2650 *aoutSize = cp - aout;
2655 /* sequential search through the list of touched cells is not a good
2656 * long-term solution here. For small n, though, it should be just
2657 * fine. Should consider special-casing the local cell for large n.
2658 * Likewise for PSetSPrefs.
2660 * s - number of ids in array l[] -- NOT index of last id
2661 * l - array of cell ids which have volumes that need to be sorted
2662 * vlonly - sort vl servers or file servers?
2664 static void *ReSortCells_cb(struct cell *cell, void *arg)
2666 afs_int32 *p = (afs_int32 *) arg;
2667 afs_int32 *l = p + 1;
2670 for (i=0; i<s; i++) {
2671 if (l[i] == cell->cellNum) {
2672 ObtainWriteLock(&cell->lock, 690);
2673 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2674 ReleaseWriteLock(&cell->lock);
2681 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2689 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2691 memcpy(p+1, l, s * sizeof(afs_int32));
2692 afs_TraverseCells(&ReSortCells_cb, p);
2693 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2697 ObtainReadLock(&afs_xvolume);
2698 for (i= 0; i< NVOLS; i++) {
2699 for (j=afs_volumes[i];j;j=j->next) {
2701 if (j->cell == l[k]) {
2702 ObtainWriteLock(&j->lock,233);
2703 afs_SortServers(j->serverHost, MAXHOSTS);
2704 ReleaseWriteLock(&j->lock);
2709 ReleaseReadLock(&afs_xvolume);
2713 static int debugsetsp = 0;
2714 static int afs_setsprefs(sp, num, vlonly)
2717 unsigned int vlonly;
2720 int i,j,k,matches,touchedSize;
2721 struct server *srvr = NULL;
2722 afs_int32 touched[34];
2726 for (k=0; k < num; sp++, k++) {
2728 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2731 ObtainReadLock(&afs_xserver);
2733 i = SHash(sp->host.s_addr);
2734 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2735 if (sa->sa_ip == sp->host.s_addr) {
2737 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2738 || (sa->sa_portal == AFS_FSPORT);
2739 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2746 if (sa && matches) { /* found one! */
2748 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2750 sa->sa_iprank = sp->rank + afs_randomMod15();
2751 afs_SortOneServer(sa->server);
2754 /* if we don't know yet what cell it's in, this is moot */
2755 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2756 /* is it in our list of touched cells ? */ ;
2757 if (j < 0) { /* no, it's not */
2758 touched[touchedSize++] = srvr->cell->cellNum;
2759 if (touchedSize >= 32) { /* watch for ovrflow */
2760 ReleaseReadLock(&afs_xserver);
2761 ReSortCells(touchedSize, touched, vlonly);
2763 ObtainReadLock(&afs_xserver);
2769 ReleaseReadLock(&afs_xserver);
2770 /* if we didn't find one, start to create one. */
2771 /* Note that it doesn't have a cell yet... */
2773 afs_uint32 temp = sp->host.s_addr;
2774 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2775 WRITE_LOCK, (afsUUID *)0,0);
2776 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2777 afs_PutServer(srvr, WRITE_LOCK);
2779 } /* for all cited preferences */
2781 ReSortCells(touchedSize, touched, vlonly);
2785 /* Note that this may only be performed by the local root user.
2787 DECL_PIOCTL(PSetSPrefs)
2789 struct setspref *ssp;
2790 AFS_STATCNT(PSetSPrefs);
2792 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2793 return EIO; /* Inappropriate ioctl for device */
2795 if (!afs_osi_suser(*acred))
2798 if (ainSize < sizeof(struct setspref))
2801 ssp = (struct setspref *)ain;
2802 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2805 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2806 (ssp->flags & DBservers));
2810 DECL_PIOCTL(PSetSPrefs33)
2813 AFS_STATCNT(PSetSPrefs);
2814 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2815 return EIO; /* Inappropriate ioctl for device */
2818 if (!afs_osi_suser(*acred))
2821 sp = (struct spref *)ain;
2822 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2826 /* some notes on the following code...
2827 * in the hash table of server structs, all servers with the same IP address
2828 * will be on the same overflow chain.
2829 * This could be sped slightly in some circumstances by having it cache the
2830 * immediately previous slot in the hash table and some supporting information
2831 * Only reports file servers now.
2833 DECL_PIOCTL(PGetSPrefs)
2835 struct sprefrequest *spin; /* input */
2836 struct sprefinfo *spout; /* output */
2837 struct spref *srvout; /* one output component */
2838 int i,j; /* counters for hash table traversal */
2839 struct server *srvr; /* one of CM's server structs */
2841 int vlonly; /* just return vlservers ? */
2844 AFS_STATCNT(PGetSPrefs);
2845 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2846 return EIO; /* Inappropriate ioctl for device */
2849 if (ainSize < sizeof (struct sprefrequest_33)) {
2853 spin = ((struct sprefrequest *) ain);
2856 if (ainSize > sizeof (struct sprefrequest_33)) {
2857 vlonly = (spin->flags & DBservers);
2861 /* struct sprefinfo includes 1 server struct... that size gets added
2862 * in during the loop that follows.
2864 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2865 spout = (struct sprefinfo *) aout;
2866 spout->next_offset = spin->offset;
2867 spout->num_servers = 0;
2868 srvout = spout->servers;
2870 ObtainReadLock(&afs_xserver);
2871 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2872 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2873 if (spin->offset > (unsigned short)i) {
2874 continue; /* catch up to where we left off */
2876 spout->next_offset++;
2879 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2880 || (sa->sa_portal == AFS_FSPORT);
2882 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2883 /* only report ranks for vl servers */
2887 srvout->host.s_addr = sa->sa_ip;
2888 srvout->rank = sa->sa_iprank;
2889 *aoutSize += sizeof(struct spref);
2890 spout->num_servers++;
2893 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2894 ReleaseReadLock(&afs_xserver); /* no more room! */
2899 ReleaseReadLock(&afs_xserver);
2901 spout->next_offset = 0; /* start over from the beginning next time */
2905 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2906 int afs_NFSRootOnly = 1;
2907 DECL_PIOCTL(PExportAfs)
2909 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2910 register struct afs_exporter *exporter;
2912 AFS_STATCNT(PExportAfs);
2913 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2914 type = handleValue >> 24;
2919 exporter = exporter_find(type);
2921 export = handleValue & 3;
2922 changestate = handleValue & 0xff;
2923 smounts = (handleValue >> 2) & 3;
2924 pwsync = (handleValue >> 4) & 3;
2925 convmode = (handleValue >> 6) & 3;
2927 changestate = (handleValue >> 16) & 0x1;
2928 convmode = (handleValue >> 16) & 0x2;
2929 pwsync = (handleValue >> 16) & 0x4;
2930 smounts = (handleValue >> 16) & 0x8;
2931 export = handleValue & 0xff;
2934 /* Failed finding desired exporter; */
2938 handleValue = exporter->exp_states;
2939 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2940 *aoutSize = sizeof(afs_int32);
2942 if (!afs_osi_suser(*acred))
2943 return EACCES; /* Only superuser can do this */
2947 exporter->exp_states |= EXP_EXPORTED;
2949 exporter->exp_states &= ~EXP_EXPORTED;
2953 exporter->exp_states |= EXP_UNIXMODE;
2955 exporter->exp_states &= ~EXP_UNIXMODE;
2959 exporter->exp_states |= EXP_PWSYNC;
2961 exporter->exp_states &= ~EXP_PWSYNC;
2965 afs_NFSRootOnly = 0;
2966 exporter->exp_states |= EXP_SUBMOUNTS;
2968 afs_NFSRootOnly = 1;
2969 exporter->exp_states &= ~EXP_SUBMOUNTS;
2972 handleValue = exporter->exp_states;
2973 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2974 *aoutSize = sizeof(afs_int32);
2977 exporter->exp_states |= EXP_EXPORTED;
2979 exporter->exp_states &= ~EXP_EXPORTED;
2981 exporter->exp_states |= EXP_UNIXMODE;
2983 exporter->exp_states &= ~EXP_UNIXMODE;
2985 exporter->exp_states |= EXP_PWSYNC;
2987 exporter->exp_states &= ~EXP_PWSYNC;
2989 afs_NFSRootOnly = 0;
2990 exporter->exp_states |= EXP_SUBMOUNTS;
2992 afs_NFSRootOnly = 1;
2993 exporter->exp_states &= ~EXP_SUBMOUNTS;
3003 struct gaginfo *gagflags;
3005 if (!afs_osi_suser(*acred))
3008 gagflags = (struct gaginfo *) ain;
3009 afs_showflags = gagflags->showflags;
3015 DECL_PIOCTL(PTwiddleRx)
3017 struct rxparams *rxp;
3019 if (!afs_osi_suser(*acred))
3022 rxp = (struct rxparams *) ain;
3024 if (rxp->rx_initReceiveWindow)
3025 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3026 if (rxp->rx_maxReceiveWindow)
3027 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3028 if (rxp->rx_initSendWindow)
3029 rx_initSendWindow = rxp->rx_initSendWindow;
3030 if (rxp->rx_maxSendWindow)
3031 rx_maxSendWindow = rxp->rx_maxSendWindow;
3032 if (rxp->rxi_nSendFrags)
3033 rxi_nSendFrags = rxp->rxi_nSendFrags;
3034 if (rxp->rxi_nRecvFrags)
3035 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3036 if (rxp->rxi_OrphanFragSize)
3037 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3038 if (rxp->rx_maxReceiveSize)
3040 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3041 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3043 if (rxp->rx_MyMaxSendSize)
3044 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3049 DECL_PIOCTL(PGetInitParams)
3051 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3054 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3055 *aoutSize = sizeof(struct cm_initparams);
3059 #ifdef AFS_SGI65_ENV
3060 /* They took crget() from us, so fake it. */
3061 static cred_t *crget(void)
3064 cr = crdup(get_current_cred());
3065 memset((char*)cr, 0, sizeof(cred_t));
3066 #if CELL || CELL_PREPARE
3073 DECL_PIOCTL(PGetRxkcrypt)
3075 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3076 *aoutSize=sizeof(afs_int32);
3080 DECL_PIOCTL(PSetRxkcrypt)
3084 if (!afs_osi_suser(*acred))
3086 if (ainSize != sizeof(afs_int32) || ain == NULL)
3088 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3089 /* if new mappings added later this will need to be changed */
3090 if (tmpval != 0 && tmpval != 1)
3097 * Create new credentials to correspond to a remote user with given
3098 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3099 * provide pioctl (and other) services to foreign clients (i.e. nfs
3100 * clients) by using this call to `become' the client.
3103 #define PIOCTL_HEADER 6
3104 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3106 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3107 return EINVAL; /* NFS trans not supported for Ultrix */
3110 afs_uint32 hostaddr;
3111 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3112 struct afs_exporter *exporter, *outexporter;
3113 struct AFS_UCRED *newcred;
3114 struct unixuser *au;
3116 #if defined(AFS_SGIMP_ENV)
3117 osi_Assert(ISAFS_GLOCK());
3119 AFS_STATCNT(HandleClientContext);
3120 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3121 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3122 return EINVAL; /* Too small to be good */
3124 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3125 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3127 osi_FreeLargeSpace(inData);
3131 /* Extract information for remote user */
3132 hostaddr = *((afs_uint32 *)ain);
3133 ain += sizeof(hostaddr);
3134 uid = *((afs_uint32 *)ain);
3136 g0 = *((afs_uint32 *)ain);
3138 g1 = *((afs_uint32 *)ain);
3140 *com = *((afs_uint32 *)ain);
3141 ain += sizeof(afs_int32);
3142 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3145 * Of course, one must be root for most of these functions, but
3146 * we'll allow (for knfs) you to set things if the pag is 0 and
3147 * you're setting tokens or unlogging.
3150 if (!afs_osi_suser(credp)) {
3152 #ifndef AFS_SGI64_ENV
3153 /* Since SGI's suser() returns explicit failure after the call.. */
3157 /* check for acceptable opcodes for normal folks, which are, so far,
3158 * set tokens and unlog.
3160 if (i != 9 && i != 3 && i != 38 && i != 8) {
3161 osi_FreeLargeSpace(inData);
3166 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3167 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3168 osi_FreeLargeSpace(inData);
3171 * We map uid 0 to nobody to match the mapping that the nfs
3172 * server does and to ensure that the suser() calls in the afs
3173 * code fails for remote client roots.
3175 uid = afs_nobody; /* NFS_NOBODY == -2 */
3178 #ifdef AFS_AIX41_ENV
3181 newcred->cr_gid = RMTUSER_REQ;
3182 #ifdef AFS_AIX51_ENV
3183 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3184 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3186 newcred->cr_groups[0] = g0;
3187 newcred->cr_groups[1] = g1;
3190 newcred->cr_ngrps = 2;
3192 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3193 newcred->cr_ngroups = 2;
3195 for (i=2; i<NGROUPS; i++)
3196 newcred->cr_groups[i] = NOGROUP;
3199 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3200 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3202 if (!(exporter = exporter_find(exporter_type))) {
3203 /* Exporter wasn't initialized or an invalid exporter type */
3207 if (exporter->exp_states & EXP_PWSYNC) {
3208 if (uid != credp->cr_uid) {
3210 return ENOEXEC; /* XXX Find a better errno XXX */
3213 newcred->cr_uid = uid; /* Only temporary */
3214 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3215 /* The client's pag is the only unique identifier for it */
3216 newcred->cr_uid = pag;
3218 if (!code && *com == PSETPAG) {
3219 /* Special case for 'setpag' */
3220 afs_uint32 pagvalue = genpag();
3222 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3224 * Note that we leave the 'outexporter' struct held so it won't
3227 au->exporter = outexporter;
3228 if (ablob->out_size >= 4) {
3229 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3231 afs_PutUser(au, WRITE_LOCK);
3232 if (code) return code;
3233 return PSETPAG; /* Special return for setpag */
3235 EXP_RELE(outexporter);
3238 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3241 /* get all interface addresses of this client */
3243 DECL_PIOCTL(PGetCPrefs)
3245 struct sprefrequest *spin; /* input */
3246 struct sprefinfo *spout; /* output */
3247 struct spref *srvout; /* one output component */
3251 AFS_STATCNT(PGetCPrefs);
3252 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3253 return EIO; /* Inappropriate ioctl for device */
3255 if ( ainSize < sizeof (struct sprefrequest ))
3258 spin = (struct sprefrequest *) ain;
3259 spout = (struct sprefinfo *) aout;
3261 maxNumber = spin->num_servers; /* max addrs this time */
3262 srvout = spout->servers;
3264 ObtainReadLock(&afs_xinterface);
3266 /* copy out the client interface information from the
3267 ** kernel data structure "interface" to the output buffer
3269 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3270 && ( j< maxNumber) ; i++, j++, srvout++)
3271 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3273 spout->num_servers = j;
3274 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3276 if ( i >= afs_cb_interface.numberOfInterfaces )
3277 spout->next_offset = 0; /* start from beginning again */
3279 spout->next_offset = spin->offset + j;
3281 ReleaseReadLock(&afs_xinterface);
3285 DECL_PIOCTL(PSetCPrefs)
3287 struct setspref *sin;
3290 AFS_STATCNT(PSetCPrefs);
3291 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3292 return EIO; /* Inappropriate ioctl for device */
3294 sin = (struct setspref *)ain;
3296 if ( ainSize < sizeof(struct setspref) )
3298 #if 0 /* num_servers is unsigned */
3299 if ( sin->num_servers < 0 )
3302 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3305 ObtainWriteLock(&afs_xinterface, 412);
3306 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3307 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3308 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3310 ReleaseWriteLock(&afs_xinterface);
3314 DECL_PIOCTL(PFlushMount)
3316 register afs_int32 code;
3317 register struct vcache *tvc;
3318 register struct dcache *tdc;
3319 struct VenusFid tfid;
3321 struct sysname_info sysState;
3322 afs_size_t offset, len;
3324 AFS_STATCNT(PFlushMount);
3325 if (!avc) return EINVAL;
3326 code = afs_VerifyVCache(avc, areq);
3327 if (code) return code;
3328 if (vType(avc) != VDIR) {
3331 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3332 if (!tdc) return ENOENT;
3333 Check_AtSys(avc, ain, &sysState, areq);
3334 ObtainReadLock(&tdc->lock);
3336 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3337 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3338 ReleaseReadLock(&tdc->lock);
3339 afs_PutDCache(tdc); /* we're done with the data */
3340 bufp = sysState.name;
3344 tfid.Cell = avc->fid.Cell;
3345 tfid.Fid.Volume = avc->fid.Fid.Volume;
3346 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3347 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3349 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3355 if (tvc->mvstat != 1) {
3360 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3361 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3363 ObtainWriteLock(&tvc->lock,649);
3364 ObtainWriteLock(&afs_xcbhash, 650);
3365 afs_DequeueCallback(tvc);
3366 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3367 ReleaseWriteLock(&afs_xcbhash);
3368 /* now find the disk cache entries */
3369 afs_TryToSmush(tvc, *acred, 1);
3370 osi_dnlc_purgedp(tvc);
3371 afs_symhint_inval(tvc);
3372 if (tvc->linkData && !(tvc->states & CCore)) {
3373 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3374 tvc->linkData = NULL;
3376 ReleaseWriteLock(&tvc->lock);
3377 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3378 afs_BozonUnlock(&tvc->pvnLock, tvc);
3382 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3386 DECL_PIOCTL(PRxStatProc)
3391 if (!afs_osi_suser(*acred)) {
3395 if (ainSize != sizeof(afs_int32)) {
3399 memcpy((char *)&flags, ain, sizeof(afs_int32));
3400 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3404 if (flags & AFSCALL_RXSTATS_ENABLE) {
3405 rx_enableProcessRPCStats();
3407 if (flags & AFSCALL_RXSTATS_DISABLE) {
3408 rx_disableProcessRPCStats();
3410 if (flags & AFSCALL_RXSTATS_CLEAR) {
3411 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3419 DECL_PIOCTL(PRxStatPeer)
3424 if (!afs_osi_suser(*acred)) {
3428 if (ainSize != sizeof(afs_int32)) {
3432 memcpy((char *)&flags, ain, sizeof(afs_int32));
3433 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3437 if (flags & AFSCALL_RXSTATS_ENABLE) {
3438 rx_enablePeerRPCStats();
3440 if (flags & AFSCALL_RXSTATS_DISABLE) {
3441 rx_disablePeerRPCStats();
3443 if (flags & AFSCALL_RXSTATS_CLEAR) {
3444 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3451 DECL_PIOCTL(PPrefetchFromTape)
3453 register afs_int32 code, code1;
3456 struct rx_call *tcall;
3457 struct AFSVolSync tsync;
3458 struct AFSFetchStatus OutStatus;
3459 struct AFSCallBack CallBack;
3460 struct VenusFid tfid;
3464 AFS_STATCNT(PSetAcl);
3468 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3469 Fid = (struct AFSFid *) ain;
3471 Fid = &avc->fid.Fid;
3472 tfid.Cell = avc->fid.Cell;
3473 tfid.Fid.Volume = Fid->Volume;
3474 tfid.Fid.Vnode = Fid->Vnode;
3475 tfid.Fid.Unique = Fid->Unique;
3477 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3479 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3480 ICL_TYPE_POINTER, tvc,
3481 ICL_TYPE_FID, &tfid,
3482 ICL_TYPE_FID, &avc->fid);
3485 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3486 ICL_TYPE_POINTER, tvc,
3487 ICL_TYPE_FID, &tfid,
3488 ICL_TYPE_FID, &tvc->fid);
3491 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3495 tcall = rx_NewCall(tc->id);
3496 code = StartRXAFS_FetchData(tcall,
3497 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3499 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3500 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3502 code1 = rx_EndCall(tcall, code);
3507 (afs_Analyze(tc, code, &tvc->fid, areq,
3508 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3510 /* This call is done only to have the callback things handled correctly */
3511 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3515 *aoutSize = sizeof(afs_int32);
3520 DECL_PIOCTL(PResidencyCmd)
3522 register afs_int32 code;
3525 struct ResidencyCmdInputs *Inputs;
3526 struct ResidencyCmdOutputs *Outputs;
3527 struct VenusFid tfid;
3530 Inputs = (struct ResidencyCmdInputs *) ain;
3531 Outputs = (struct ResidencyCmdOutputs *) aout;
3532 if (!avc) return EINVAL;
3533 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3537 Fid = &avc->fid.Fid;
3539 tfid.Cell = avc->fid.Cell;
3540 tfid.Fid.Volume = Fid->Volume;
3541 tfid.Fid.Vnode = Fid->Vnode;
3542 tfid.Fid.Unique = Fid->Unique;
3544 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3545 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3546 ICL_TYPE_POINTER, tvc,
3547 ICL_TYPE_INT32, Inputs->command,
3548 ICL_TYPE_FID, &tfid);
3552 if (Inputs->command) {
3554 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3557 code = RXAFS_ResidencyCmd(tc->id, Fid,
3559 (struct ResidencyCmdOutputs *) aout);
3564 (afs_Analyze(tc, code, &tvc->fid, areq,
3565 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3567 /* This call is done to have the callback things handled correctly */
3568 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3569 } else { /* just a status request, return also link data */
3571 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3572 Outputs->chars[0] = 0;
3573 if (vType(tvc) == VLNK) {
3574 ObtainWriteLock(&tvc->lock,555);
3575 if (afs_HandleLink(tvc, areq) == 0)
3576 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3577 ReleaseWriteLock(&tvc->lock);
3584 *aoutSize = sizeof(struct ResidencyCmdOutputs);