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 "../afs/param.h" /* Should be always first */
11 #include "../afs/sysincludes.h" /* Standard vendor system headers */
12 #include "../afs/afsincludes.h" /* Afs-based standard headers */
13 #include "../afs/afs_stats.h" /* afs statistics */
14 #include "../afs/vice.h"
15 #include "../rx/rx_globals.h"
17 extern void afs_ComputePAGStats();
18 extern struct vcache *afs_LookupVCache();
19 struct VenusFid afs_rootFid;
20 afs_int32 afs_waitForever=0;
21 short afs_waitForeverCount = 0;
22 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
23 extern afs_int32 PROBE_INTERVAL;
25 extern int cacheDiskType;
26 extern afs_int32 afs_cacheBlocks;
27 extern struct afs_q CellLRU;
28 extern char *afs_indexFlags; /* only one: is there data there? */
29 extern afs_int32 afs_blocksUsed;
30 extern struct unixuser *afs_users[NUSERS];
31 extern struct server *afs_servers[NSERVERS];
32 extern struct interfaceAddr afs_cb_interface; /* client interface addresses */
33 extern afs_rwlock_t afs_xserver;
34 extern afs_rwlock_t afs_xinterface;
35 extern afs_rwlock_t afs_xcell;
36 extern afs_rwlock_t afs_xuser;
37 #ifndef AFS_FINEG_SUNLOCK
38 extern afs_rwlock_t afs_xconn;
40 extern afs_rwlock_t afs_xvolume;
41 extern afs_lock_t afs_xdcache; /* lock: alloc new disk cache entries */
42 extern afs_rwlock_t afs_xvcache;
43 extern afs_rwlock_t afs_xcbhash;
44 extern afs_int32 afs_mariner, afs_marinerHost;
45 extern struct srvAddr *afs_srvAddrs[NSERVERS];
46 extern int afs_resourceinit_flag;
47 extern afs_int32 cryptall;
49 static int PBogus(), PSetAcl(), PGetAcl(), PSetTokens(), PGetVolumeStatus();
50 static int PSetVolumeStatus(), PFlush(), PNewStatMount(), PGetTokens(), PUnlog();
51 static int PCheckServers(), PCheckVolNames(), PCheckAuth(), PFindVolume();
52 static int PViceAccess(), PSetCacheSize(), Prefetch();
53 static int PRemoveCallBack(), PNewCell(), PListCells(), PRemoveMount();
54 static int PMariner(), PGetUserCell(), PGetWSCell(), PGetFileCell();
55 static int PVenusLogging(), PNoop(), PSetCellStatus(), PGetCellStatus();
56 static int PFlushVolumeData(), PGetCacheSize();
57 static int PSetSysName(),PGetFID();
58 static int PGetVnodeXStatus();
59 static int PSetSPrefs(), PGetSPrefs(), PGag(), PTwiddleRx();
60 static int PSetSPrefs33(), PStoreBehind(), PGCPAGs();
61 static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */
62 static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer();
65 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
67 extern struct cm_initparams cm_initParams;
69 static int (*(pioctlSw[]))() = {
74 PGetVolumeStatus, /* 4 */
75 PSetVolumeStatus, /* 5 */
80 PCheckServers, /* 10 */
81 PCheckVolNames, /* 11 */
83 PBogus, /* 13 -- used to be quick check time */
85 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
86 PBogus, /* 16 -- used to be testing code */
87 PNoop, /* 17 -- used to be enable group */
88 PNoop, /* 18 -- used to be disable group */
89 PBogus, /* 19 -- used to be list group */
91 PUnlog, /* 21 -- unlog *is* unpag in this system */
92 PGetFID, /* 22 -- get file ID */
93 PBogus, /* 23 -- used to be waitforever */
94 PSetCacheSize, /* 24 */
95 PRemoveCallBack, /* 25 -- flush only the callback */
98 PRemoveMount, /* 28 -- delete mount point */
99 PNewStatMount, /* 29 -- new style mount point stat */
100 PGetFileCell, /* 30 -- get cell name for input file */
101 PGetWSCell, /* 31 -- get cell name for workstation */
102 PMariner, /* 32 - set/get mariner host */
103 PGetUserCell, /* 33 -- get cell name for user */
104 PVenusLogging, /* 34 -- Enable/Disable logging */
105 PGetCellStatus, /* 35 */
106 PSetCellStatus, /* 36 */
107 PFlushVolumeData, /* 37 -- flush all data from a volume */
108 PSetSysName, /* 38 - Set system name */
109 PExportAfs, /* 39 - Export Afs to remote nfs clients */
110 PGetCacheSize, /* 40 - get cache size and usage */
111 PGetVnodeXStatus, /* 41 - get vcache's special status */
112 PSetSPrefs33, /* 42 - Set CM Server preferences... */
113 PGetSPrefs, /* 43 - Get CM Server preferences... */
114 PGag, /* 44 - turn off/on all CM messages */
115 PTwiddleRx, /* 45 - adjust some RX params */
116 PSetSPrefs, /* 46 - Set CM Server preferences... */
117 PStoreBehind, /* 47 - set degree of store behind to be done */
118 PGCPAGs, /* 48 - disable automatic pag gc-ing */
119 PGetInitParams, /* 49 - get initial cm params */
120 PGetCPrefs, /* 50 - get client interface addresses */
121 PSetCPrefs, /* 51 - set client interface addresses */
122 PFlushMount, /* 52 - flush mount symlink data */
123 PRxStatProc, /* 53 - control process RX statistics */
124 PRxStatPeer, /* 54 - control peer RX statistics */
125 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
126 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
127 PNoop, /* 57 -- arla: set file prio */
128 PNoop, /* 58 -- arla: fallback getfh */
129 PNoop, /* 59 -- arla: fallback fhopen */
130 PNoop, /* 60 -- arla: controls xfsdebug */
131 PNoop, /* 61 -- arla: controls arla debug */
132 PNoop, /* 62 -- arla: debug interface */
133 PNoop, /* 63 -- arla: print xfs status */
134 PNoop, /* 64 -- arla: force cache check */
135 PNoop, /* 65 -- arla: break callback */
138 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
139 int afs_nobody = NFS_NOBODY;
142 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
144 dst->in = (char *)(unsigned long)src->in;
145 dst->out = (char *)(unsigned long)src->out;
146 dst->in_size = src->in_size;
147 dst->out_size = src->out_size;
151 * If you need to change copyin_afs_ioctl(), you may also need to change
156 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
160 #if defined(AFS_HPUX_64BIT_ENV)
161 struct afs_ioctl32 dst32;
163 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
165 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
167 afs_ioctl32_to_afs_ioctl(&dst32, dst);
170 #endif /* defined(AFS_HPUX_64BIT_ENV) */
172 #if defined(AFS_SUN57_64BIT_ENV)
173 struct afs_ioctl32 dst32;
175 if (get_udatamodel() == DATAMODEL_ILP32) {
176 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
178 afs_ioctl32_to_afs_ioctl(&dst32, dst);
181 #endif /* defined(AFS_SUN57_64BIT_ENV) */
183 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
184 struct afs_ioctl32 dst32;
186 if (!ABI_IS_64BIT(get_current_abi()))
188 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
190 afs_ioctl32_to_afs_ioctl(&dst32, dst);
193 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
195 #if defined(AFS_LINUX_64BIT_KERNEL)
196 struct afs_ioctl32 dst32;
198 #ifdef AFS_SPARC64_LINUX20_ENV
199 if (current->tss.flags & SPARC_FLAG_32BIT) {
201 #error Not done for this linux type
203 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
205 afs_ioctl32_to_afs_ioctl(&dst32, dst);
208 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
210 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
214 HandleIoctl(avc, acom, adata)
215 register struct vcache *avc;
216 register afs_int32 acom;
217 struct afs_ioctl *adata; {
218 register afs_int32 code;
221 AFS_STATCNT(HandleIoctl);
223 switch(acom & 0xff) {
225 avc->states |= CSafeStore;
229 /* case 2 used to be abort store, but this is no longer provided,
230 since it is impossible to implement under normal Unix.
234 /* return the name of the cell this file is open on */
235 register struct cell *tcell;
236 register afs_int32 i;
238 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
240 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
242 if (i > adata->out_size) {
243 /* 0 means we're not interested in the output */
244 if (adata->out_size != 0) code = EFAULT;
248 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
250 afs_PutCell(tcell, READ_LOCK);
256 case 49: /* VIOC_GETINITPARAMS */
257 if (adata->out_size < sizeof(struct cm_initparams)) {
261 AFS_COPYOUT(&cm_initParams, adata->out,
262 sizeof(struct cm_initparams), code);
271 return code; /* so far, none implemented */
276 /* For aix we don't temporarily bypass ioctl(2) but rather do our
277 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
278 * is now called from afs_gn_ioctl.
280 afs_ioctl(tvc, cmd, arg)
285 struct afs_ioctl data;
288 AFS_STATCNT(afs_ioctl);
289 if (((cmd >> 8) & 0xff) == 'V') {
290 /* This is a VICEIOCTL call */
291 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
294 error = HandleIoctl(tvc, cmd, &data);
297 /* No-op call; just return. */
301 #endif /* AFS_AIX_ENV */
303 #if defined(AFS_SGI_ENV)
304 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
310 struct afs_ioctl data;
316 AFS_STATCNT(afs_ioctl);
317 if (((cmd >> 8) & 0xff) == 'V') {
318 /* This is a VICEIOCTL call */
319 error = copyin_afs_ioctl(arg, &data);
322 locked = ISAFS_GLOCK();
325 error = HandleIoctl(tvc, cmd, &data);
330 /* No-op call; just return. */
334 #endif /* AFS_SGI_ENV */
337 /* unlike most calls here, this one uses u.u_error to return error conditions,
338 since this is really an intercepted chapter 2 call, rather than a vnode
341 /* AFS_HPUX102 and up uses VNODE ioctl instead */
342 #ifndef AFS_HPUX102_ENV
343 #if !defined(AFS_SGI_ENV)
345 kioctl(fdes, com, arg, ext)
352 } u_uap, *uap = &u_uap;
356 struct afs_ioctl_sys {
362 afs_xioctl (uap, rvp)
363 struct afs_ioctl_sys *uap;
368 afs_xioctl (p, args, retval)
377 } *uap = (struct a *)args;
378 #else /* AFS_OSF_ENV */
379 #ifdef AFS_LINUX22_ENV
380 struct afs_ioctl_sys {
384 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
385 unsigned int com, unsigned long arg)
387 struct afs_ioctl_sys ua, *uap = &ua;
395 } *uap = (struct a *)u.u_ap;
396 #endif /* AFS_LINUX22_ENV */
397 #endif /* AFS_OSF_ENV */
398 #endif /* AFS_SUN5_ENV */
400 #ifndef AFS_LINUX22_ENV
401 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
404 register struct file *fd;
407 register struct vcache *tvc;
408 register int ioctlDone = 0, code = 0;
410 AFS_STATCNT(afs_xioctl);
411 #ifdef AFS_LINUX22_ENV
419 if (setuerror(getf(uap->fd, &fd))) {
425 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
427 #else /* AFS_OSF_ENV */
429 #if defined(AFS_SUN57_ENV)
431 if (!fd) return(EBADF);
432 #elif defined(AFS_SUN54_ENV)
434 if (!fd) return(EBADF);
436 if (code = getf(uap->fd, &fd)) {
448 /* first determine whether this is any sort of vnode */
449 #ifdef AFS_LINUX22_ENV
450 tvc = (struct vcache *)ip;
454 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
456 if (fd->f_type == DTYPE_VNODE) {
458 /* good, this is a vnode; next see if it is an AFS vnode */
459 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
460 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
462 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
464 #endif /* AFS_LINUX22_ENV */
465 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
467 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
468 if (!tvc) { /* shouldn't happen with held gnodes */
473 /* This is an AFS vnode */
474 if (((uap->com >> 8) & 0xff) == 'V') {
475 register struct afs_ioctl *datap;
477 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
478 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
480 osi_FreeSmallSpace(datap);
482 #if defined(AFS_SUN5_ENV)
497 #else /* AFS_OSF_ENV */
501 #ifdef AFS_LINUX22_ENV
510 code = HandleIoctl(tvc, uap->com, datap);
511 osi_FreeSmallSpace(datap);
525 #if defined(AFS_LINUX22_ENV)
535 code = okioctl(fdes, com, arg, ext);
539 okioctl(fdes, com, arg, ext);
541 #if defined(AFS_SUN5_ENV)
542 #if defined(AFS_SUN57_ENV)
544 #elif defined(AFS_SUN54_ENV)
549 code = ioctl(uap, rvp);
552 code = ioctl(p, args, retval);
559 #else /* AFS_OSF_ENV */
560 #ifndef AFS_LINUX22_ENV
577 #ifdef AFS_LINUX22_ENV
580 #if !defined(AFS_OSF_ENV)
583 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
584 return (getuerror() ? -1 : u.u_ioctlrv);
586 return getuerror() ? -1 : 0;
589 #endif /* AFS_LINUX22_ENV */
590 #endif /* AFS_SUN5_ENV */
595 #endif /* AFS_SGI_ENV */
596 #endif /* AFS_HPUX102_ENV */
598 #if defined(AFS_SGI_ENV)
599 /* "pioctl" system call entry point; just pass argument to the parameterized
608 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
612 AFS_STATCNT(afs_pioctl);
614 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
622 #endif /* AFS_SGI_ENV */
625 afs_pioctl(p, args, retval)
635 } *uap = (struct a *) args;
637 AFS_STATCNT(afs_pioctl);
638 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
641 extern struct mount *afs_globalVFS;
642 #else /* AFS_OSF_ENV */
643 extern struct vfs *afs_globalVFS;
646 /* macro to avoid adding any more #ifdef's to pioctl code. */
647 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
648 #define PIOCTL_FREE_CRED() crfree(credp)
650 #define PIOCTL_FREE_CRED()
654 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
656 struct AFS_UCRED *credp;
658 afs_syscall_pioctl(path, com, cmarg, follow)
665 struct afs_ioctl data;
666 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
667 register afs_int32 code = 0;
673 struct ucred *credp = crref(); /* don't free until done! */
675 #ifdef AFS_LINUX22_ENV
676 cred_t *credp = crref(); /* don't free until done! */
679 AFS_STATCNT(afs_syscall_pioctl);
680 if (follow) follow = 1; /* compat. with old venus */
682 if (! _VALIDVICEIOCTL(com)) {
686 #else /* AFS_OSF_ENV */
687 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
696 code = copyin_afs_ioctl(cmarg, &data);
699 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
706 if ((com & 0xff) == PSetClientContext) {
707 #ifdef AFS_LINUX22_ENV
708 return EINVAL; /* Not handling these yet. */
710 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
711 code = HandleClientContext(&data, &com, &foreigncreds, credp);
713 #if defined(AFS_HPUX101_ENV)
714 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
717 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
719 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
720 #endif /* AFS_SGI_ENV */
725 crfree(foreigncreds);
728 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
731 return (setuerror(code), code);
735 #ifndef AFS_LINUX22_ENV
738 * We could have done without temporary setting the u.u_cred below
739 * (foreigncreds could be passed as param the pioctl modules)
740 * but calls such as afs_osi_suser() doesn't allow that since it
741 * references u.u_cred directly. We could, of course, do something
742 * like afs_osi_suser(cred) which, I think, is better since it
743 * generalizes and supports multi cred environments...
747 credp = foreigncreds;
750 tmpcred = crref(); /* XXX */
753 #if defined(AFS_HPUX101_ENV)
754 tmpcred = p_cred(u.u_procp);
755 set_p_cred(u.u_procp, foreigncreds);
758 tmpcred = OSI_GET_CURRENT_CRED();
759 OSI_SET_CURRENT_CRED(foreigncreds);
762 u.u_cred = foreigncreds;
763 #endif /* AFS_SGI64_ENV */
764 #endif /* AFS_HPUX101_ENV */
769 if ((com & 0xff) == 15) {
770 /* special case prefetch so entire pathname eval occurs in helper process.
771 otherwise, the pioctl call is essentially useless */
772 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
773 code = Prefetch(path, &data, follow,
774 foreigncreds ? foreigncreds : credp);
776 #if defined(AFS_HPUX101_ENV)
777 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
780 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
782 code = Prefetch(path, &data, follow, u.u_cred);
783 #endif /* AFS_SGI64_ENV */
784 #endif /* AFS_HPUX101_ENV */
786 #ifndef AFS_LINUX22_ENV
789 crset(tmpcred); /* restore original credentials */
791 #if defined(AFS_HPUX101_ENV)
792 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
796 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
798 u.u_cred = tmpcred; /* restore original credentials */
801 #endif /* AFS_HPUX101_ENV */
802 crfree(foreigncreds);
805 #endif /* AFS_LINUX22_ENV */
807 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
810 return (setuerror(code), code);
816 code = lookupname(path, USR, follow, NULL, &vp,
817 foreigncreds ? foreigncreds : credp);
819 #ifdef AFS_LINUX22_ENV
820 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
822 vp = (struct vnode *)dp->d_inode;
824 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
825 #endif /* AFS_LINUX22_ENV */
826 #endif /* AFS_AIX41_ENV */
829 #ifndef AFS_LINUX22_ENV
832 crset(tmpcred); /* restore original credentials */
834 #if defined(AFS_HPUX101_ENV)
835 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
837 #if !defined(AFS_SUN5_ENV)
839 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
841 u.u_cred = tmpcred; /* restore original credentials */
842 #endif /* AFS_SGI64_ENV */
844 #endif /* AFS_HPUX101_ENV */
845 crfree(foreigncreds);
848 #endif /* AFS_LINUX22_ENV */
850 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
853 return(setuerror(code), code);
857 else vp = (struct vnode *) 0;
859 /* now make the call if we were passed no file, or were passed an AFS file */
860 if (!vp || IsAfsVnode(vp)) {
862 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
863 * So, we must test in this part of the code. Also, must arrange to
864 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
865 * we hold gnodes, whose references hold our vcache entries.
868 gp = vp; /* remember for "put" */
869 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
871 else gp = (struct vnode *) 0;
874 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
878 struct ucred *cred1, *cred2;
881 cred1 = cred2 = foreigncreds;
883 cred1 = cred2 = credp;
885 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
886 if (cred1 != cred2) {
887 /* something changed the creds */
892 #if defined(AFS_HPUX101_ENV)
894 struct ucred *cred = p_cred(u.u_procp);
895 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
901 credp = OSI_GET_CURRENT_CRED();
902 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
905 #ifdef AFS_LINUX22_ENV
906 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
908 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
910 #endif /* AFS_SGI_ENV */
911 #endif /* AFS_HPUX101_ENV */
912 #endif /* AFS_AIX41_ENV */
913 #endif /* AFS_SUN5_ENV */
915 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
916 code = EINVAL; /* not in /afs */
923 vp = (struct vnode *) 0;
928 #ifndef AFS_LINUX22_ENV
933 #if defined(AFS_HPUX101_ENV)
934 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
938 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
940 u.u_cred = tmpcred; /* restore original credentials */
941 #endif /* ASF_SGI64_ENV */
943 #endif /* AFS_HPUX101_ENV */
944 crfree(foreigncreds);
947 #endif /* AFS_LINUX22_ENV */
949 #ifdef AFS_LINUX22_ENV
952 AFS_RELE(vp); /* put vnode back */
956 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
961 return (getuerror());
966 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
967 register struct vcache *avc;
969 struct AFS_UCRED **acred;
970 register struct afs_ioctl *ablob;
973 struct vrequest treq;
974 register afs_int32 code;
975 register afs_int32 function;
976 afs_int32 inSize, outSize;
977 char *inData, *outData;
979 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
980 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
981 AFS_STATCNT(HandlePioctl);
982 if (code = afs_InitReq(&treq, *acred)) return code;
983 function = acom & 0xff;
984 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
985 return EINVAL; /* out of range */
987 inSize = ablob->in_size;
988 if (inSize >= PIGGYSIZE) return E2BIG;
989 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
991 AFS_COPYIN(ablob->in, inData, inSize, code);
995 osi_FreeLargeSpace(inData);
998 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1000 if (function == 3) /* PSetTokens */
1001 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1003 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1004 osi_FreeLargeSpace(inData);
1005 if (code == 0 && ablob->out_size > 0) {
1006 if (outSize > ablob->out_size) outSize = ablob->out_size;
1007 if (outSize >= PIGGYSIZE) code = E2BIG;
1009 AFS_COPYOUT(outData, ablob->out, outSize, code);
1011 osi_FreeLargeSpace(outData);
1012 return afs_CheckCode(code, &treq, 41);
1015 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1018 struct vrequest *areq;
1021 afs_int32 *aoutSize; /* set this */ {
1022 register afs_int32 code;
1024 AFS_STATCNT(PGetFID);
1025 if (!avc) return EINVAL;
1026 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1027 *aoutSize = sizeof(struct VenusFid);
1031 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1034 struct vrequest *areq;
1037 afs_int32 *aoutSize; /* set this */ {
1038 register afs_int32 code;
1040 struct AFSOpaque acl;
1041 struct AFSVolSync tsync;
1042 struct AFSFetchStatus OutStatus;
1045 AFS_STATCNT(PSetAcl);
1048 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1051 acl.AFSOpaque_val = ain;
1053 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1055 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1056 #ifdef RX_ENABLE_LOCKS
1058 #endif /* RX_ENABLE_LOCKS */
1059 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1060 &acl, &OutStatus, &tsync);
1061 #ifdef RX_ENABLE_LOCKS
1063 #endif /* RX_ENABLE_LOCKS */
1068 (afs_Analyze(tconn, code, &avc->fid, areq,
1069 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1071 /* now we've forgotten all of the access info */
1072 ObtainWriteLock(&afs_xcbhash, 455);
1074 afs_DequeueCallback(avc);
1075 avc->states &= ~(CStatd | CUnique);
1076 ReleaseWriteLock(&afs_xcbhash);
1077 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1078 osi_dnlc_purgedp(avc);
1082 int afs_defaultAsynchrony = 0;
1084 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1087 struct vrequest *areq;
1090 afs_int32 *aoutSize; /* set this */
1091 struct AFS_UCRED *acred;
1094 struct sbstruct *sbr;
1096 sbr = (struct sbstruct *)ain;
1097 if (sbr->sb_default != -1) {
1098 if (afs_osi_suser(acred))
1099 afs_defaultAsynchrony = sbr->sb_default;
1103 if (avc && (sbr->sb_thisfile != -1))
1104 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1105 areq, DONT_CHECK_MODE_BITS))
1106 avc->asynchrony = sbr->sb_thisfile;
1109 *aoutSize = sizeof(struct sbstruct);
1110 sbr = (struct sbstruct *)aout;
1111 sbr->sb_default = afs_defaultAsynchrony;
1113 sbr->sb_thisfile = avc->asynchrony;
1119 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1122 struct vrequest *areq;
1125 afs_int32 *aoutSize; /* set this */
1126 struct AFS_UCRED *acred;
1128 if (!afs_osi_suser(acred)) {
1131 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1135 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1138 struct vrequest *areq;
1141 afs_int32 *aoutSize; /* set this */ {
1142 struct AFSOpaque acl;
1143 struct AFSVolSync tsync;
1144 struct AFSFetchStatus OutStatus;
1150 AFS_STATCNT(PGetAcl);
1151 if (!avc) return EINVAL;
1152 Fid.Volume = avc->fid.Fid.Volume;
1153 Fid.Vnode = avc->fid.Fid.Vnode;
1154 Fid.Unique = avc->fid.Fid.Unique;
1155 if (avc->states & CForeign) {
1157 * For a dfs xlator acl we have a special hack so that the
1158 * xlator will distinguish which type of acl will return. So
1159 * we currently use the top 2-bytes (vals 0-4) to tell which
1160 * type of acl to bring back. Horrible hack but this will
1161 * cause the least number of changes to code size and interfaces.
1163 if (Fid.Vnode & 0xc0000000)
1165 Fid.Vnode |= (ainSize << 30);
1167 acl.AFSOpaque_val = aout;
1169 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1172 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1173 #ifdef RX_ENABLE_LOCKS
1175 #endif /* RX_ENABLE_LOCKS */
1176 code = RXAFS_FetchACL(tconn->id, &Fid,
1177 &acl, &OutStatus, &tsync);
1178 #ifdef RX_ENABLE_LOCKS
1180 #endif /* RX_ENABLE_LOCKS */
1185 (afs_Analyze(tconn, code, &avc->fid, areq,
1186 AFS_STATS_FS_RPCIDX_FETCHACL,
1187 SHARED_LOCK, (struct cell *)0));
1190 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1201 AFS_STATCNT(PBogus);
1205 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1208 struct vrequest *areq;
1212 afs_int32 *aoutSize; /* set this */ {
1213 register struct cell *tcell;
1215 AFS_STATCNT(PGetFileCell);
1216 if (!avc) return EINVAL;
1217 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1218 if (!tcell) return ESRCH;
1219 strcpy(aout, tcell->cellName);
1220 afs_PutCell(tcell, READ_LOCK);
1221 *aoutSize = strlen(aout) + 1;
1225 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1228 struct vrequest *areq;
1232 afs_int32 *aoutSize; /* set this */ {
1233 register struct cell *tcell=0, *cellOne=0;
1234 register struct afs_q *cq, *tq;
1236 AFS_STATCNT(PGetWSCell);
1237 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1238 return EIO; /* Inappropriate ioctl for device */
1240 ObtainReadLock(&afs_xcell);
1241 cellOne = (struct cell *) 0;
1243 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1244 tcell = QTOC(cq); tq = QNext(cq);
1245 if (tcell->states & CPrimary) break;
1246 if (tcell->cell == 1) cellOne = tcell;
1249 ReleaseReadLock(&afs_xcell);
1250 if (!tcell) { /* no primary cell, use cell #1 */
1251 if (!cellOne) return ESRCH;
1254 strcpy(aout, tcell->cellName);
1255 *aoutSize = strlen(aout) + 1;
1259 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1262 struct vrequest *areq;
1266 afs_int32 *aoutSize; /* set this */ {
1267 register afs_int32 i;
1268 register struct unixuser *tu;
1269 register struct cell *tcell;
1271 AFS_STATCNT(PGetUserCell);
1272 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1273 return EIO; /* Inappropriate ioctl for device */
1275 /* return the cell name of the primary cell for this user */
1276 i = UHash(areq->uid);
1277 ObtainWriteLock(&afs_xuser,224);
1278 for(tu = afs_users[i]; tu; tu = tu->next) {
1279 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1281 ReleaseWriteLock(&afs_xuser);
1286 tcell = afs_GetCell(tu->cell, READ_LOCK);
1287 afs_PutUser(tu, WRITE_LOCK);
1288 if (!tcell) return ESRCH;
1290 strcpy(aout, tcell->cellName);
1291 afs_PutCell(tcell, READ_LOCK);
1292 *aoutSize = strlen(aout)+1; /* 1 for the null */
1296 ReleaseWriteLock(&afs_xuser);
1303 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1306 struct vrequest *areq;
1310 afs_int32 *aoutSize; /* set this */
1311 struct AFS_UCRED **acred;
1314 register struct unixuser *tu;
1315 struct ClearToken clear;
1316 register struct cell *tcell;
1319 struct vrequest treq;
1320 afs_int32 flag, set_parent_pag = 0;
1322 AFS_STATCNT(PSetTokens);
1323 if (!afs_resourceinit_flag) {
1326 bcopy(ain, (char *)&i, sizeof(afs_int32));
1327 ain += sizeof(afs_int32);
1328 stp = ain; /* remember where the ticket is */
1329 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1331 ain += i; /* skip over ticket */
1332 bcopy(ain, (char *)&i, sizeof(afs_int32));
1333 ain += sizeof(afs_int32);
1334 if (i != sizeof(struct ClearToken)) {
1337 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1338 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1339 ain += sizeof(struct ClearToken);
1340 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1341 /* still stuff left? we've got primary flag and cell name. Set these */
1342 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1343 ain += sizeof(afs_int32); /* skip id field */
1344 /* rest is cell name, look it up */
1345 if (flag & 0x8000) { /* XXX Use Constant XXX */
1349 tcell = afs_GetCellByName(ain, READ_LOCK);
1358 /* default to cell 1, primary id */
1359 flag = 1; /* primary id */
1360 i = 1; /* cell number */
1361 tcell = afs_GetCell(1, READ_LOCK);
1362 if (!tcell) goto nocell;
1364 afs_PutCell(tcell, READ_LOCK);
1365 if (set_parent_pag) {
1368 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1370 if (!setpag(acred, -1, &pag, 1)) {
1372 afs_InitReq(&treq, *acred);
1376 /* now we just set the tokens */
1377 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1378 tu->vid = clear.ViceId;
1379 if (tu->stp != (char *) 0) {
1380 afs_osi_Free(tu->stp, tu->stLen);
1382 tu->stp = (char *) afs_osi_Alloc(stLen);
1384 bcopy(stp, tu->stp, stLen);
1387 afs_stats_cmfullperf.authent.TicketUpdates++;
1388 afs_ComputePAGStats();
1389 #endif /* AFS_NOSTATS */
1390 tu->states |= UHasTokens;
1391 tu->states &= ~UTokensBad;
1392 afs_SetPrimary(tu, flag);
1393 tu->tokenTime =osi_Time();
1394 afs_ResetUserConns(tu);
1395 afs_PutUser(tu, WRITE_LOCK);
1410 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1413 struct vrequest *areq;
1416 afs_int32 *aoutSize; /* set this */ {
1418 char offLineMsg[256];
1420 register struct conn *tc;
1421 register afs_int32 code;
1422 struct VolumeStatus volstat;
1424 char *Name, *OfflineMsg, *MOTD;
1427 AFS_STATCNT(PGetVolumeStatus);
1428 if (!avc) return EINVAL;
1430 OfflineMsg = offLineMsg;
1433 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1435 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1436 #ifdef RX_ENABLE_LOCKS
1438 #endif /* RX_ENABLE_LOCKS */
1439 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1440 &Name, &OfflineMsg, &MOTD);
1441 #ifdef RX_ENABLE_LOCKS
1443 #endif /* RX_ENABLE_LOCKS */
1448 (afs_Analyze(tc, code, &avc->fid, areq,
1449 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1450 SHARED_LOCK, (struct cell *)0));
1452 if (code) return code;
1453 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1455 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1456 cp += sizeof(VolumeStatus);
1457 strcpy(cp, volName);
1458 cp += strlen(volName)+1;
1459 strcpy(cp, offLineMsg);
1460 cp += strlen(offLineMsg)+1;
1462 cp += strlen(motd)+1;
1463 *aoutSize = (cp - aout);
1467 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1470 struct vrequest *areq;
1473 afs_int32 *aoutSize; /* set this */ {
1475 char offLineMsg[256];
1477 register struct conn *tc;
1478 register afs_int32 code;
1479 struct AFSFetchVolumeStatus volstat;
1480 struct AFSStoreVolumeStatus storeStat;
1481 register struct volume *tvp;
1485 AFS_STATCNT(PSetVolumeStatus);
1486 if (!avc) return EINVAL;
1488 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1490 if (tvp->states & (VRO | VBackup)) {
1491 afs_PutVolume(tvp, READ_LOCK);
1494 afs_PutVolume(tvp, READ_LOCK);
1497 /* Copy the junk out, using cp as a roving pointer. */
1499 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1500 cp += sizeof(AFSFetchVolumeStatus);
1501 strcpy(volName, cp);
1502 cp += strlen(volName)+1;
1503 strcpy(offLineMsg, cp);
1504 cp += strlen(offLineMsg)+1;
1507 if (volstat.MinQuota != -1) {
1508 storeStat.MinQuota = volstat.MinQuota;
1509 storeStat.Mask |= AFS_SETMINQUOTA;
1511 if (volstat.MaxQuota != -1) {
1512 storeStat.MaxQuota = volstat.MaxQuota;
1513 storeStat.Mask |= AFS_SETMAXQUOTA;
1516 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1518 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1519 #ifdef RX_ENABLE_LOCKS
1521 #endif /* RX_ENABLE_LOCKS */
1522 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1523 &storeStat, volName, offLineMsg, motd);
1524 #ifdef RX_ENABLE_LOCKS
1526 #endif /* RX_ENABLE_LOCKS */
1531 (afs_Analyze(tc, code, &avc->fid, areq,
1532 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1533 SHARED_LOCK, (struct cell *)0));
1535 if (code) return code;
1536 /* we are sending parms back to make compat. with prev system. should
1537 change interface later to not ask for current status, just set new status */
1539 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1540 cp += sizeof(VolumeStatus);
1541 strcpy(cp, volName);
1542 cp += strlen(volName)+1;
1543 strcpy(cp, offLineMsg);
1544 cp += strlen(offLineMsg)+1;
1546 cp += strlen(motd)+1;
1547 *aoutSize = cp - aout;
1551 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1552 register struct vcache *avc;
1554 struct vrequest *areq;
1557 afs_int32 *aoutSize; /* set this */
1558 struct AFS_UCRED *acred;
1561 AFS_STATCNT(PFlush);
1562 if (!avc) return EINVAL;
1563 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1564 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1566 ObtainWriteLock(&avc->lock,225);
1567 ObtainWriteLock(&afs_xcbhash, 456);
1568 afs_DequeueCallback(avc);
1569 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1570 ReleaseWriteLock(&afs_xcbhash);
1571 /* now find the disk cache entries */
1572 afs_TryToSmush(avc, acred, 1);
1573 osi_dnlc_purgedp(avc);
1574 afs_symhint_inval(avc);
1575 if (avc->linkData && !(avc->states & CCore)) {
1576 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1577 avc->linkData = (char *) 0;
1579 ReleaseWriteLock(&avc->lock);
1580 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1581 afs_BozonUnlock(&avc->pvnLock, avc);
1586 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1589 struct vrequest *areq;
1592 afs_int32 *aoutSize; /* set this */ {
1593 register afs_int32 code;
1594 register struct vcache *tvc;
1595 register struct dcache *tdc;
1596 struct VenusFid tfid;
1598 afs_int32 offset, len, hasatsys=0;
1600 AFS_STATCNT(PNewStatMount);
1601 if (!avc) return EINVAL;
1602 code = afs_VerifyVCache(avc, areq);
1603 if (code) return code;
1604 if (vType(avc) != VDIR) {
1607 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1608 if (!tdc) return ENOENT;
1609 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1610 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1615 tfid.Cell = avc->fid.Cell;
1616 tfid.Fid.Volume = avc->fid.Fid.Volume;
1617 afs_PutDCache(tdc); /* we're done with the data */
1618 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1619 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1621 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1628 if (vType(tvc) != VLNK) {
1629 afs_PutVCache(tvc, WRITE_LOCK);
1633 ObtainWriteLock(&tvc->lock,226);
1634 code = afs_HandleLink(tvc, areq);
1636 if (tvc->linkData) {
1637 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1640 /* we have the data */
1641 strcpy(aout, tvc->linkData);
1642 *aoutSize = strlen(tvc->linkData)+1;
1647 ReleaseWriteLock(&tvc->lock);
1648 afs_PutVCache(tvc, WRITE_LOCK);
1650 if (hasatsys) osi_FreeLargeSpace(bufp);
1654 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1657 struct vrequest *areq;
1660 afs_int32 *aoutSize; /* set this */ {
1661 register struct cell *tcell;
1662 register afs_int32 i;
1663 register struct unixuser *tu;
1668 AFS_STATCNT(PGetTokens);
1669 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1670 return EIO; /* Inappropriate ioctl for device */
1672 /* weird interface. If input parameter is present, it is an integer and
1673 we're supposed to return the parm'th tokens for this unix uid.
1674 If not present, we just return tokens for cell 1.
1675 If counter out of bounds, return EDOM.
1676 If no tokens for the particular cell, return ENOTCONN.
1677 Also, if this mysterious parm is present, we return, along with the
1678 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1679 at the end, in that order.
1681 if (newStyle = (ainSize > 0)) {
1682 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1684 i = UHash(areq->uid);
1685 ObtainReadLock(&afs_xuser);
1686 for(tu = afs_users[i]; tu; tu=tu->next) {
1688 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1689 if (iterator-- == 0) break; /* are we done yet? */
1693 if (tu->uid == areq->uid && tu->cell == 1) break;
1698 * No need to hold a read lock on each user entry
1702 ReleaseReadLock(&afs_xuser);
1707 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1708 tu->states |= (UTokensBad | UNeedsReset);
1709 afs_PutUser(tu, READ_LOCK);
1712 /* use iterator for temp */
1714 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1715 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1716 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1717 cp += sizeof(afs_int32);
1718 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1720 iterator = sizeof(struct ClearToken);
1721 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1722 cp += sizeof(afs_int32);
1723 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1724 cp += sizeof(struct ClearToken);
1726 /* put out primary id and cell name, too */
1727 iterator = (tu->states & UPrimary ? 1 : 0);
1728 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1729 cp += sizeof(afs_int32);
1730 tcell = afs_GetCell(tu->cell, READ_LOCK);
1732 strcpy(cp, tcell->cellName);
1733 cp += strlen(tcell->cellName)+1;
1734 afs_PutCell(tcell, READ_LOCK);
1738 *aoutSize = cp - aout;
1739 afs_PutUser(tu, READ_LOCK);
1743 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1746 struct vrequest *areq;
1749 afs_int32 *aoutSize; /* set this */ {
1750 register afs_int32 i;
1751 register struct unixuser *tu;
1753 AFS_STATCNT(PUnlog);
1754 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1755 return EIO; /* Inappropriate ioctl for device */
1757 i = UHash(areq->uid);
1758 ObtainWriteLock(&afs_xuser,227);
1759 for(tu=afs_users[i]; tu; tu=tu->next) {
1760 if (tu->uid == areq->uid) {
1762 tu->states &= ~UHasTokens;
1763 /* security is not having to say you're sorry */
1764 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1766 ReleaseWriteLock(&afs_xuser);
1767 /* We have to drop the lock over the call to afs_ResetUserConns, since
1768 * it obtains the afs_xvcache lock. We could also keep the lock, and
1769 * modify ResetUserConns to take parm saying we obtained the lock
1770 * already, but that is overkill. By keeping the "tu" pointer
1771 * held over the released lock, we guarantee that we won't lose our
1772 * place, and that we'll pass over every user conn that existed when
1773 * we began this call.
1775 afs_ResetUserConns(tu);
1777 ObtainWriteLock(&afs_xuser,228);
1780 ReleaseWriteLock(&afs_xuser);
1784 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1787 struct vrequest *areq;
1790 afs_int32 *aoutSize; /* set this */ {
1791 afs_int32 newHostAddr;
1792 afs_int32 oldHostAddr;
1794 AFS_STATCNT(PMariner);
1796 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1798 oldHostAddr = 0xffffffff; /* disabled */
1800 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1801 if (newHostAddr == 0xffffffff) {
1802 /* disable mariner operations */
1805 else if (newHostAddr) {
1807 afs_marinerHost = newHostAddr;
1809 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1810 *aoutSize = sizeof(afs_int32);
1814 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1817 struct vrequest *areq;
1820 afs_int32 *aoutSize; /* set this */
1821 struct AFS_UCRED *acred;
1823 register char *cp = 0;
1825 register struct server *ts;
1826 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1828 struct chservinfo *pcheck;
1830 AFS_STATCNT(PCheckServers);
1832 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1833 return EIO; /* Inappropriate ioctl for device */
1835 if (*lp == 0x12345678) { /* For afs3.3 version */
1836 pcheck=(struct chservinfo *)ain;
1837 if (pcheck->tinterval >= 0) {
1839 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1840 *aoutSize = sizeof(afs_int32);
1841 if (pcheck->tinterval > 0) {
1842 if (!afs_osi_suser(acred))
1844 PROBE_INTERVAL=pcheck->tinterval;
1850 temp=pcheck->tflags;
1851 cp = pcheck->tbuffer;
1852 } else { /* For pre afs3.3 versions */
1853 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1854 cp = ain+sizeof(afs_int32);
1855 if (ainSize > sizeof(afs_int32))
1860 * 1: fast check, don't contact servers.
1861 * 2: local cell only.
1864 /* have cell name, too */
1865 cellp = afs_GetCellByName(cp, READ_LOCK);
1866 if (!cellp) return ENOENT;
1868 else cellp = (struct cell *) 0;
1869 if (!cellp && (temp & 2)) {
1870 /* use local cell */
1871 cellp = afs_GetCell(1, READ_LOCK);
1873 if (!(temp & 1)) { /* if not fast, call server checker routine */
1874 afs_CheckServers(1, cellp); /* check down servers */
1875 afs_CheckServers(0, cellp); /* check up servers */
1877 /* now return the current down server list */
1879 ObtainReadLock(&afs_xserver);
1880 for(i=0;i<NSERVERS;i++) {
1881 for(ts = afs_servers[i]; ts; ts=ts->next) {
1882 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1883 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1884 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1885 cp += sizeof(afs_int32);
1889 ReleaseReadLock(&afs_xserver);
1890 if (cellp) afs_PutCell(cellp, READ_LOCK);
1891 *aoutSize = cp - aout;
1895 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1898 struct vrequest *areq;
1901 afs_int32 *aoutSize; /* set this */ {
1902 AFS_STATCNT(PCheckVolNames);
1903 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1904 return EIO; /* Inappropriate ioctl for device */
1906 afs_CheckRootVolume();
1907 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1908 AFS_VOLCHECK_EXPIRED |
1910 AFS_VOLCHECK_MTPTS);
1914 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1917 struct vrequest *areq;
1920 afs_int32 *aoutSize; /* set this */ {
1924 struct unixuser *tu;
1926 extern afs_rwlock_t afs_xsrvAddr;
1928 AFS_STATCNT(PCheckAuth);
1929 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1930 return EIO; /* Inappropriate ioctl for device */
1933 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1934 if (!tu) retValue = EACCES;
1936 /* we have a user */
1937 ObtainReadLock(&afs_xsrvAddr);
1938 ObtainReadLock(&afs_xconn);
1940 /* any tokens set? */
1941 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1942 /* all connections in cell 1 working? */
1943 for(i=0;i<NSERVERS;i++) {
1944 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1945 for (tc = sa->conns; tc; tc=tc->next) {
1946 if (tc->user == tu && (tu->states & UTokensBad))
1951 ReleaseReadLock(&afs_xsrvAddr);
1952 ReleaseReadLock(&afs_xconn);
1953 afs_PutUser(tu, READ_LOCK);
1955 bcopy((char *)&retValue, aout, sizeof(afs_int32));
1956 *aoutSize = sizeof(afs_int32);
1960 static Prefetch(apath, adata, afollow, acred)
1962 struct afs_ioctl *adata;
1964 struct AFS_UCRED *acred;
1967 register afs_int32 code;
1970 AFS_STATCNT(Prefetch);
1971 if (!apath) return EINVAL;
1972 tp = osi_AllocLargeSpace(1024);
1973 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1975 osi_FreeLargeSpace(tp);
1978 if (afs_BBusy()) { /* do this as late as possible */
1979 osi_FreeLargeSpace(tp);
1980 return EWOULDBLOCK; /* pretty close */
1982 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
1986 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
1989 struct vrequest *areq;
1992 afs_int32 *aoutSize; /* set this */ {
1993 register struct volume *tvp;
1994 register struct server *ts;
1995 register afs_int32 i;
1998 AFS_STATCNT(PFindVolume);
1999 if (!avc) return EINVAL;
2000 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2003 for(i=0;i<MAXHOSTS;i++) {
2004 ts = tvp->serverHost[i];
2006 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2007 cp += sizeof(afs_int32);
2010 /* still room for terminating NULL, add it on */
2011 ainSize = 0; /* reuse vbl */
2012 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2013 cp += sizeof(afs_int32);
2015 *aoutSize = cp - aout;
2016 afs_PutVolume(tvp, READ_LOCK);
2022 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2025 struct vrequest *areq;
2028 afs_int32 *aoutSize; /* set this */ {
2029 register afs_int32 code;
2032 AFS_STATCNT(PViceAccess);
2033 if (!avc) return EINVAL;
2034 code = afs_VerifyVCache(avc, areq);
2035 if (code) return code;
2036 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2037 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2042 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2045 struct vrequest *areq;
2048 afs_int32 *aoutSize; /* set this */
2049 struct AFS_UCRED *acred;
2054 AFS_STATCNT(PSetCacheSize);
2055 if (!afs_osi_suser(acred))
2057 /* too many things are setup initially in mem cache version */
2058 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2059 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2060 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2062 extern u_int afs_min_cache;
2063 if (newValue < afs_min_cache)
2064 afs_cacheBlocks = afs_min_cache;
2066 afs_cacheBlocks = newValue;
2068 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2069 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2070 afs_MaybeWakeupTruncateDaemon();
2071 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2072 afs_osi_Wait(1000, 0, 0);
2073 afs_MaybeWakeupTruncateDaemon();
2078 #define MAXGCSTATS 16
2079 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2082 struct vrequest *areq;
2085 afs_int32 *aoutSize; /* set this */ {
2086 afs_int32 results[MAXGCSTATS];
2088 AFS_STATCNT(PGetCacheSize);
2089 bzero((char *)results, sizeof(results));
2090 results[0] = afs_cacheBlocks;
2091 results[1] = afs_blocksUsed;
2092 bcopy((char *)results, aout, sizeof(results));
2093 *aoutSize = sizeof(results);
2097 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2100 struct vrequest *areq;
2103 afs_int32 *aoutSize; /* set this */ {
2104 register struct conn *tc;
2105 register afs_int32 code;
2106 struct AFSCallBack CallBacks_Array[1];
2107 struct AFSCBFids theFids;
2108 struct AFSCBs theCBs;
2111 AFS_STATCNT(PRemoveCallBack);
2112 if (!avc) return EINVAL;
2113 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2114 ObtainWriteLock(&avc->lock,229);
2115 theFids.AFSCBFids_len = 1;
2116 theCBs.AFSCBs_len = 1;
2117 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2118 theCBs.AFSCBs_val = CallBacks_Array;
2119 CallBacks_Array[0].CallBackType = CB_DROPPED;
2120 if (avc->callback) {
2122 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2124 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2125 #ifdef RX_ENABLE_LOCKS
2127 #endif /* RX_ENABLE_LOCKS */
2128 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2129 #ifdef RX_ENABLE_LOCKS
2131 #endif /* RX_ENABLE_LOCKS */
2134 /* don't set code on failure since we wouldn't use it */
2136 (afs_Analyze(tc, code, &avc->fid, areq,
2137 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2138 SHARED_LOCK, (struct cell *)0));
2140 ObtainWriteLock(&afs_xcbhash, 457);
2141 afs_DequeueCallback(avc);
2143 avc->states &= ~(CStatd | CUnique);
2144 ReleaseWriteLock(&afs_xcbhash);
2145 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2146 osi_dnlc_purgedp(avc);
2148 ReleaseWriteLock(&avc->lock);
2152 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2155 struct vrequest *areq;
2159 struct AFS_UCRED *acred;
2160 afs_int32 *aoutSize; /* set this */ {
2161 /* create a new cell */
2162 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2163 register struct cell *tcell;
2164 char *newcell=0, *linkedcell=0, *tp= ain;
2165 register afs_int32 code, linkedstate=0, ls;
2166 u_short fsport = 0, vlport = 0;
2169 AFS_STATCNT(PNewCell);
2170 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2171 return EIO; /* Inappropriate ioctl for device */
2173 if (!afs_osi_suser(acred))
2176 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2177 tp += sizeof(afs_int32);
2178 if (magic != 0x12345678)
2181 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2182 * server addresses while the 3.5 fs newcell command passes
2183 * MAXHOSTS. To figure out which is which, check if the cellname
2186 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2187 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2189 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2190 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2191 tp += (scount * sizeof(afs_int32));
2193 lp = (afs_int32 *)tp;
2196 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2197 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2198 tp += (3 * sizeof(afs_int32));
2200 if ((ls = *lp) & 1) {
2201 linkedcell = tp + strlen(newcell)+1;
2202 linkedstate |= CLinkedCell;
2205 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2206 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport);
2210 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2213 struct vrequest *areq;
2216 afs_int32 *aoutSize; /* set this */ {
2217 afs_int32 whichCell;
2218 register struct cell *tcell=0;
2219 register afs_int32 i;
2220 register char *cp, *tp = ain;
2221 register struct afs_q *cq, *tq;
2223 AFS_STATCNT(PListCells);
2224 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2225 return EIO; /* Inappropriate ioctl for device */
2227 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2228 tp += sizeof(afs_int32);
2229 ObtainReadLock(&afs_xcell);
2230 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2231 tcell = QTOC(cq); tq = QNext(cq);
2232 if (whichCell == 0) break;
2233 if (tq == &CellLRU) tcell = 0;
2238 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2239 for(i=0;i<MAXCELLHOSTS;i++) {
2240 if (tcell->cellHosts[i] == 0) break;
2241 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2242 cp += sizeof(afs_int32);
2244 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2245 strcpy(cp, tcell->cellName);
2246 cp += strlen(tcell->cellName)+1;
2247 *aoutSize = cp - aout;
2249 ReleaseReadLock(&afs_xcell);
2250 if (tcell) return 0;
2254 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2257 struct vrequest *areq;
2261 afs_int32 *aoutSize; /* set this */ {
2262 register afs_int32 code;
2264 afs_int32 offset, len, hasatsys = 0;
2265 register struct conn *tc;
2266 register struct dcache *tdc;
2267 register struct vcache *tvc;
2268 struct AFSFetchStatus OutDirStatus;
2269 struct VenusFid tfid;
2270 struct AFSVolSync tsync;
2274 /* "ain" is the name of the file in this dir to remove */
2276 AFS_STATCNT(PRemoveMount);
2277 if (!avc) return EINVAL;
2278 code = afs_VerifyVCache(avc, areq);
2279 if (code) return code;
2280 if (vType(avc) != VDIR) return ENOTDIR;
2282 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2283 if (!tdc) return ENOENT;
2284 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2285 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2290 tfid.Cell = avc->fid.Cell;
2291 tfid.Fid.Volume = avc->fid.Fid.Volume;
2292 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2293 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2295 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2296 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2303 if (vType(tvc) != VLNK) {
2305 afs_PutVCache(tvc, WRITE_LOCK);
2309 ObtainWriteLock(&tvc->lock,230);
2310 code = afs_HandleLink(tvc, areq);
2312 if (tvc->linkData) {
2313 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2318 ReleaseWriteLock(&tvc->lock);
2319 osi_dnlc_purgedp(tvc);
2320 afs_PutVCache(tvc, WRITE_LOCK);
2325 ObtainWriteLock(&avc->lock,231);
2326 osi_dnlc_remove(avc, bufp, tvc);
2328 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2330 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2331 #ifdef RX_ENABLE_LOCKS
2333 #endif /* RX_ENABLE_LOCKS */
2334 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2335 bufp, &OutDirStatus, &tsync);
2336 #ifdef RX_ENABLE_LOCKS
2338 #endif /* RX_ENABLE_LOCKS */
2343 (afs_Analyze(tc, code, &avc->fid, areq,
2344 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2345 SHARED_LOCK, (struct cell *)0));
2348 if (tdc) afs_PutDCache(tdc);
2349 ReleaseWriteLock(&avc->lock);
2353 /* we have the thing in the cache */
2354 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2355 /* we can do it locally */
2356 code = afs_dir_Delete(&tdc->f.inode, bufp);
2358 ZapDCE(tdc); /* surprise error -- invalid value */
2359 DZap(&tdc->f.inode);
2362 afs_PutDCache(tdc); /* drop ref count */
2364 avc->states &= ~CUnique; /* For the dfs xlator */
2365 ReleaseWriteLock(&avc->lock);
2368 if (hasatsys) osi_FreeLargeSpace(bufp);
2372 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2375 struct vrequest *areq;
2379 struct AFS_UCRED *acred;
2380 afs_int32 *aoutSize; /* set this */ {
2381 return EINVAL; /* OBSOLETE */
2384 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2387 struct vrequest *areq;
2390 afs_int32 *aoutSize; /* set this */ {
2391 register struct cell *tcell;
2394 AFS_STATCNT(PGetCellStatus);
2395 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2396 return EIO; /* Inappropriate ioctl for device */
2398 tcell = afs_GetCellByName(ain, READ_LOCK);
2399 if (!tcell) return ENOENT;
2400 temp = tcell->states;
2401 afs_PutCell(tcell, READ_LOCK);
2402 bcopy((char *)&temp, aout, sizeof(afs_int32));
2403 *aoutSize = sizeof(afs_int32);
2407 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2410 struct vrequest *areq;
2413 struct AFS_UCRED *acred;
2414 afs_int32 *aoutSize; /* set this */ {
2415 register struct cell *tcell;
2418 if (!afs_osi_suser(acred))
2420 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2421 return EIO; /* Inappropriate ioctl for device */
2423 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2424 if (!tcell) return ENOENT;
2425 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2427 tcell->states |= CNoSUID;
2429 tcell->states &= ~CNoSUID;
2430 afs_PutCell(tcell, WRITE_LOCK);
2434 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2437 struct vrequest *areq;
2440 afs_int32 *aoutSize; /* set this */
2441 struct AFS_UCRED *acred;
2443 extern struct volume *afs_volumes[NVOLS];
2444 register afs_int32 i;
2445 register struct dcache *tdc;
2446 register struct vcache *tvc;
2447 register struct volume *tv;
2448 afs_int32 cell, volume;
2450 AFS_STATCNT(PFlushVolumeData);
2453 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2454 return EIO; /* Inappropriate ioctl for device */
2456 volume = avc->fid.Fid.Volume; /* who to zap */
2457 cell = avc->fid.Cell;
2460 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2461 * the vcaches associated with the volume.
2463 ObtainReadLock(&afs_xvcache);
2464 for(i = 0; i < VCSIZE; i++) {
2465 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2466 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2467 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2468 VN_HOLD((struct vnode *)tvc);
2472 ReleaseReadLock(&afs_xvcache);
2473 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2474 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2476 ObtainWriteLock(&tvc->lock,232);
2478 ObtainWriteLock(&afs_xcbhash, 458);
2479 afs_DequeueCallback(tvc);
2480 tvc->states &= ~(CStatd | CDirty);
2481 ReleaseWriteLock(&afs_xcbhash);
2482 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2483 osi_dnlc_purgedp(tvc);
2484 afs_TryToSmush(tvc, acred, 1);
2485 ReleaseWriteLock(&tvc->lock);
2486 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2487 afs_BozonUnlock(&tvc->pvnLock, tvc);
2489 ObtainReadLock(&afs_xvcache);
2490 /* our tvc ptr is still good until now */
2495 ReleaseReadLock(&afs_xvcache);
2498 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2499 for(i=0;i<afs_cacheFiles;i++) {
2500 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2501 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2502 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2503 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2504 if (! (afs_indexFlags[i] & IFDataMod)) {
2505 /* if the file is modified, but has a ref cnt of only 1, then
2506 someone probably has the file open and is writing into it.
2507 Better to skip flushing such a file, it will be brought back
2508 immediately on the next write anyway.
2510 If we *must* flush, then this code has to be rearranged to call
2511 afs_storeAllSegments() first */
2512 afs_FlushDCache(tdc);
2516 tdc->refCount--; /* bumped by getdslot */
2518 MReleaseWriteLock(&afs_xdcache);
2520 ObtainReadLock(&afs_xvolume);
2521 for (i=0;i<NVOLS;i++) {
2522 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2523 if (tv->volume == volume) {
2524 afs_ResetVolumeInfo(tv);
2529 ReleaseReadLock(&afs_xvolume);
2531 /* probably, a user is doing this, probably, because things are screwed up.
2532 * maybe it's the dnlc's fault? */
2539 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2542 struct vrequest *areq;
2545 afs_int32 *aoutSize; /* set this */ {
2546 register afs_int32 code;
2547 struct vcxstat stat;
2550 /* AFS_STATCNT(PGetVnodeXStatus); */
2551 if (!avc) return EINVAL;
2552 code = afs_VerifyVCache(avc, areq);
2553 if (code) return code;
2554 if (vType(avc) == VDIR)
2555 mode = PRSFS_LOOKUP;
2558 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2560 stat.fid = avc->fid;
2561 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2562 stat.lock = avc->lock;
2563 stat.parentVnode = avc->parentVnode;
2564 stat.parentUnique = avc->parentUnique;
2565 hset(stat.flushDV, avc->flushDV);
2566 hset(stat.mapDV, avc->mapDV);
2567 stat.truncPos = avc->truncPos;
2568 { /* just grab the first two - won't break anything... */
2569 struct axscache *ac;
2571 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2572 stat.randomUid[i] = ac->uid;
2573 stat.randomAccess[i] = ac->axess;
2576 stat.callback = afs_data_pointer_to_int32(avc->callback);
2577 stat.cbExpires = avc->cbExpires;
2578 stat.anyAccess = avc->anyAccess;
2579 stat.opens = avc->opens;
2580 stat.execsOrWriters = avc->execsOrWriters;
2581 stat.flockCount = avc->flockCount;
2582 stat.mvstat = avc->mvstat;
2583 stat.states = avc->states;
2584 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2585 *aoutSize = sizeof(struct vcxstat);
2590 /* We require root for local sysname changes, but not for remote */
2591 /* (since we don't really believe remote uids anyway) */
2592 /* outname[] shouldn't really be needed- this is left as an excercise */
2593 /* for the reader. */
2595 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2598 struct vrequest *areq;
2601 afs_int32 *aoutSize; /* set this */
2602 register struct AFS_UCRED *acred;
2604 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2605 int setsysname, foundname=0;
2606 register struct afs_exporter *exporter;
2607 extern struct unixuser *afs_FindUser();
2608 extern char *afs_sysname;
2609 register struct unixuser *au;
2610 register afs_int32 pag, error;
2614 AFS_STATCNT(PSetSysName);
2615 if (!afs_globalVFS) {
2616 /* Afsd is NOT running; disable it */
2617 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
2620 return (setuerror(EINVAL), EINVAL);
2623 bzero(inname, MAXSYSNAME);
2624 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2625 ain += sizeof(afs_int32);
2630 bcopy(ain, inname, t+1); /* include terminating null */
2633 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2634 pag = PagInCred(acred);
2636 return EINVAL; /* Better than panicing */
2638 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2639 return EINVAL; /* Better than panicing */
2641 if (!(exporter = au->exporter)) {
2642 afs_PutUser(au, READ_LOCK);
2643 return EINVAL; /* Better than panicing */
2645 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2647 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2649 afs_PutUser(au, READ_LOCK);
2654 afs_PutUser(au, READ_LOCK);
2656 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2658 strcpy(outname, afs_sysname);
2661 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2663 strcpy(afs_sysname, inname);
2668 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2669 cp += sizeof(afs_int32);
2671 strcpy(cp, outname);
2672 cp += strlen(outname)+1;
2674 *aoutSize = cp - aout;
2679 /* sequential search through the list of touched cells is not a good
2680 * long-term solution here. For small n, though, it should be just
2681 * fine. Should consider special-casing the local cell for large n.
2682 * Likewise for PSetSPrefs.
2684 static void ReSortCells(s,l, vlonly)
2685 int s; /* number of ids in array l[] -- NOT index of last id */
2686 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2687 int vlonly; /* sort vl servers or file servers?*/
2689 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2698 tcell = afs_GetCell(l[k], WRITE_LOCK);
2699 if (!tcell) continue;
2700 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2701 afs_PutCell(tcell, WRITE_LOCK);
2706 ObtainReadLock(&afs_xvolume);
2707 for (i= 0; i< NVOLS; i++) {
2708 for (j=afs_volumes[i];j;j=j->next) {
2710 if (j->cell == l[k]) {
2711 ObtainWriteLock(&j->lock,233);
2712 afs_SortServers(j->serverHost, MAXHOSTS);
2713 ReleaseWriteLock(&j->lock);
2718 ReleaseReadLock(&afs_xvolume);
2723 static int afs_setsprefs(sp, num, vlonly)
2726 unsigned int vlonly;
2729 int i,j,k,matches,touchedSize;
2730 struct server *srvr = NULL;
2731 afs_int32 touched[34];
2735 for (k=0; k < num; sp++, k++) {
2737 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2740 ObtainReadLock(&afs_xserver);
2742 i = SHash(sp->host.s_addr);
2743 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2744 if (sa->sa_ip == sp->host.s_addr) {
2746 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2747 || (sa->sa_portal == AFS_FSPORT);
2748 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2755 if (sa && matches) { /* found one! */
2757 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2759 sa->sa_iprank = sp->rank + afs_randomMod15();
2760 afs_SortOneServer(sa->server);
2763 /* if we don't know yet what cell it's in, this is moot */
2764 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2765 /* is it in our list of touched cells ? */ ;
2766 if (j < 0) { /* no, it's not */
2767 touched[touchedSize++] = srvr->cell->cell;
2768 if (touchedSize >= 32) { /* watch for ovrflow */
2769 ReleaseReadLock(&afs_xserver);
2770 ReSortCells(touchedSize, touched, vlonly);
2772 ObtainReadLock(&afs_xserver);
2778 ReleaseReadLock(&afs_xserver);
2779 /* if we didn't find one, start to create one. */
2780 /* Note that it doesn't have a cell yet... */
2782 afs_uint32 temp = sp->host.s_addr;
2783 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2784 WRITE_LOCK, (afsUUID *)0,0);
2785 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2786 afs_PutServer(srvr, WRITE_LOCK);
2788 } /* for all cited preferences */
2790 ReSortCells(touchedSize, touched, vlonly);
2794 /* Note that this may only be performed by the local root user.
2797 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2800 struct vrequest *areq;
2803 struct AFS_UCRED *acred;
2804 afs_int32 *aoutSize;
2806 struct setspref *ssp;
2807 AFS_STATCNT(PSetSPrefs);
2809 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2810 return EIO; /* Inappropriate ioctl for device */
2812 if (!afs_osi_suser(acred))
2815 if (ainSize < sizeof(struct setspref))
2818 ssp = (struct setspref *)ain;
2819 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2822 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2823 (ssp->flags & DBservers));
2828 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2831 struct vrequest *areq;
2834 struct AFS_UCRED *acred;
2835 afs_int32 *aoutSize;
2838 AFS_STATCNT(PSetSPrefs);
2839 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2840 return EIO; /* Inappropriate ioctl for device */
2843 if (!afs_osi_suser(acred))
2846 sp = (struct spref *)ain;
2847 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2851 /* some notes on the following code...
2852 * in the hash table of server structs, all servers with the same IP address
2853 * will be on the same overflow chain.
2854 * This could be sped slightly in some circumstances by having it cache the
2855 * immediately previous slot in the hash table and some supporting information
2856 * Only reports file servers now.
2859 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2862 struct vrequest *areq;
2865 afs_int32 *aoutSize;
2867 struct sprefrequest *spin; /* input */
2868 struct sprefinfo *spout; /* output */
2869 struct spref *srvout; /* one output component */
2870 int i,j; /* counters for hash table traversal */
2871 struct server *srvr; /* one of CM's server structs */
2874 int vlonly; /* just return vlservers ? */
2877 AFS_STATCNT(PGetSPrefs);
2878 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2879 return EIO; /* Inappropriate ioctl for device */
2882 if (ainSize < sizeof (struct sprefrequest_33)) {
2886 spin = ((struct sprefrequest *) ain);
2889 if (ainSize > sizeof (struct sprefrequest_33)) {
2890 vlonly = (spin->flags & DBservers);
2894 /* struct sprefinfo includes 1 server struct... that size gets added
2895 * in during the loop that follows.
2897 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2898 spout = (struct sprefinfo *) aout;
2899 spout->next_offset = spin->offset;
2900 spout->num_servers = 0;
2901 srvout = spout->servers;
2903 ObtainReadLock(&afs_xserver);
2904 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2905 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2906 if (spin->offset > (unsigned short)i) {
2907 continue; /* catch up to where we left off */
2909 spout->next_offset++;
2912 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2913 || (sa->sa_portal == AFS_FSPORT);
2915 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2916 /* only report ranks for vl servers */
2920 srvout->host.s_addr = sa->sa_ip;
2921 srvout->rank = sa->sa_iprank;
2922 *aoutSize += sizeof(struct spref);
2923 spout->num_servers++;
2926 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2927 ReleaseReadLock(&afs_xserver); /* no more room! */
2932 ReleaseReadLock(&afs_xserver);
2934 spout->next_offset = 0; /* start over from the beginning next time */
2938 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2939 int afs_NFSRootOnly = 1;
2940 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2943 struct vrequest *areq;
2946 afs_int32 *aoutSize; /* set this */
2947 struct AFS_UCRED *acred;
2949 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2950 extern struct afs_exporter *exporter_find();
2951 register struct afs_exporter *exporter;
2953 AFS_STATCNT(PExportAfs);
2954 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
2955 type = handleValue >> 24;
2960 exporter = exporter_find(type);
2962 export = handleValue & 3;
2963 changestate = handleValue & 0xff;
2964 smounts = (handleValue >> 2) & 3;
2965 pwsync = (handleValue >> 4) & 3;
2966 convmode = (handleValue >> 6) & 3;
2968 changestate = (handleValue >> 16) & 0x1;
2969 convmode = (handleValue >> 16) & 0x2;
2970 pwsync = (handleValue >> 16) & 0x4;
2971 smounts = (handleValue >> 16) & 0x8;
2972 export = handleValue & 0xff;
2975 /* Failed finding desired exporter; */
2979 handleValue = exporter->exp_states;
2980 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2981 *aoutSize = sizeof(afs_int32);
2983 if (!afs_osi_suser(acred))
2984 return EACCES; /* Only superuser can do this */
2988 exporter->exp_states |= EXP_EXPORTED;
2990 exporter->exp_states &= ~EXP_EXPORTED;
2994 exporter->exp_states |= EXP_UNIXMODE;
2996 exporter->exp_states &= ~EXP_UNIXMODE;
3000 exporter->exp_states |= EXP_PWSYNC;
3002 exporter->exp_states &= ~EXP_PWSYNC;
3006 afs_NFSRootOnly = 0;
3007 exporter->exp_states |= EXP_SUBMOUNTS;
3009 afs_NFSRootOnly = 1;
3010 exporter->exp_states &= ~EXP_SUBMOUNTS;
3013 handleValue = exporter->exp_states;
3014 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3015 *aoutSize = sizeof(afs_int32);
3018 exporter->exp_states |= EXP_EXPORTED;
3020 exporter->exp_states &= ~EXP_EXPORTED;
3022 exporter->exp_states |= EXP_UNIXMODE;
3024 exporter->exp_states &= ~EXP_UNIXMODE;
3026 exporter->exp_states |= EXP_PWSYNC;
3028 exporter->exp_states &= ~EXP_PWSYNC;
3030 afs_NFSRootOnly = 0;
3031 exporter->exp_states |= EXP_SUBMOUNTS;
3033 afs_NFSRootOnly = 1;
3034 exporter->exp_states &= ~EXP_SUBMOUNTS;
3043 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3046 struct vrequest *areq;
3049 struct AFS_UCRED *acred;
3050 afs_int32 *aoutSize; /* set this */
3052 struct gaginfo *gagflags;
3054 if (!afs_osi_suser(acred))
3057 gagflags = (struct gaginfo *) ain;
3058 afs_showflags = gagflags->showflags;
3065 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3068 struct vrequest *areq;
3071 struct AFS_UCRED *acred;
3072 afs_int32 *aoutSize;
3074 struct rxparams *rxp;
3076 if (!afs_osi_suser(acred))
3079 rxp = (struct rxparams *) ain;
3081 if (rxp->rx_initReceiveWindow)
3082 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3083 if (rxp->rx_maxReceiveWindow)
3084 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3085 if (rxp->rx_initSendWindow)
3086 rx_initSendWindow = rxp->rx_initSendWindow;
3087 if (rxp->rx_maxSendWindow)
3088 rx_maxSendWindow = rxp->rx_maxSendWindow;
3089 if (rxp->rxi_nSendFrags)
3090 rxi_nSendFrags = rxp->rxi_nSendFrags;
3091 if (rxp->rxi_nRecvFrags)
3092 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3093 if (rxp->rxi_OrphanFragSize)
3094 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3095 if (rxp->rx_maxReceiveSize)
3097 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3098 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3100 if (rxp->rx_MyMaxSendSize)
3101 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3106 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3109 struct vrequest *areq;
3113 afs_int32 *aoutSize; /* set this */
3115 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3118 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3119 *aoutSize = sizeof(struct cm_initparams);
3123 #ifdef AFS_SGI65_ENV
3124 /* They took crget() from us, so fake it. */
3125 static cred_t *crget(void)
3128 cr = crdup(get_current_cred());
3129 bzero((char*)cr, sizeof(cred_t));
3130 #if CELL || CELL_PREPARE
3138 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3141 struct vrequest *areq;
3144 afs_int32 *aoutSize;
3145 struct AFS_UCRED *acred;
3147 bcopy((char *)&cryptall, aout, sizeof(int32));
3148 *aoutSize=sizeof(afs_int32);
3153 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3156 struct vrequest *areq;
3159 afs_int32 *aoutSize;
3160 struct AFS_UCRED *acred;
3164 if (!afs_osi_suser(acred))
3166 if (ainSize != sizeof(afs_int32) || ain == NULL)
3168 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3169 /* if new mappings added later this will need to be changed */
3170 if (tmpval != 0 && tmpval != 1)
3177 * Create new credentials to correspond to a remote user with given
3178 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3179 * provide pioctl (and other) services to foreign clients (i.e. nfs
3180 * clients) by using this call to `become' the client.
3183 #define PIOCTL_HEADER 6
3184 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3187 afs_uint32 hostaddr;
3188 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3189 extern struct afs_exporter *exporter_find();
3190 struct afs_exporter *exporter, *outexporter;
3191 struct AFS_UCRED *newcred;
3192 struct unixuser *au;
3194 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3195 return EINVAL; /* NFS trans not supported for Ultrix */
3197 #if defined(AFS_SGIMP_ENV)
3198 osi_Assert(ISAFS_GLOCK());
3200 AFS_STATCNT(HandleClientContext);
3201 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3202 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3203 return EINVAL; /* Too small to be good */
3205 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3206 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3208 osi_FreeLargeSpace(inData);
3212 /* Extract information for remote user */
3213 hostaddr = *((afs_uint32 *)ain);
3214 ain += sizeof(hostaddr);
3215 uid = *((afs_uint32 *)ain);
3217 g0 = *((afs_uint32 *)ain);
3219 g1 = *((afs_uint32 *)ain);
3221 *com = *((afs_uint32 *)ain);
3222 ain += sizeof(afs_int32);
3223 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3226 * Of course, one must be root for most of these functions, but
3227 * we'll allow (for knfs) you to set things if the pag is 0 and
3228 * you're setting tokens or unlogging.
3231 if (!afs_osi_suser(credp)) {
3233 #ifndef AFS_SGI64_ENV
3234 /* Since SGI's suser() returns explicit failure after the call.. */
3238 /* check for acceptable opcodes for normal folks, which are, so far,
3239 * set tokens and unlog.
3241 if (i != 9 && i != 3 && i != 38 && i != 8) {
3242 osi_FreeLargeSpace(inData);
3247 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3248 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3249 osi_FreeLargeSpace(inData);
3252 * We map uid 0 to nobody to match the mapping that the nfs
3253 * server does and to ensure that the suser() calls in the afs
3254 * code fails for remote client roots.
3256 uid = afs_nobody; /* NFS_NOBODY == -2 */
3259 #ifdef AFS_AIX41_ENV
3262 newcred->cr_gid = RMTUSER_REQ;
3263 newcred->cr_groups[0] = g0;
3264 newcred->cr_groups[1] = g1;
3266 newcred->cr_ngrps = 2;
3268 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3269 newcred->cr_ngroups = 2;
3271 for (i=2; i<NGROUPS; i++)
3272 newcred->cr_groups[i] = NOGROUP;
3275 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3276 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3278 if (!(exporter = exporter_find(exporter_type))) {
3279 /* Exporter wasn't initialized or an invalid exporter type */
3283 if (exporter->exp_states & EXP_PWSYNC) {
3284 if (uid != credp->cr_uid) {
3286 return ENOEXEC; /* XXX Find a better errno XXX */
3289 newcred->cr_uid = uid; /* Only temporary */
3290 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3291 /* The client's pag is the only unique identifier for it */
3292 newcred->cr_uid = pag;
3294 if (!code && *com == PSETPAG) {
3295 /* Special case for 'setpag' */
3296 afs_uint32 pagvalue = genpag();
3298 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3300 * Note that we leave the 'outexporter' struct held so it won't
3303 au->exporter = outexporter;
3304 if (ablob->out_size >= 4) {
3305 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3307 afs_PutUser(au, WRITE_LOCK);
3308 if (code) return code;
3309 return PSETPAG; /* Special return for setpag */
3311 EXP_RELE(outexporter);
3314 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3317 /* get all interface addresses of this client */
3320 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3323 struct vrequest *areq;
3326 afs_int32 *aoutSize;
3328 struct sprefrequest *spin; /* input */
3329 struct sprefinfo *spout; /* output */
3330 struct spref *srvout; /* one output component */
3334 AFS_STATCNT(PGetCPrefs);
3335 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3336 return EIO; /* Inappropriate ioctl for device */
3338 if ( ainSize < sizeof (struct sprefrequest ))
3341 spin = (struct sprefrequest *) ain;
3342 spout = (struct sprefinfo *) aout;
3344 maxNumber = spin->num_servers; /* max addrs this time */
3345 srvout = spout->servers;
3347 ObtainReadLock(&afs_xinterface);
3349 /* copy out the client interface information from the
3350 ** kernel data structure "interface" to the output buffer
3352 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3353 && ( j< maxNumber) ; i++, j++, srvout++)
3354 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3356 spout->num_servers = j;
3357 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3359 if ( i >= afs_cb_interface.numberOfInterfaces )
3360 spout->next_offset = 0; /* start from beginning again */
3362 spout->next_offset = spin->offset + j;
3364 ReleaseReadLock(&afs_xinterface);
3369 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3372 struct vrequest *areq;
3375 afs_int32 *aoutSize;
3377 struct setspref *sin;
3380 AFS_STATCNT(PSetCPrefs);
3381 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3382 return EIO; /* Inappropriate ioctl for device */
3384 sin = (struct setspref *)ain;
3386 if ( ainSize < sizeof(struct setspref) )
3388 #if 0 /* num_servers is unsigned */
3389 if ( sin->num_servers < 0 )
3392 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3395 ObtainWriteLock(&afs_xinterface, 412);
3396 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3397 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3398 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3400 ReleaseWriteLock(&afs_xinterface);
3404 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3407 struct vrequest *areq;
3410 afs_int32 *aoutSize;
3411 struct AFS_UCRED *acred; {
3412 register afs_int32 code;
3413 register struct vcache *tvc;
3414 register struct dcache *tdc;
3415 struct VenusFid tfid;
3417 afs_int32 offset, len, hasatsys=0;
3419 AFS_STATCNT(PFlushMount);
3420 if (!avc) return EINVAL;
3421 code = afs_VerifyVCache(avc, areq);
3422 if (code) return code;
3423 if (vType(avc) != VDIR) {
3426 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3427 if (!tdc) return ENOENT;
3428 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3429 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3434 tfid.Cell = avc->fid.Cell;
3435 tfid.Fid.Volume = avc->fid.Fid.Volume;
3436 afs_PutDCache(tdc); /* we're done with the data */
3437 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3438 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3440 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3447 if (vType(tvc) != VLNK) {
3448 afs_PutVCache(tvc, WRITE_LOCK);
3452 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3453 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3455 ObtainWriteLock(&tvc->lock,645);
3456 ObtainWriteLock(&afs_xcbhash, 646);
3457 afs_DequeueCallback(tvc);
3458 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3459 ReleaseWriteLock(&afs_xcbhash);
3460 /* now find the disk cache entries */
3461 afs_TryToSmush(tvc, acred, 1);
3462 osi_dnlc_purgedp(tvc);
3463 afs_symhint_inval(tvc);
3464 if (tvc->linkData && !(tvc->states & CCore)) {
3465 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3466 tvc->linkData = (char *) 0;
3468 ReleaseWriteLock(&tvc->lock);
3469 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3470 afs_BozonUnlock(&tvc->pvnLock, tvc);
3472 afs_PutVCache(tvc, WRITE_LOCK);
3474 if (hasatsys) osi_FreeLargeSpace(bufp);
3478 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3481 struct vrequest *areq;
3484 afs_int32 *aoutSize;
3485 struct AFS_UCRED *acred;
3490 if (!afs_osi_suser(acred)) {
3494 if (ainSize != sizeof(afs_int32)) {
3498 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3499 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3503 if (flags & AFSCALL_RXSTATS_ENABLE) {
3504 rx_enableProcessRPCStats();
3506 if (flags & AFSCALL_RXSTATS_DISABLE) {
3507 rx_disableProcessRPCStats();
3509 if (flags & AFSCALL_RXSTATS_CLEAR) {
3510 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3518 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3521 struct vrequest *areq;
3524 afs_int32 *aoutSize;
3525 struct AFS_UCRED *acred;
3530 if (!afs_osi_suser(acred)) {
3534 if (ainSize != sizeof(afs_int32)) {
3538 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3539 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3543 if (flags & AFSCALL_RXSTATS_ENABLE) {
3544 rx_enablePeerRPCStats();
3546 if (flags & AFSCALL_RXSTATS_DISABLE) {
3547 rx_disablePeerRPCStats();
3549 if (flags & AFSCALL_RXSTATS_CLEAR) {
3550 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);