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;
48 static int PBogus(), PSetAcl(), PGetAcl(), PSetTokens(), PGetVolumeStatus();
49 static int PSetVolumeStatus(), PFlush(), PNewStatMount(), PGetTokens(), PUnlog();
50 static int PCheckServers(), PCheckVolNames(), PCheckAuth(), PFindVolume();
51 static int PViceAccess(), PSetCacheSize(), Prefetch();
52 static int PRemoveCallBack(), PNewCell(), PListCells(), PRemoveMount();
53 static int PMariner(), PGetUserCell(), PGetWSCell(), PGetFileCell();
54 static int PVenusLogging(), PNoop(), PSetCellStatus(), PGetCellStatus();
55 static int PFlushVolumeData(), PGetCacheSize();
56 static int PSetSysName(),PGetFID();
57 static int PGetVnodeXStatus();
58 static int PSetSPrefs(), PGetSPrefs(), PGag(), PTwiddleRx();
59 static int PSetSPrefs33(), PStoreBehind(), PGCPAGs();
60 static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */
61 static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer();
64 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
66 extern struct cm_initparams cm_initParams;
68 static int (*(pioctlSw[]))() = {
73 PGetVolumeStatus, /* 4 */
74 PSetVolumeStatus, /* 5 */
79 PCheckServers, /* 10 */
80 PCheckVolNames, /* 11 */
82 PBogus, /* 13 -- used to be quick check time */
84 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
85 PBogus, /* 16 -- used to be testing code */
86 PNoop, /* 17 -- used to be enable group */
87 PNoop, /* 18 -- used to be disable group */
88 PBogus, /* 19 -- used to be list group */
90 PUnlog, /* 21 -- unlog *is* unpag in this system */
91 PGetFID, /* 22 -- get file ID */
92 PBogus, /* 23 -- used to be waitforever */
93 PSetCacheSize, /* 24 */
94 PRemoveCallBack, /* 25 -- flush only the callback */
97 PRemoveMount, /* 28 -- delete mount point */
98 PNewStatMount, /* 29 -- new style mount point stat */
99 PGetFileCell, /* 30 -- get cell name for input file */
100 PGetWSCell, /* 31 -- get cell name for workstation */
101 PMariner, /* 32 - set/get mariner host */
102 PGetUserCell, /* 33 -- get cell name for user */
103 PVenusLogging, /* 34 -- Enable/Disable logging */
104 PGetCellStatus, /* 35 */
105 PSetCellStatus, /* 36 */
106 PFlushVolumeData, /* 37 -- flush all data from a volume */
107 PSetSysName, /* 38 - Set system name */
108 PExportAfs, /* 39 - Export Afs to remote nfs clients */
109 PGetCacheSize, /* 40 - get cache size and usage */
110 PGetVnodeXStatus, /* 41 - get vcache's special status */
111 PSetSPrefs33, /* 42 - Set CM Server preferences... */
112 PGetSPrefs, /* 43 - Get CM Server preferences... */
113 PGag, /* 44 - turn off/on all CM messages */
114 PTwiddleRx, /* 45 - adjust some RX params */
115 PSetSPrefs, /* 46 - Set CM Server preferences... */
116 PStoreBehind, /* 47 - set degree of store behind to be done */
117 PGCPAGs, /* 48 - disable automatic pag gc-ing */
118 PGetInitParams, /* 49 - get initial cm params */
119 PGetCPrefs, /* 50 - get client interface addresses */
120 PSetCPrefs, /* 51 - set client interface addresses */
121 PFlushMount, /* 52 - flush mount symlink data */
122 PRxStatProc, /* 53 - control process RX statistics */
123 PRxStatPeer, /* 54 - control peer RX statistics */
124 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
125 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
126 PNoop, /* 57 -- arla: set file prio */
127 PNoop, /* 58 -- arla: fallback getfh */
128 PNoop, /* 59 -- arla: fallback fhopen */
129 PNoop, /* 60 -- arla: controls xfsdebug */
130 PNoop, /* 61 -- arla: controls arla debug */
131 PNoop, /* 62 -- arla: debug interface */
132 PNoop, /* 63 -- arla: print xfs status */
133 PNoop, /* 64 -- arla: force cache check */
134 PNoop, /* 65 -- arla: break callback */
137 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
138 int afs_nobody = NFS_NOBODY;
141 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
143 dst->in = (char *)(unsigned long)src->in;
144 dst->out = (char *)(unsigned long)src->out;
145 dst->in_size = src->in_size;
146 dst->out_size = src->out_size;
150 * If you need to change copyin_afs_ioctl(), you may also need to change
155 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
159 #if defined(AFS_HPUX_64BIT_ENV)
160 struct afs_ioctl32 dst32;
162 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
164 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
166 afs_ioctl32_to_afs_ioctl(&dst32, dst);
169 #endif /* defined(AFS_HPUX_64BIT_ENV) */
171 #if defined(AFS_SUN57_64BIT_ENV)
172 struct afs_ioctl32 dst32;
174 if (get_udatamodel() == DATAMODEL_ILP32) {
175 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
177 afs_ioctl32_to_afs_ioctl(&dst32, dst);
180 #endif /* defined(AFS_SUN57_64BIT_ENV) */
182 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
183 struct afs_ioctl32 dst32;
185 if (!ABI_IS_64BIT(get_current_abi()))
187 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
189 afs_ioctl32_to_afs_ioctl(&dst32, dst);
192 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
194 #if defined(AFS_LINUX_64BIT_KERNEL)
195 struct afs_ioctl32 dst32;
197 #ifdef AFS_SPARC64_LINUX20_ENV
198 if (current->tss.flags & SPARC_FLAG_32BIT) {
200 #error Not done for this linux type
202 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
204 afs_ioctl32_to_afs_ioctl(&dst32, dst);
207 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
209 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
213 HandleIoctl(avc, acom, adata)
214 register struct vcache *avc;
215 register afs_int32 acom;
216 struct afs_ioctl *adata; {
217 register afs_int32 code;
220 AFS_STATCNT(HandleIoctl);
222 switch(acom & 0xff) {
224 avc->states |= CSafeStore;
228 /* case 2 used to be abort store, but this is no longer provided,
229 since it is impossible to implement under normal Unix.
233 /* return the name of the cell this file is open on */
234 register struct cell *tcell;
235 register afs_int32 i;
237 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
239 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
241 if (i > adata->out_size) {
242 /* 0 means we're not interested in the output */
243 if (adata->out_size != 0) code = EFAULT;
247 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
249 afs_PutCell(tcell, READ_LOCK);
255 case 49: /* VIOC_GETINITPARAMS */
256 if (adata->out_size < sizeof(struct cm_initparams)) {
260 AFS_COPYOUT(&cm_initParams, adata->out,
261 sizeof(struct cm_initparams), code);
270 return code; /* so far, none implemented */
275 /* For aix we don't temporarily bypass ioctl(2) but rather do our
276 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
277 * is now called from afs_gn_ioctl.
279 afs_ioctl(tvc, cmd, arg)
284 struct afs_ioctl data;
287 AFS_STATCNT(afs_ioctl);
288 if (((cmd >> 8) & 0xff) == 'V') {
289 /* This is a VICEIOCTL call */
290 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
293 error = HandleIoctl(tvc, cmd, &data);
296 /* No-op call; just return. */
300 #endif /* AFS_AIX_ENV */
302 #if defined(AFS_SGI_ENV)
303 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
309 struct afs_ioctl data;
315 AFS_STATCNT(afs_ioctl);
316 if (((cmd >> 8) & 0xff) == 'V') {
317 /* This is a VICEIOCTL call */
318 error = copyin_afs_ioctl(arg, &data);
321 locked = ISAFS_GLOCK();
324 error = HandleIoctl(tvc, cmd, &data);
329 /* No-op call; just return. */
333 #endif /* AFS_SGI_ENV */
336 /* unlike most calls here, this one uses u.u_error to return error conditions,
337 since this is really an intercepted chapter 2 call, rather than a vnode
340 /* AFS_HPUX102 and up uses VNODE ioctl instead */
341 #ifndef AFS_HPUX102_ENV
342 #if !defined(AFS_SGI_ENV)
344 kioctl(fdes, com, arg, ext)
351 } u_uap, *uap = &u_uap;
355 struct afs_ioctl_sys {
361 afs_xioctl (uap, rvp)
362 struct afs_ioctl_sys *uap;
367 afs_xioctl (p, args, retval)
376 } *uap = (struct a *)args;
377 #else /* AFS_OSF_ENV */
378 #ifdef AFS_LINUX22_ENV
379 struct afs_ioctl_sys {
383 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
384 unsigned int com, unsigned long arg)
386 struct afs_ioctl_sys ua, *uap = &ua;
394 } *uap = (struct a *)u.u_ap;
395 #endif /* AFS_LINUX22_ENV */
396 #endif /* AFS_OSF_ENV */
397 #endif /* AFS_SUN5_ENV */
399 #ifndef AFS_LINUX22_ENV
400 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
403 register struct file *fd;
406 register struct vcache *tvc;
407 register int ioctlDone = 0, code = 0;
409 AFS_STATCNT(afs_xioctl);
410 #ifdef AFS_LINUX22_ENV
418 if (setuerror(getf(uap->fd, &fd))) {
424 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
426 #else /* AFS_OSF_ENV */
428 #if defined(AFS_SUN57_ENV)
430 if (!fd) return(EBADF);
431 #elif defined(AFS_SUN54_ENV)
433 if (!fd) return(EBADF);
435 if (code = getf(uap->fd, &fd)) {
447 /* first determine whether this is any sort of vnode */
448 #ifdef AFS_LINUX22_ENV
449 tvc = (struct vcache *)ip;
453 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
455 if (fd->f_type == DTYPE_VNODE) {
457 /* good, this is a vnode; next see if it is an AFS vnode */
458 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
459 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
461 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
463 #endif /* AFS_LINUX22_ENV */
464 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
466 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
467 if (!tvc) { /* shouldn't happen with held gnodes */
472 /* This is an AFS vnode */
473 if (((uap->com >> 8) & 0xff) == 'V') {
474 register struct afs_ioctl *datap;
476 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
477 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
479 osi_FreeSmallSpace(datap);
481 #if defined(AFS_SUN5_ENV)
496 #else /* AFS_OSF_ENV */
500 #ifdef AFS_LINUX22_ENV
509 code = HandleIoctl(tvc, uap->com, datap);
510 osi_FreeSmallSpace(datap);
524 #if defined(AFS_LINUX22_ENV)
534 code = okioctl(fdes, com, arg, ext);
538 okioctl(fdes, com, arg, ext);
540 #if defined(AFS_SUN5_ENV)
541 #if defined(AFS_SUN57_ENV)
543 #elif defined(AFS_SUN54_ENV)
548 code = ioctl(uap, rvp);
551 code = ioctl(p, args, retval);
558 #else /* AFS_OSF_ENV */
559 #ifndef AFS_LINUX22_ENV
576 #ifdef AFS_LINUX22_ENV
579 #if !defined(AFS_OSF_ENV)
582 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
583 return (getuerror() ? -1 : u.u_ioctlrv);
585 return getuerror() ? -1 : 0;
588 #endif /* AFS_LINUX22_ENV */
589 #endif /* AFS_SUN5_ENV */
594 #endif /* AFS_SGI_ENV */
595 #endif /* AFS_HPUX102_ENV */
597 #if defined(AFS_SGI_ENV)
598 /* "pioctl" system call entry point; just pass argument to the parameterized
607 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
611 AFS_STATCNT(afs_pioctl);
613 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
621 #endif /* AFS_SGI_ENV */
624 afs_pioctl(p, args, retval)
634 } *uap = (struct a *) args;
636 AFS_STATCNT(afs_pioctl);
637 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
640 extern struct mount *afs_globalVFS;
641 #else /* AFS_OSF_ENV */
642 extern struct vfs *afs_globalVFS;
645 /* macro to avoid adding any more #ifdef's to pioctl code. */
646 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
647 #define PIOCTL_FREE_CRED() crfree(credp)
649 #define PIOCTL_FREE_CRED()
653 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
655 struct AFS_UCRED *credp;
657 afs_syscall_pioctl(path, com, cmarg, follow)
664 struct afs_ioctl data;
665 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
666 register afs_int32 code = 0;
672 struct ucred *credp = crref(); /* don't free until done! */
674 #ifdef AFS_LINUX22_ENV
675 cred_t *credp = crref(); /* don't free until done! */
678 AFS_STATCNT(afs_syscall_pioctl);
679 if (follow) follow = 1; /* compat. with old venus */
681 if (! _VALIDVICEIOCTL(com)) {
685 #else /* AFS_OSF_ENV */
686 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
695 code = copyin_afs_ioctl(cmarg, &data);
698 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
705 if ((com & 0xff) == PSetClientContext) {
706 #ifdef AFS_LINUX22_ENV
707 return EINVAL; /* Not handling these yet. */
709 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
710 code = HandleClientContext(&data, &com, &foreigncreds, credp);
712 #if defined(AFS_HPUX101_ENV)
713 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
716 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
718 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
719 #endif /* AFS_SGI_ENV */
724 crfree(foreigncreds);
727 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
730 return (setuerror(code), code);
734 #ifndef AFS_LINUX22_ENV
737 * We could have done without temporary setting the u.u_cred below
738 * (foreigncreds could be passed as param the pioctl modules)
739 * but calls such as afs_osi_suser() doesn't allow that since it
740 * references u.u_cred directly. We could, of course, do something
741 * like afs_osi_suser(cred) which, I think, is better since it
742 * generalizes and supports multi cred environments...
746 credp = foreigncreds;
749 tmpcred = crref(); /* XXX */
752 #if defined(AFS_HPUX101_ENV)
753 tmpcred = p_cred(u.u_procp);
754 set_p_cred(u.u_procp, foreigncreds);
757 tmpcred = OSI_GET_CURRENT_CRED();
758 OSI_SET_CURRENT_CRED(foreigncreds);
761 u.u_cred = foreigncreds;
762 #endif /* AFS_SGI64_ENV */
763 #endif /* AFS_HPUX101_ENV */
768 if ((com & 0xff) == 15) {
769 /* special case prefetch so entire pathname eval occurs in helper process.
770 otherwise, the pioctl call is essentially useless */
771 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
772 code = Prefetch(path, &data, follow,
773 foreigncreds ? foreigncreds : credp);
775 #if defined(AFS_HPUX101_ENV)
776 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
779 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
781 code = Prefetch(path, &data, follow, u.u_cred);
782 #endif /* AFS_SGI64_ENV */
783 #endif /* AFS_HPUX101_ENV */
785 #ifndef AFS_LINUX22_ENV
788 crset(tmpcred); /* restore original credentials */
790 #if defined(AFS_HPUX101_ENV)
791 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
795 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
797 u.u_cred = tmpcred; /* restore original credentials */
800 #endif /* AFS_HPUX101_ENV */
801 crfree(foreigncreds);
804 #endif /* AFS_LINUX22_ENV */
806 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
809 return (setuerror(code), code);
815 code = lookupname(path, USR, follow, NULL, &vp,
816 foreigncreds ? foreigncreds : credp);
818 #ifdef AFS_LINUX22_ENV
819 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
821 vp = (struct vnode *)dp->d_inode;
823 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
824 #endif /* AFS_LINUX22_ENV */
825 #endif /* AFS_AIX41_ENV */
828 #ifndef AFS_LINUX22_ENV
831 crset(tmpcred); /* restore original credentials */
833 #if defined(AFS_HPUX101_ENV)
834 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
836 #if !defined(AFS_SUN5_ENV)
838 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
840 u.u_cred = tmpcred; /* restore original credentials */
841 #endif /* AFS_SGI64_ENV */
843 #endif /* AFS_HPUX101_ENV */
844 crfree(foreigncreds);
847 #endif /* AFS_LINUX22_ENV */
849 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
852 return(setuerror(code), code);
856 else vp = (struct vnode *) 0;
858 /* now make the call if we were passed no file, or were passed an AFS file */
859 if (!vp || IsAfsVnode(vp)) {
861 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
862 * So, we must test in this part of the code. Also, must arrange to
863 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
864 * we hold gnodes, whose references hold our vcache entries.
867 gp = vp; /* remember for "put" */
868 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
870 else gp = (struct vnode *) 0;
873 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
877 struct ucred *cred1, *cred2;
880 cred1 = cred2 = foreigncreds;
882 cred1 = cred2 = credp;
884 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
885 if (cred1 != cred2) {
886 /* something changed the creds */
891 #if defined(AFS_HPUX101_ENV)
893 struct ucred *cred = p_cred(u.u_procp);
894 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
900 credp = OSI_GET_CURRENT_CRED();
901 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
904 #ifdef AFS_LINUX22_ENV
905 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
907 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
909 #endif /* AFS_SGI_ENV */
910 #endif /* AFS_HPUX101_ENV */
911 #endif /* AFS_AIX41_ENV */
912 #endif /* AFS_SUN5_ENV */
914 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
915 code = EINVAL; /* not in /afs */
922 vp = (struct vnode *) 0;
927 #ifndef AFS_LINUX22_ENV
932 #if defined(AFS_HPUX101_ENV)
933 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
937 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
939 u.u_cred = tmpcred; /* restore original credentials */
940 #endif /* ASF_SGI64_ENV */
942 #endif /* AFS_HPUX101_ENV */
943 crfree(foreigncreds);
946 #endif /* AFS_LINUX22_ENV */
948 #ifdef AFS_LINUX22_ENV
951 AFS_RELE(vp); /* put vnode back */
955 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
960 return (getuerror());
965 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
966 register struct vcache *avc;
968 struct AFS_UCRED **acred;
969 register struct afs_ioctl *ablob;
972 struct vrequest treq;
973 register afs_int32 code;
974 register afs_int32 function;
975 afs_int32 inSize, outSize;
976 char *inData, *outData;
978 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
979 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
980 AFS_STATCNT(HandlePioctl);
981 if (code = afs_InitReq(&treq, *acred)) return code;
982 function = acom & 0xff;
983 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
984 return EINVAL; /* out of range */
986 inSize = ablob->in_size;
987 if (inSize >= PIGGYSIZE) return E2BIG;
988 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
990 AFS_COPYIN(ablob->in, inData, inSize, code);
994 osi_FreeLargeSpace(inData);
997 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
999 if (function == 3) /* PSetTokens */
1000 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1002 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1003 osi_FreeLargeSpace(inData);
1004 if (code == 0 && ablob->out_size > 0) {
1005 if (outSize > ablob->out_size) outSize = ablob->out_size;
1006 if (outSize >= PIGGYSIZE) code = E2BIG;
1008 AFS_COPYOUT(outData, ablob->out, outSize, code);
1010 osi_FreeLargeSpace(outData);
1011 return afs_CheckCode(code, &treq, 41);
1014 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1017 struct vrequest *areq;
1020 afs_int32 *aoutSize; /* set this */ {
1021 register afs_int32 code;
1023 AFS_STATCNT(PGetFID);
1024 if (!avc) return EINVAL;
1025 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1026 *aoutSize = sizeof(struct VenusFid);
1030 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1033 struct vrequest *areq;
1036 afs_int32 *aoutSize; /* set this */ {
1037 register afs_int32 code;
1039 struct AFSOpaque acl;
1040 struct AFSVolSync tsync;
1041 struct AFSFetchStatus OutStatus;
1044 AFS_STATCNT(PSetAcl);
1047 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1050 acl.AFSOpaque_val = ain;
1052 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1054 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1055 #ifdef RX_ENABLE_LOCKS
1057 #endif /* RX_ENABLE_LOCKS */
1058 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1059 &acl, &OutStatus, &tsync);
1060 #ifdef RX_ENABLE_LOCKS
1062 #endif /* RX_ENABLE_LOCKS */
1067 (afs_Analyze(tconn, code, &avc->fid, areq,
1068 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1070 /* now we've forgotten all of the access info */
1071 ObtainWriteLock(&afs_xcbhash, 455);
1073 afs_DequeueCallback(avc);
1074 avc->states &= ~(CStatd | CUnique);
1075 ReleaseWriteLock(&afs_xcbhash);
1076 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1077 osi_dnlc_purgedp(avc);
1081 int afs_defaultAsynchrony = 0;
1083 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1086 struct vrequest *areq;
1089 afs_int32 *aoutSize; /* set this */
1090 struct AFS_UCRED *acred;
1093 struct sbstruct *sbr;
1095 sbr = (struct sbstruct *)ain;
1096 if (sbr->sb_default != -1) {
1097 if (afs_osi_suser(acred))
1098 afs_defaultAsynchrony = sbr->sb_default;
1102 if (avc && (sbr->sb_thisfile != -1))
1103 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1104 areq, DONT_CHECK_MODE_BITS))
1105 avc->asynchrony = sbr->sb_thisfile;
1108 *aoutSize = sizeof(struct sbstruct);
1109 sbr = (struct sbstruct *)aout;
1110 sbr->sb_default = afs_defaultAsynchrony;
1112 sbr->sb_thisfile = avc->asynchrony;
1118 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1121 struct vrequest *areq;
1124 afs_int32 *aoutSize; /* set this */
1125 struct AFS_UCRED *acred;
1127 if (!afs_osi_suser(acred)) {
1130 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1134 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1137 struct vrequest *areq;
1140 afs_int32 *aoutSize; /* set this */ {
1141 struct AFSOpaque acl;
1142 struct AFSVolSync tsync;
1143 struct AFSFetchStatus OutStatus;
1149 AFS_STATCNT(PGetAcl);
1150 if (!avc) return EINVAL;
1151 Fid.Volume = avc->fid.Fid.Volume;
1152 Fid.Vnode = avc->fid.Fid.Vnode;
1153 Fid.Unique = avc->fid.Fid.Unique;
1154 if (avc->states & CForeign) {
1156 * For a dfs xlator acl we have a special hack so that the
1157 * xlator will distinguish which type of acl will return. So
1158 * we currently use the top 2-bytes (vals 0-4) to tell which
1159 * type of acl to bring back. Horrible hack but this will
1160 * cause the least number of changes to code size and interfaces.
1162 if (Fid.Vnode & 0xc0000000)
1164 Fid.Vnode |= (ainSize << 30);
1166 acl.AFSOpaque_val = aout;
1168 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1171 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1172 #ifdef RX_ENABLE_LOCKS
1174 #endif /* RX_ENABLE_LOCKS */
1175 code = RXAFS_FetchACL(tconn->id, &Fid,
1176 &acl, &OutStatus, &tsync);
1177 #ifdef RX_ENABLE_LOCKS
1179 #endif /* RX_ENABLE_LOCKS */
1184 (afs_Analyze(tconn, code, &avc->fid, areq,
1185 AFS_STATS_FS_RPCIDX_FETCHACL,
1186 SHARED_LOCK, (struct cell *)0));
1189 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1200 AFS_STATCNT(PBogus);
1204 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1207 struct vrequest *areq;
1211 afs_int32 *aoutSize; /* set this */ {
1212 register struct cell *tcell;
1214 AFS_STATCNT(PGetFileCell);
1215 if (!avc) return EINVAL;
1216 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1217 if (!tcell) return ESRCH;
1218 strcpy(aout, tcell->cellName);
1219 afs_PutCell(tcell, READ_LOCK);
1220 *aoutSize = strlen(aout) + 1;
1224 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1227 struct vrequest *areq;
1231 afs_int32 *aoutSize; /* set this */ {
1232 register struct cell *tcell=0, *cellOne=0;
1233 register struct afs_q *cq, *tq;
1235 AFS_STATCNT(PGetWSCell);
1236 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1237 return EIO; /* Inappropriate ioctl for device */
1239 ObtainReadLock(&afs_xcell);
1240 cellOne = (struct cell *) 0;
1242 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1243 tcell = QTOC(cq); tq = QNext(cq);
1244 if (tcell->states & CPrimary) break;
1245 if (tcell->cell == 1) cellOne = tcell;
1248 ReleaseReadLock(&afs_xcell);
1249 if (!tcell) { /* no primary cell, use cell #1 */
1250 if (!cellOne) return ESRCH;
1253 strcpy(aout, tcell->cellName);
1254 *aoutSize = strlen(aout) + 1;
1258 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1261 struct vrequest *areq;
1265 afs_int32 *aoutSize; /* set this */ {
1266 register afs_int32 i;
1267 register struct unixuser *tu;
1268 register struct cell *tcell;
1270 AFS_STATCNT(PGetUserCell);
1271 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1272 return EIO; /* Inappropriate ioctl for device */
1274 /* return the cell name of the primary cell for this user */
1275 i = UHash(areq->uid);
1276 ObtainWriteLock(&afs_xuser,224);
1277 for(tu = afs_users[i]; tu; tu = tu->next) {
1278 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1280 ReleaseWriteLock(&afs_xuser);
1285 tcell = afs_GetCell(tu->cell, READ_LOCK);
1286 afs_PutUser(tu, WRITE_LOCK);
1287 if (!tcell) return ESRCH;
1289 strcpy(aout, tcell->cellName);
1290 afs_PutCell(tcell, READ_LOCK);
1291 *aoutSize = strlen(aout)+1; /* 1 for the null */
1295 ReleaseWriteLock(&afs_xuser);
1302 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1305 struct vrequest *areq;
1309 afs_int32 *aoutSize; /* set this */
1310 struct AFS_UCRED **acred;
1313 register struct unixuser *tu;
1314 struct ClearToken clear;
1315 register struct cell *tcell;
1318 struct vrequest treq;
1319 afs_int32 flag, set_parent_pag = 0;
1321 AFS_STATCNT(PSetTokens);
1322 if (!afs_resourceinit_flag) {
1325 bcopy(ain, (char *)&i, sizeof(afs_int32));
1326 ain += sizeof(afs_int32);
1327 stp = ain; /* remember where the ticket is */
1328 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1330 ain += i; /* skip over ticket */
1331 bcopy(ain, (char *)&i, sizeof(afs_int32));
1332 ain += sizeof(afs_int32);
1333 if (i != sizeof(struct ClearToken)) {
1336 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1337 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1338 ain += sizeof(struct ClearToken);
1339 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1340 /* still stuff left? we've got primary flag and cell name. Set these */
1341 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1342 ain += sizeof(afs_int32); /* skip id field */
1343 /* rest is cell name, look it up */
1344 if (flag & 0x8000) { /* XXX Use Constant XXX */
1348 tcell = afs_GetCellByName(ain, READ_LOCK);
1357 /* default to cell 1, primary id */
1358 flag = 1; /* primary id */
1359 i = 1; /* cell number */
1360 tcell = afs_GetCell(1, READ_LOCK);
1361 if (!tcell) goto nocell;
1363 afs_PutCell(tcell, READ_LOCK);
1364 if (set_parent_pag) {
1367 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1369 if (!setpag(acred, -1, &pag, 1)) {
1371 afs_InitReq(&treq, *acred);
1375 /* now we just set the tokens */
1376 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1377 tu->vid = clear.ViceId;
1378 if (tu->stp != (char *) 0) {
1379 afs_osi_Free(tu->stp, tu->stLen);
1381 tu->stp = (char *) afs_osi_Alloc(stLen);
1383 bcopy(stp, tu->stp, stLen);
1386 afs_stats_cmfullperf.authent.TicketUpdates++;
1387 afs_ComputePAGStats();
1388 #endif /* AFS_NOSTATS */
1389 tu->states |= UHasTokens;
1390 tu->states &= ~UTokensBad;
1391 afs_SetPrimary(tu, flag);
1392 tu->tokenTime =osi_Time();
1393 afs_ResetUserConns(tu);
1394 afs_PutUser(tu, WRITE_LOCK);
1409 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1412 struct vrequest *areq;
1415 afs_int32 *aoutSize; /* set this */ {
1417 char offLineMsg[256];
1419 register struct conn *tc;
1420 register afs_int32 code;
1421 struct VolumeStatus volstat;
1423 char *Name, *OfflineMsg, *MOTD;
1426 AFS_STATCNT(PGetVolumeStatus);
1427 if (!avc) return EINVAL;
1429 OfflineMsg = offLineMsg;
1432 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1434 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1435 #ifdef RX_ENABLE_LOCKS
1437 #endif /* RX_ENABLE_LOCKS */
1438 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1439 &Name, &OfflineMsg, &MOTD);
1440 #ifdef RX_ENABLE_LOCKS
1442 #endif /* RX_ENABLE_LOCKS */
1447 (afs_Analyze(tc, code, &avc->fid, areq,
1448 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1449 SHARED_LOCK, (struct cell *)0));
1451 if (code) return code;
1452 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1454 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1455 cp += sizeof(VolumeStatus);
1456 strcpy(cp, volName);
1457 cp += strlen(volName)+1;
1458 strcpy(cp, offLineMsg);
1459 cp += strlen(offLineMsg)+1;
1461 cp += strlen(motd)+1;
1462 *aoutSize = (cp - aout);
1466 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1469 struct vrequest *areq;
1472 afs_int32 *aoutSize; /* set this */ {
1474 char offLineMsg[256];
1476 register struct conn *tc;
1477 register afs_int32 code;
1478 struct AFSFetchVolumeStatus volstat;
1479 struct AFSStoreVolumeStatus storeStat;
1480 register struct volume *tvp;
1484 AFS_STATCNT(PSetVolumeStatus);
1485 if (!avc) return EINVAL;
1487 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1489 if (tvp->states & (VRO | VBackup)) {
1490 afs_PutVolume(tvp, READ_LOCK);
1493 afs_PutVolume(tvp, READ_LOCK);
1496 /* Copy the junk out, using cp as a roving pointer. */
1498 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1499 cp += sizeof(AFSFetchVolumeStatus);
1500 strcpy(volName, cp);
1501 cp += strlen(volName)+1;
1502 strcpy(offLineMsg, cp);
1503 cp += strlen(offLineMsg)+1;
1506 if (volstat.MinQuota != -1) {
1507 storeStat.MinQuota = volstat.MinQuota;
1508 storeStat.Mask |= AFS_SETMINQUOTA;
1510 if (volstat.MaxQuota != -1) {
1511 storeStat.MaxQuota = volstat.MaxQuota;
1512 storeStat.Mask |= AFS_SETMAXQUOTA;
1515 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1517 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1518 #ifdef RX_ENABLE_LOCKS
1520 #endif /* RX_ENABLE_LOCKS */
1521 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1522 &storeStat, volName, offLineMsg, motd);
1523 #ifdef RX_ENABLE_LOCKS
1525 #endif /* RX_ENABLE_LOCKS */
1530 (afs_Analyze(tc, code, &avc->fid, areq,
1531 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1532 SHARED_LOCK, (struct cell *)0));
1534 if (code) return code;
1535 /* we are sending parms back to make compat. with prev system. should
1536 change interface later to not ask for current status, just set new status */
1538 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1539 cp += sizeof(VolumeStatus);
1540 strcpy(cp, volName);
1541 cp += strlen(volName)+1;
1542 strcpy(cp, offLineMsg);
1543 cp += strlen(offLineMsg)+1;
1545 cp += strlen(motd)+1;
1546 *aoutSize = cp - aout;
1550 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1551 register struct vcache *avc;
1553 struct vrequest *areq;
1556 afs_int32 *aoutSize; /* set this */
1557 struct AFS_UCRED *acred;
1560 AFS_STATCNT(PFlush);
1561 if (!avc) return EINVAL;
1562 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1563 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1565 ObtainWriteLock(&avc->lock,225);
1566 ObtainWriteLock(&afs_xcbhash, 456);
1567 afs_DequeueCallback(avc);
1568 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1569 ReleaseWriteLock(&afs_xcbhash);
1570 /* now find the disk cache entries */
1571 afs_TryToSmush(avc, acred, 1);
1572 osi_dnlc_purgedp(avc);
1573 afs_symhint_inval(avc);
1574 if (avc->linkData && !(avc->states & CCore)) {
1575 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1576 avc->linkData = (char *) 0;
1578 ReleaseWriteLock(&avc->lock);
1579 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1580 afs_BozonUnlock(&avc->pvnLock, avc);
1585 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1588 struct vrequest *areq;
1591 afs_int32 *aoutSize; /* set this */ {
1592 register afs_int32 code;
1593 register struct vcache *tvc;
1594 register struct dcache *tdc;
1595 struct VenusFid tfid;
1597 afs_int32 offset, len, hasatsys=0;
1599 AFS_STATCNT(PNewStatMount);
1600 if (!avc) return EINVAL;
1601 code = afs_VerifyVCache(avc, areq);
1602 if (code) return code;
1603 if (vType(avc) != VDIR) {
1606 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1607 if (!tdc) return ENOENT;
1608 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1609 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1614 tfid.Cell = avc->fid.Cell;
1615 tfid.Fid.Volume = avc->fid.Fid.Volume;
1616 afs_PutDCache(tdc); /* we're done with the data */
1617 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1618 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1620 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1627 if (vType(tvc) != VLNK) {
1628 afs_PutVCache(tvc, WRITE_LOCK);
1632 ObtainWriteLock(&tvc->lock,226);
1633 code = afs_HandleLink(tvc, areq);
1635 if (tvc->linkData) {
1636 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1639 /* we have the data */
1640 strcpy(aout, tvc->linkData);
1641 *aoutSize = strlen(tvc->linkData)+1;
1646 ReleaseWriteLock(&tvc->lock);
1647 afs_PutVCache(tvc, WRITE_LOCK);
1649 if (hasatsys) osi_FreeLargeSpace(bufp);
1653 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1656 struct vrequest *areq;
1659 afs_int32 *aoutSize; /* set this */ {
1660 register struct cell *tcell;
1661 register afs_int32 i;
1662 register struct unixuser *tu;
1667 AFS_STATCNT(PGetTokens);
1668 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1669 return EIO; /* Inappropriate ioctl for device */
1671 /* weird interface. If input parameter is present, it is an integer and
1672 we're supposed to return the parm'th tokens for this unix uid.
1673 If not present, we just return tokens for cell 1.
1674 If counter out of bounds, return EDOM.
1675 If no tokens for the particular cell, return ENOTCONN.
1676 Also, if this mysterious parm is present, we return, along with the
1677 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1678 at the end, in that order.
1680 if (newStyle = (ainSize > 0)) {
1681 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1683 i = UHash(areq->uid);
1684 ObtainReadLock(&afs_xuser);
1685 for(tu = afs_users[i]; tu; tu=tu->next) {
1687 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1688 if (iterator-- == 0) break; /* are we done yet? */
1692 if (tu->uid == areq->uid && tu->cell == 1) break;
1697 * No need to hold a read lock on each user entry
1701 ReleaseReadLock(&afs_xuser);
1706 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1707 tu->states |= (UTokensBad | UNeedsReset);
1708 afs_PutUser(tu, READ_LOCK);
1711 /* use iterator for temp */
1713 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1714 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1715 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1716 cp += sizeof(afs_int32);
1717 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1719 iterator = sizeof(struct ClearToken);
1720 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1721 cp += sizeof(afs_int32);
1722 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1723 cp += sizeof(struct ClearToken);
1725 /* put out primary id and cell name, too */
1726 iterator = (tu->states & UPrimary ? 1 : 0);
1727 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1728 cp += sizeof(afs_int32);
1729 tcell = afs_GetCell(tu->cell, READ_LOCK);
1731 strcpy(cp, tcell->cellName);
1732 cp += strlen(tcell->cellName)+1;
1733 afs_PutCell(tcell, READ_LOCK);
1737 *aoutSize = cp - aout;
1738 afs_PutUser(tu, READ_LOCK);
1742 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1745 struct vrequest *areq;
1748 afs_int32 *aoutSize; /* set this */ {
1749 register afs_int32 i;
1750 register struct unixuser *tu;
1752 AFS_STATCNT(PUnlog);
1753 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1754 return EIO; /* Inappropriate ioctl for device */
1756 i = UHash(areq->uid);
1757 ObtainWriteLock(&afs_xuser,227);
1758 for(tu=afs_users[i]; tu; tu=tu->next) {
1759 if (tu->uid == areq->uid) {
1761 tu->states &= ~UHasTokens;
1762 /* security is not having to say you're sorry */
1763 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1765 ReleaseWriteLock(&afs_xuser);
1766 /* We have to drop the lock over the call to afs_ResetUserConns, since
1767 * it obtains the afs_xvcache lock. We could also keep the lock, and
1768 * modify ResetUserConns to take parm saying we obtained the lock
1769 * already, but that is overkill. By keeping the "tu" pointer
1770 * held over the released lock, we guarantee that we won't lose our
1771 * place, and that we'll pass over every user conn that existed when
1772 * we began this call.
1774 afs_ResetUserConns(tu);
1776 ObtainWriteLock(&afs_xuser,228);
1779 ReleaseWriteLock(&afs_xuser);
1783 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1786 struct vrequest *areq;
1789 afs_int32 *aoutSize; /* set this */ {
1790 afs_int32 newHostAddr;
1791 afs_int32 oldHostAddr;
1793 AFS_STATCNT(PMariner);
1795 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1797 oldHostAddr = 0xffffffff; /* disabled */
1799 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1800 if (newHostAddr == 0xffffffff) {
1801 /* disable mariner operations */
1804 else if (newHostAddr) {
1806 afs_marinerHost = newHostAddr;
1808 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1809 *aoutSize = sizeof(afs_int32);
1813 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1816 struct vrequest *areq;
1819 afs_int32 *aoutSize; /* set this */
1820 struct AFS_UCRED *acred;
1822 register char *cp = 0;
1824 register struct server *ts;
1825 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1827 struct chservinfo *pcheck;
1829 AFS_STATCNT(PCheckServers);
1831 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1832 return EIO; /* Inappropriate ioctl for device */
1834 if (*lp == 0x12345678) { /* For afs3.3 version */
1835 pcheck=(struct chservinfo *)ain;
1836 if (pcheck->tinterval >= 0) {
1838 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1839 *aoutSize = sizeof(afs_int32);
1840 if (pcheck->tinterval > 0) {
1841 if (!afs_osi_suser(acred))
1843 PROBE_INTERVAL=pcheck->tinterval;
1849 temp=pcheck->tflags;
1850 cp = pcheck->tbuffer;
1851 } else { /* For pre afs3.3 versions */
1852 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1853 cp = ain+sizeof(afs_int32);
1854 if (ainSize > sizeof(afs_int32))
1859 * 1: fast check, don't contact servers.
1860 * 2: local cell only.
1863 /* have cell name, too */
1864 cellp = afs_GetCellByName(cp, READ_LOCK);
1865 if (!cellp) return ENOENT;
1867 else cellp = (struct cell *) 0;
1868 if (!cellp && (temp & 2)) {
1869 /* use local cell */
1870 cellp = afs_GetCell(1, READ_LOCK);
1872 if (!(temp & 1)) { /* if not fast, call server checker routine */
1873 afs_CheckServers(1, cellp); /* check down servers */
1874 afs_CheckServers(0, cellp); /* check up servers */
1876 /* now return the current down server list */
1878 ObtainReadLock(&afs_xserver);
1879 for(i=0;i<NSERVERS;i++) {
1880 for(ts = afs_servers[i]; ts; ts=ts->next) {
1881 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1882 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1883 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1884 cp += sizeof(afs_int32);
1888 ReleaseReadLock(&afs_xserver);
1889 if (cellp) afs_PutCell(cellp, READ_LOCK);
1890 *aoutSize = cp - aout;
1894 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1897 struct vrequest *areq;
1900 afs_int32 *aoutSize; /* set this */ {
1901 AFS_STATCNT(PCheckVolNames);
1902 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1903 return EIO; /* Inappropriate ioctl for device */
1905 afs_CheckRootVolume();
1906 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1907 AFS_VOLCHECK_EXPIRED |
1909 AFS_VOLCHECK_MTPTS);
1913 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1916 struct vrequest *areq;
1919 afs_int32 *aoutSize; /* set this */ {
1923 struct unixuser *tu;
1925 extern afs_rwlock_t afs_xsrvAddr;
1927 AFS_STATCNT(PCheckAuth);
1928 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1929 return EIO; /* Inappropriate ioctl for device */
1932 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1933 if (!tu) retValue = EACCES;
1935 /* we have a user */
1936 ObtainReadLock(&afs_xsrvAddr);
1937 ObtainReadLock(&afs_xconn);
1939 /* any tokens set? */
1940 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1941 /* all connections in cell 1 working? */
1942 for(i=0;i<NSERVERS;i++) {
1943 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1944 for (tc = sa->conns; tc; tc=tc->next) {
1945 if (tc->user == tu && (tu->states & UTokensBad))
1950 ReleaseReadLock(&afs_xsrvAddr);
1951 ReleaseReadLock(&afs_xconn);
1952 afs_PutUser(tu, READ_LOCK);
1954 bcopy((char *)&retValue, aout, sizeof(afs_int32));
1955 *aoutSize = sizeof(afs_int32);
1959 static Prefetch(apath, adata, afollow, acred)
1961 struct afs_ioctl *adata;
1963 struct AFS_UCRED *acred;
1966 register afs_int32 code;
1969 AFS_STATCNT(Prefetch);
1970 if (!apath) return EINVAL;
1971 tp = osi_AllocLargeSpace(1024);
1972 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1974 osi_FreeLargeSpace(tp);
1977 if (afs_BBusy()) { /* do this as late as possible */
1978 osi_FreeLargeSpace(tp);
1979 return EWOULDBLOCK; /* pretty close */
1981 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
1985 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
1988 struct vrequest *areq;
1991 afs_int32 *aoutSize; /* set this */ {
1992 register struct volume *tvp;
1993 register struct server *ts;
1994 register afs_int32 i;
1997 AFS_STATCNT(PFindVolume);
1998 if (!avc) return EINVAL;
1999 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2002 for(i=0;i<MAXHOSTS;i++) {
2003 ts = tvp->serverHost[i];
2005 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2006 cp += sizeof(afs_int32);
2009 /* still room for terminating NULL, add it on */
2010 ainSize = 0; /* reuse vbl */
2011 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2012 cp += sizeof(afs_int32);
2014 *aoutSize = cp - aout;
2015 afs_PutVolume(tvp, READ_LOCK);
2021 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2024 struct vrequest *areq;
2027 afs_int32 *aoutSize; /* set this */ {
2028 register afs_int32 code;
2031 AFS_STATCNT(PViceAccess);
2032 if (!avc) return EINVAL;
2033 code = afs_VerifyVCache(avc, areq);
2034 if (code) return code;
2035 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2036 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2041 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2044 struct vrequest *areq;
2047 afs_int32 *aoutSize; /* set this */
2048 struct AFS_UCRED *acred;
2053 AFS_STATCNT(PSetCacheSize);
2054 if (!afs_osi_suser(acred))
2056 /* too many things are setup initially in mem cache version */
2057 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2058 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2059 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2061 extern u_int afs_min_cache;
2062 if (newValue < afs_min_cache)
2063 afs_cacheBlocks = afs_min_cache;
2065 afs_cacheBlocks = newValue;
2067 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2068 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2069 afs_MaybeWakeupTruncateDaemon();
2070 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2071 afs_osi_Wait(1000, 0, 0);
2072 afs_MaybeWakeupTruncateDaemon();
2077 #define MAXGCSTATS 16
2078 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2081 struct vrequest *areq;
2084 afs_int32 *aoutSize; /* set this */ {
2085 afs_int32 results[MAXGCSTATS];
2087 AFS_STATCNT(PGetCacheSize);
2088 bzero((char *)results, sizeof(results));
2089 results[0] = afs_cacheBlocks;
2090 results[1] = afs_blocksUsed;
2091 bcopy((char *)results, aout, sizeof(results));
2092 *aoutSize = sizeof(results);
2096 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2099 struct vrequest *areq;
2102 afs_int32 *aoutSize; /* set this */ {
2103 register struct conn *tc;
2104 register afs_int32 code;
2105 struct AFSCallBack CallBacks_Array[1];
2106 struct AFSCBFids theFids;
2107 struct AFSCBs theCBs;
2110 AFS_STATCNT(PRemoveCallBack);
2111 if (!avc) return EINVAL;
2112 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2113 ObtainWriteLock(&avc->lock,229);
2114 theFids.AFSCBFids_len = 1;
2115 theCBs.AFSCBs_len = 1;
2116 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2117 theCBs.AFSCBs_val = CallBacks_Array;
2118 CallBacks_Array[0].CallBackType = CB_DROPPED;
2119 if (avc->callback) {
2121 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2123 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2124 #ifdef RX_ENABLE_LOCKS
2126 #endif /* RX_ENABLE_LOCKS */
2127 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2128 #ifdef RX_ENABLE_LOCKS
2130 #endif /* RX_ENABLE_LOCKS */
2133 /* don't set code on failure since we wouldn't use it */
2135 (afs_Analyze(tc, code, &avc->fid, areq,
2136 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2137 SHARED_LOCK, (struct cell *)0));
2139 ObtainWriteLock(&afs_xcbhash, 457);
2140 afs_DequeueCallback(avc);
2142 avc->states &= ~(CStatd | CUnique);
2143 ReleaseWriteLock(&afs_xcbhash);
2144 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2145 osi_dnlc_purgedp(avc);
2147 ReleaseWriteLock(&avc->lock);
2151 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2154 struct vrequest *areq;
2158 struct AFS_UCRED *acred;
2159 afs_int32 *aoutSize; /* set this */ {
2160 /* create a new cell */
2161 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2162 register struct cell *tcell;
2163 char *newcell=0, *linkedcell=0, *tp= ain;
2164 register afs_int32 code, linkedstate=0, ls;
2165 u_short fsport = 0, vlport = 0;
2168 AFS_STATCNT(PNewCell);
2169 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2170 return EIO; /* Inappropriate ioctl for device */
2172 if (!afs_osi_suser(acred))
2175 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2176 tp += sizeof(afs_int32);
2177 if (magic != 0x12345678)
2180 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2181 * server addresses while the 3.5 fs newcell command passes
2182 * MAXHOSTS. To figure out which is which, check if the cellname
2185 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2186 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2188 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2189 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2190 tp += (scount * sizeof(afs_int32));
2192 lp = (afs_int32 *)tp;
2195 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2196 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2197 tp += (3 * sizeof(afs_int32));
2199 if ((ls = *lp) & 1) {
2200 linkedcell = tp + strlen(newcell)+1;
2201 linkedstate |= CLinkedCell;
2204 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2205 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport);
2209 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2212 struct vrequest *areq;
2215 afs_int32 *aoutSize; /* set this */ {
2216 afs_int32 whichCell;
2217 register struct cell *tcell=0;
2218 register afs_int32 i;
2219 register char *cp, *tp = ain;
2220 register struct afs_q *cq, *tq;
2222 AFS_STATCNT(PListCells);
2223 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2224 return EIO; /* Inappropriate ioctl for device */
2226 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2227 tp += sizeof(afs_int32);
2228 ObtainReadLock(&afs_xcell);
2229 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2230 tcell = QTOC(cq); tq = QNext(cq);
2231 if (whichCell == 0) break;
2232 if (tq == &CellLRU) tcell = 0;
2237 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2238 for(i=0;i<MAXCELLHOSTS;i++) {
2239 if (tcell->cellHosts[i] == 0) break;
2240 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2241 cp += sizeof(afs_int32);
2243 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2244 strcpy(cp, tcell->cellName);
2245 cp += strlen(tcell->cellName)+1;
2246 *aoutSize = cp - aout;
2248 ReleaseReadLock(&afs_xcell);
2249 if (tcell) return 0;
2253 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2256 struct vrequest *areq;
2260 afs_int32 *aoutSize; /* set this */ {
2261 register afs_int32 code;
2263 afs_int32 offset, len, hasatsys = 0;
2264 register struct conn *tc;
2265 register struct dcache *tdc;
2266 register struct vcache *tvc;
2267 struct AFSFetchStatus OutDirStatus;
2268 struct VenusFid tfid;
2269 struct AFSVolSync tsync;
2273 /* "ain" is the name of the file in this dir to remove */
2275 AFS_STATCNT(PRemoveMount);
2276 if (!avc) return EINVAL;
2277 code = afs_VerifyVCache(avc, areq);
2278 if (code) return code;
2279 if (vType(avc) != VDIR) return ENOTDIR;
2281 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2282 if (!tdc) return ENOENT;
2283 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2284 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2289 tfid.Cell = avc->fid.Cell;
2290 tfid.Fid.Volume = avc->fid.Fid.Volume;
2291 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2292 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2294 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2295 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2302 if (vType(tvc) != VLNK) {
2304 afs_PutVCache(tvc, WRITE_LOCK);
2308 ObtainWriteLock(&tvc->lock,230);
2309 code = afs_HandleLink(tvc, areq);
2311 if (tvc->linkData) {
2312 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2317 ReleaseWriteLock(&tvc->lock);
2318 osi_dnlc_purgedp(tvc);
2319 afs_PutVCache(tvc, WRITE_LOCK);
2324 ObtainWriteLock(&avc->lock,231);
2325 osi_dnlc_remove(avc, bufp, tvc);
2327 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2329 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2330 #ifdef RX_ENABLE_LOCKS
2332 #endif /* RX_ENABLE_LOCKS */
2333 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2334 bufp, &OutDirStatus, &tsync);
2335 #ifdef RX_ENABLE_LOCKS
2337 #endif /* RX_ENABLE_LOCKS */
2342 (afs_Analyze(tc, code, &avc->fid, areq,
2343 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2344 SHARED_LOCK, (struct cell *)0));
2347 if (tdc) afs_PutDCache(tdc);
2348 ReleaseWriteLock(&avc->lock);
2352 /* we have the thing in the cache */
2353 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2354 /* we can do it locally */
2355 code = afs_dir_Delete(&tdc->f.inode, bufp);
2357 ZapDCE(tdc); /* surprise error -- invalid value */
2358 DZap(&tdc->f.inode);
2361 afs_PutDCache(tdc); /* drop ref count */
2363 avc->states &= ~CUnique; /* For the dfs xlator */
2364 ReleaseWriteLock(&avc->lock);
2367 if (hasatsys) osi_FreeLargeSpace(bufp);
2371 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2374 struct vrequest *areq;
2378 struct AFS_UCRED *acred;
2379 afs_int32 *aoutSize; /* set this */ {
2380 return EINVAL; /* OBSOLETE */
2383 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2386 struct vrequest *areq;
2389 afs_int32 *aoutSize; /* set this */ {
2390 register struct cell *tcell;
2393 AFS_STATCNT(PGetCellStatus);
2394 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2395 return EIO; /* Inappropriate ioctl for device */
2397 tcell = afs_GetCellByName(ain, READ_LOCK);
2398 if (!tcell) return ENOENT;
2399 temp = tcell->states;
2400 afs_PutCell(tcell, READ_LOCK);
2401 bcopy((char *)&temp, aout, sizeof(afs_int32));
2402 *aoutSize = sizeof(afs_int32);
2406 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2409 struct vrequest *areq;
2412 struct AFS_UCRED *acred;
2413 afs_int32 *aoutSize; /* set this */ {
2414 register struct cell *tcell;
2417 if (!afs_osi_suser(acred))
2419 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2420 return EIO; /* Inappropriate ioctl for device */
2422 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2423 if (!tcell) return ENOENT;
2424 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2426 tcell->states |= CNoSUID;
2428 tcell->states &= ~CNoSUID;
2429 afs_PutCell(tcell, WRITE_LOCK);
2433 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2436 struct vrequest *areq;
2439 afs_int32 *aoutSize; /* set this */
2440 struct AFS_UCRED *acred;
2442 extern struct volume *afs_volumes[NVOLS];
2443 register afs_int32 i;
2444 register struct dcache *tdc;
2445 register struct vcache *tvc;
2446 register struct volume *tv;
2447 afs_int32 cell, volume;
2449 AFS_STATCNT(PFlushVolumeData);
2452 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2453 return EIO; /* Inappropriate ioctl for device */
2455 volume = avc->fid.Fid.Volume; /* who to zap */
2456 cell = avc->fid.Cell;
2459 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2460 * the vcaches associated with the volume.
2462 ObtainReadLock(&afs_xvcache);
2463 for(i = 0; i < VCSIZE; i++) {
2464 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2465 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2466 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2467 VN_HOLD((struct vnode *)tvc);
2471 ReleaseReadLock(&afs_xvcache);
2472 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2473 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2475 ObtainWriteLock(&tvc->lock,232);
2477 ObtainWriteLock(&afs_xcbhash, 458);
2478 afs_DequeueCallback(tvc);
2479 tvc->states &= ~(CStatd | CDirty);
2480 ReleaseWriteLock(&afs_xcbhash);
2481 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2482 osi_dnlc_purgedp(tvc);
2483 afs_TryToSmush(tvc, acred, 1);
2484 ReleaseWriteLock(&tvc->lock);
2485 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2486 afs_BozonUnlock(&tvc->pvnLock, tvc);
2488 ObtainReadLock(&afs_xvcache);
2489 /* our tvc ptr is still good until now */
2494 ReleaseReadLock(&afs_xvcache);
2497 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2498 for(i=0;i<afs_cacheFiles;i++) {
2499 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2500 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2501 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2502 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2503 if (! (afs_indexFlags[i] & IFDataMod)) {
2504 /* if the file is modified, but has a ref cnt of only 1, then
2505 someone probably has the file open and is writing into it.
2506 Better to skip flushing such a file, it will be brought back
2507 immediately on the next write anyway.
2509 If we *must* flush, then this code has to be rearranged to call
2510 afs_storeAllSegments() first */
2511 afs_FlushDCache(tdc);
2515 tdc->refCount--; /* bumped by getdslot */
2517 MReleaseWriteLock(&afs_xdcache);
2519 ObtainReadLock(&afs_xvolume);
2520 for (i=0;i<NVOLS;i++) {
2521 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2522 if (tv->volume == volume) {
2523 afs_ResetVolumeInfo(tv);
2528 ReleaseReadLock(&afs_xvolume);
2530 /* probably, a user is doing this, probably, because things are screwed up.
2531 * maybe it's the dnlc's fault? */
2538 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2541 struct vrequest *areq;
2544 afs_int32 *aoutSize; /* set this */ {
2545 register afs_int32 code;
2546 struct vcxstat stat;
2549 /* AFS_STATCNT(PGetVnodeXStatus); */
2550 if (!avc) return EINVAL;
2551 code = afs_VerifyVCache(avc, areq);
2552 if (code) return code;
2553 if (vType(avc) == VDIR)
2554 mode = PRSFS_LOOKUP;
2557 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2559 stat.fid = avc->fid;
2560 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2561 stat.lock = avc->lock;
2562 stat.parentVnode = avc->parentVnode;
2563 stat.parentUnique = avc->parentUnique;
2564 hset(stat.flushDV, avc->flushDV);
2565 hset(stat.mapDV, avc->mapDV);
2566 stat.truncPos = avc->truncPos;
2567 { /* just grab the first two - won't break anything... */
2568 struct axscache *ac;
2570 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2571 stat.randomUid[i] = ac->uid;
2572 stat.randomAccess[i] = ac->axess;
2575 stat.callback = afs_data_pointer_to_int32(avc->callback);
2576 stat.cbExpires = avc->cbExpires;
2577 stat.anyAccess = avc->anyAccess;
2578 stat.opens = avc->opens;
2579 stat.execsOrWriters = avc->execsOrWriters;
2580 stat.flockCount = avc->flockCount;
2581 stat.mvstat = avc->mvstat;
2582 stat.states = avc->states;
2583 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2584 *aoutSize = sizeof(struct vcxstat);
2589 /* We require root for local sysname changes, but not for remote */
2590 /* (since we don't really believe remote uids anyway) */
2591 /* outname[] shouldn't really be needed- this is left as an excercise */
2592 /* for the reader. */
2594 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2597 struct vrequest *areq;
2600 afs_int32 *aoutSize; /* set this */
2601 register struct AFS_UCRED *acred;
2603 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2604 int setsysname, foundname=0;
2605 register struct afs_exporter *exporter;
2606 extern struct unixuser *afs_FindUser();
2607 extern char *afs_sysname;
2608 register struct unixuser *au;
2609 register afs_int32 pag, error;
2613 AFS_STATCNT(PSetSysName);
2614 if (!afs_globalVFS) {
2615 /* Afsd is NOT running; disable it */
2616 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
2619 return (setuerror(EINVAL), EINVAL);
2622 bzero(inname, MAXSYSNAME);
2623 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2624 ain += sizeof(afs_int32);
2629 bcopy(ain, inname, t+1); /* include terminating null */
2632 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2633 pag = PagInCred(acred);
2635 return EINVAL; /* Better than panicing */
2637 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2638 return EINVAL; /* Better than panicing */
2640 if (!(exporter = au->exporter)) {
2641 afs_PutUser(au, READ_LOCK);
2642 return EINVAL; /* Better than panicing */
2644 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2646 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2648 afs_PutUser(au, READ_LOCK);
2653 afs_PutUser(au, READ_LOCK);
2655 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2657 strcpy(outname, afs_sysname);
2660 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2662 strcpy(afs_sysname, inname);
2667 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2668 cp += sizeof(afs_int32);
2670 strcpy(cp, outname);
2671 cp += strlen(outname)+1;
2673 *aoutSize = cp - aout;
2678 /* sequential search through the list of touched cells is not a good
2679 * long-term solution here. For small n, though, it should be just
2680 * fine. Should consider special-casing the local cell for large n.
2681 * Likewise for PSetSPrefs.
2683 static void ReSortCells(s,l, vlonly)
2684 int s; /* number of ids in array l[] -- NOT index of last id */
2685 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2686 int vlonly; /* sort vl servers or file servers?*/
2688 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2697 tcell = afs_GetCell(l[k], WRITE_LOCK);
2698 if (!tcell) continue;
2699 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2700 afs_PutCell(tcell, WRITE_LOCK);
2705 ObtainReadLock(&afs_xvolume);
2706 for (i= 0; i< NVOLS; i++) {
2707 for (j=afs_volumes[i];j;j=j->next) {
2709 if (j->cell == l[k]) {
2710 ObtainWriteLock(&j->lock,233);
2711 afs_SortServers(j->serverHost, MAXHOSTS);
2712 ReleaseWriteLock(&j->lock);
2717 ReleaseReadLock(&afs_xvolume);
2722 static int afs_setsprefs(sp, num, vlonly)
2725 unsigned int vlonly;
2728 int i,j,k,matches,touchedSize;
2729 struct server *srvr = NULL;
2730 afs_int32 touched[34];
2734 for (k=0; k < num; sp++, k++) {
2736 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2739 ObtainReadLock(&afs_xserver);
2741 i = SHash(sp->host.s_addr);
2742 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2743 if (sa->sa_ip == sp->host.s_addr) {
2745 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2746 || (sa->sa_portal == AFS_FSPORT);
2747 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2754 if (sa && matches) { /* found one! */
2756 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2758 sa->sa_iprank = sp->rank + afs_randomMod15();
2759 afs_SortOneServer(sa->server);
2762 /* if we don't know yet what cell it's in, this is moot */
2763 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2764 /* is it in our list of touched cells ? */ ;
2765 if (j < 0) { /* no, it's not */
2766 touched[touchedSize++] = srvr->cell->cell;
2767 if (touchedSize >= 32) { /* watch for ovrflow */
2768 ReleaseReadLock(&afs_xserver);
2769 ReSortCells(touchedSize, touched, vlonly);
2771 ObtainReadLock(&afs_xserver);
2777 ReleaseReadLock(&afs_xserver);
2778 /* if we didn't find one, start to create one. */
2779 /* Note that it doesn't have a cell yet... */
2781 afs_uint32 temp = sp->host.s_addr;
2782 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2783 WRITE_LOCK, (afsUUID *)0,0);
2784 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2785 afs_PutServer(srvr, WRITE_LOCK);
2787 } /* for all cited preferences */
2789 ReSortCells(touchedSize, touched, vlonly);
2793 /* Note that this may only be performed by the local root user.
2796 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2799 struct vrequest *areq;
2802 struct AFS_UCRED *acred;
2803 afs_int32 *aoutSize;
2805 struct setspref *ssp;
2806 AFS_STATCNT(PSetSPrefs);
2808 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2809 return EIO; /* Inappropriate ioctl for device */
2811 if (!afs_osi_suser(acred))
2814 if (ainSize < sizeof(struct setspref))
2817 ssp = (struct setspref *)ain;
2818 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2821 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2822 (ssp->flags & DBservers));
2827 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2830 struct vrequest *areq;
2833 struct AFS_UCRED *acred;
2834 afs_int32 *aoutSize;
2837 AFS_STATCNT(PSetSPrefs);
2838 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2839 return EIO; /* Inappropriate ioctl for device */
2842 if (!afs_osi_suser(acred))
2845 sp = (struct spref *)ain;
2846 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2850 /* some notes on the following code...
2851 * in the hash table of server structs, all servers with the same IP address
2852 * will be on the same overflow chain.
2853 * This could be sped slightly in some circumstances by having it cache the
2854 * immediately previous slot in the hash table and some supporting information
2855 * Only reports file servers now.
2858 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2861 struct vrequest *areq;
2864 afs_int32 *aoutSize;
2866 struct sprefrequest *spin; /* input */
2867 struct sprefinfo *spout; /* output */
2868 struct spref *srvout; /* one output component */
2869 int i,j; /* counters for hash table traversal */
2870 struct server *srvr; /* one of CM's server structs */
2873 int vlonly; /* just return vlservers ? */
2876 AFS_STATCNT(PGetSPrefs);
2877 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2878 return EIO; /* Inappropriate ioctl for device */
2881 if (ainSize < sizeof (struct sprefrequest_33)) {
2885 spin = ((struct sprefrequest *) ain);
2888 if (ainSize > sizeof (struct sprefrequest_33)) {
2889 vlonly = (spin->flags & DBservers);
2893 /* struct sprefinfo includes 1 server struct... that size gets added
2894 * in during the loop that follows.
2896 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2897 spout = (struct sprefinfo *) aout;
2898 spout->next_offset = spin->offset;
2899 spout->num_servers = 0;
2900 srvout = spout->servers;
2902 ObtainReadLock(&afs_xserver);
2903 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2904 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2905 if (spin->offset > (unsigned short)i) {
2906 continue; /* catch up to where we left off */
2908 spout->next_offset++;
2911 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2912 || (sa->sa_portal == AFS_FSPORT);
2914 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2915 /* only report ranks for vl servers */
2919 srvout->host.s_addr = sa->sa_ip;
2920 srvout->rank = sa->sa_iprank;
2921 *aoutSize += sizeof(struct spref);
2922 spout->num_servers++;
2925 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2926 ReleaseReadLock(&afs_xserver); /* no more room! */
2931 ReleaseReadLock(&afs_xserver);
2933 spout->next_offset = 0; /* start over from the beginning next time */
2937 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2938 int afs_NFSRootOnly = 1;
2939 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2942 struct vrequest *areq;
2945 afs_int32 *aoutSize; /* set this */
2946 struct AFS_UCRED *acred;
2948 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2949 extern struct afs_exporter *exporter_find();
2950 register struct afs_exporter *exporter;
2952 AFS_STATCNT(PExportAfs);
2953 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
2954 type = handleValue >> 24;
2959 exporter = exporter_find(type);
2961 export = handleValue & 3;
2962 changestate = handleValue & 0xff;
2963 smounts = (handleValue >> 2) & 3;
2964 pwsync = (handleValue >> 4) & 3;
2965 convmode = (handleValue >> 6) & 3;
2967 changestate = (handleValue >> 16) & 0x1;
2968 convmode = (handleValue >> 16) & 0x2;
2969 pwsync = (handleValue >> 16) & 0x4;
2970 smounts = (handleValue >> 16) & 0x8;
2971 export = handleValue & 0xff;
2974 /* Failed finding desired exporter; */
2978 handleValue = exporter->exp_states;
2979 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2980 *aoutSize = sizeof(afs_int32);
2982 if (!afs_osi_suser(acred))
2983 return EACCES; /* Only superuser can do this */
2987 exporter->exp_states |= EXP_EXPORTED;
2989 exporter->exp_states &= ~EXP_EXPORTED;
2993 exporter->exp_states |= EXP_UNIXMODE;
2995 exporter->exp_states &= ~EXP_UNIXMODE;
2999 exporter->exp_states |= EXP_PWSYNC;
3001 exporter->exp_states &= ~EXP_PWSYNC;
3005 afs_NFSRootOnly = 0;
3006 exporter->exp_states |= EXP_SUBMOUNTS;
3008 afs_NFSRootOnly = 1;
3009 exporter->exp_states &= ~EXP_SUBMOUNTS;
3012 handleValue = exporter->exp_states;
3013 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3014 *aoutSize = sizeof(afs_int32);
3017 exporter->exp_states |= EXP_EXPORTED;
3019 exporter->exp_states &= ~EXP_EXPORTED;
3021 exporter->exp_states |= EXP_UNIXMODE;
3023 exporter->exp_states &= ~EXP_UNIXMODE;
3025 exporter->exp_states |= EXP_PWSYNC;
3027 exporter->exp_states &= ~EXP_PWSYNC;
3029 afs_NFSRootOnly = 0;
3030 exporter->exp_states |= EXP_SUBMOUNTS;
3032 afs_NFSRootOnly = 1;
3033 exporter->exp_states &= ~EXP_SUBMOUNTS;
3042 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3045 struct vrequest *areq;
3048 struct AFS_UCRED *acred;
3049 afs_int32 *aoutSize; /* set this */
3051 struct gaginfo *gagflags;
3053 if (!afs_osi_suser(acred))
3056 gagflags = (struct gaginfo *) ain;
3057 afs_showflags = gagflags->showflags;
3064 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3067 struct vrequest *areq;
3070 struct AFS_UCRED *acred;
3071 afs_int32 *aoutSize;
3073 struct rxparams *rxp;
3075 if (!afs_osi_suser(acred))
3078 rxp = (struct rxparams *) ain;
3080 if (rxp->rx_initReceiveWindow)
3081 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3082 if (rxp->rx_maxReceiveWindow)
3083 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3084 if (rxp->rx_initSendWindow)
3085 rx_initSendWindow = rxp->rx_initSendWindow;
3086 if (rxp->rx_maxSendWindow)
3087 rx_maxSendWindow = rxp->rx_maxSendWindow;
3088 if (rxp->rxi_nSendFrags)
3089 rxi_nSendFrags = rxp->rxi_nSendFrags;
3090 if (rxp->rxi_nRecvFrags)
3091 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3092 if (rxp->rxi_OrphanFragSize)
3093 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3094 if (rxp->rx_maxReceiveSize)
3096 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3097 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3099 if (rxp->rx_MyMaxSendSize)
3100 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3105 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3108 struct vrequest *areq;
3112 afs_int32 *aoutSize; /* set this */
3114 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3117 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3118 *aoutSize = sizeof(struct cm_initparams);
3122 #ifdef AFS_SGI65_ENV
3123 /* They took crget() from us, so fake it. */
3124 static cred_t *crget(void)
3127 cr = crdup(get_current_cred());
3128 bzero((char*)cr, sizeof(cred_t));
3129 #if CELL || CELL_PREPARE
3136 * Create new credentials to correspond to a remote user with given
3137 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3138 * provide pioctl (and other) services to foreign clients (i.e. nfs
3139 * clients) by using this call to `become' the client.
3142 #define PIOCTL_HEADER 6
3143 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3146 afs_uint32 hostaddr;
3147 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3148 extern struct afs_exporter *exporter_find();
3149 struct afs_exporter *exporter, *outexporter;
3150 struct AFS_UCRED *newcred;
3151 struct unixuser *au;
3153 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3154 return EINVAL; /* NFS trans not supported for Ultrix */
3156 #if defined(AFS_SGIMP_ENV)
3157 osi_Assert(ISAFS_GLOCK());
3159 AFS_STATCNT(HandleClientContext);
3160 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3161 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3162 return EINVAL; /* Too small to be good */
3164 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3165 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3167 osi_FreeLargeSpace(inData);
3171 /* Extract information for remote user */
3172 hostaddr = *((afs_uint32 *)ain);
3173 ain += sizeof(hostaddr);
3174 uid = *((afs_uint32 *)ain);
3176 g0 = *((afs_uint32 *)ain);
3178 g1 = *((afs_uint32 *)ain);
3180 *com = *((afs_uint32 *)ain);
3181 ain += sizeof(afs_int32);
3182 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3185 * Of course, one must be root for most of these functions, but
3186 * we'll allow (for knfs) you to set things if the pag is 0 and
3187 * you're setting tokens or unlogging.
3190 if (!afs_osi_suser(credp)) {
3192 #ifndef AFS_SGI64_ENV
3193 /* Since SGI's suser() returns explicit failure after the call.. */
3197 /* check for acceptable opcodes for normal folks, which are, so far,
3198 * set tokens and unlog.
3200 if (i != 9 && i != 3 && i != 38 && i != 8) {
3201 osi_FreeLargeSpace(inData);
3206 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3207 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3208 osi_FreeLargeSpace(inData);
3211 * We map uid 0 to nobody to match the mapping that the nfs
3212 * server does and to ensure that the suser() calls in the afs
3213 * code fails for remote client roots.
3215 uid = afs_nobody; /* NFS_NOBODY == -2 */
3218 #ifdef AFS_AIX41_ENV
3221 newcred->cr_gid = RMTUSER_REQ;
3222 newcred->cr_groups[0] = g0;
3223 newcred->cr_groups[1] = g1;
3225 newcred->cr_ngrps = 2;
3227 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3228 newcred->cr_ngroups = 2;
3230 for (i=2; i<NGROUPS; i++)
3231 newcred->cr_groups[i] = NOGROUP;
3234 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3235 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3237 if (!(exporter = exporter_find(exporter_type))) {
3238 /* Exporter wasn't initialized or an invalid exporter type */
3242 if (exporter->exp_states & EXP_PWSYNC) {
3243 if (uid != credp->cr_uid) {
3245 return ENOEXEC; /* XXX Find a better errno XXX */
3248 newcred->cr_uid = uid; /* Only temporary */
3249 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3250 /* The client's pag is the only unique identifier for it */
3251 newcred->cr_uid = pag;
3253 if (!code && *com == PSETPAG) {
3254 /* Special case for 'setpag' */
3255 afs_uint32 pagvalue = genpag();
3257 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3259 * Note that we leave the 'outexporter' struct held so it won't
3262 au->exporter = outexporter;
3263 if (ablob->out_size >= 4) {
3264 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3266 afs_PutUser(au, WRITE_LOCK);
3267 if (code) return code;
3268 return PSETPAG; /* Special return for setpag */
3270 EXP_RELE(outexporter);
3273 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3276 /* get all interface addresses of this client */
3279 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3282 struct vrequest *areq;
3285 afs_int32 *aoutSize;
3287 struct sprefrequest *spin; /* input */
3288 struct sprefinfo *spout; /* output */
3289 struct spref *srvout; /* one output component */
3293 AFS_STATCNT(PGetCPrefs);
3294 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3295 return EIO; /* Inappropriate ioctl for device */
3297 if ( ainSize < sizeof (struct sprefrequest ))
3300 spin = (struct sprefrequest *) ain;
3301 spout = (struct sprefinfo *) aout;
3303 maxNumber = spin->num_servers; /* max addrs this time */
3304 srvout = spout->servers;
3306 ObtainReadLock(&afs_xinterface);
3308 /* copy out the client interface information from the
3309 ** kernel data structure "interface" to the output buffer
3311 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3312 && ( j< maxNumber) ; i++, j++, srvout++)
3313 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3315 spout->num_servers = j;
3316 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3318 if ( i >= afs_cb_interface.numberOfInterfaces )
3319 spout->next_offset = 0; /* start from beginning again */
3321 spout->next_offset = spin->offset + j;
3323 ReleaseReadLock(&afs_xinterface);
3328 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3331 struct vrequest *areq;
3334 afs_int32 *aoutSize;
3336 struct setspref *sin;
3339 AFS_STATCNT(PSetCPrefs);
3340 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3341 return EIO; /* Inappropriate ioctl for device */
3343 sin = (struct setspref *)ain;
3345 if ( ainSize < sizeof(struct setspref) )
3347 #if 0 /* num_servers is unsigned */
3348 if ( sin->num_servers < 0 )
3351 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3354 ObtainWriteLock(&afs_xinterface, 412);
3355 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3356 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3357 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3359 ReleaseWriteLock(&afs_xinterface);
3363 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3366 struct vrequest *areq;
3369 afs_int32 *aoutSize;
3370 struct AFS_UCRED *acred; {
3371 register afs_int32 code;
3372 register struct vcache *tvc;
3373 register struct dcache *tdc;
3374 struct VenusFid tfid;
3376 afs_int32 offset, len, hasatsys=0;
3378 AFS_STATCNT(PFlushMount);
3379 if (!avc) return EINVAL;
3380 code = afs_VerifyVCache(avc, areq);
3381 if (code) return code;
3382 if (vType(avc) != VDIR) {
3385 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3386 if (!tdc) return ENOENT;
3387 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3388 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3393 tfid.Cell = avc->fid.Cell;
3394 tfid.Fid.Volume = avc->fid.Fid.Volume;
3395 afs_PutDCache(tdc); /* we're done with the data */
3396 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3397 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3399 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3406 if (vType(tvc) != VLNK) {
3407 afs_PutVCache(tvc, WRITE_LOCK);
3411 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3412 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3414 ObtainWriteLock(&tvc->lock,645);
3415 ObtainWriteLock(&afs_xcbhash, 646);
3416 afs_DequeueCallback(tvc);
3417 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3418 ReleaseWriteLock(&afs_xcbhash);
3419 /* now find the disk cache entries */
3420 afs_TryToSmush(tvc, acred, 1);
3421 osi_dnlc_purgedp(tvc);
3422 afs_symhint_inval(tvc);
3423 if (tvc->linkData && !(tvc->states & CCore)) {
3424 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3425 tvc->linkData = (char *) 0;
3427 ReleaseWriteLock(&tvc->lock);
3428 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3429 afs_BozonUnlock(&tvc->pvnLock, tvc);
3431 afs_PutVCache(tvc, WRITE_LOCK);
3433 if (hasatsys) osi_FreeLargeSpace(bufp);
3437 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3440 struct vrequest *areq;
3443 afs_int32 *aoutSize;
3444 struct AFS_UCRED *acred;
3449 if (!afs_osi_suser(acred)) {
3453 if (ainSize != sizeof(afs_int32)) {
3457 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3458 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3462 if (flags & AFSCALL_RXSTATS_ENABLE) {
3463 rx_enableProcessRPCStats();
3465 if (flags & AFSCALL_RXSTATS_DISABLE) {
3466 rx_disableProcessRPCStats();
3468 if (flags & AFSCALL_RXSTATS_CLEAR) {
3469 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3477 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3480 struct vrequest *areq;
3483 afs_int32 *aoutSize;
3484 struct AFS_UCRED *acred;
3489 if (!afs_osi_suser(acred)) {
3493 if (ainSize != sizeof(afs_int32)) {
3497 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3498 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3502 if (flags & AFSCALL_RXSTATS_ENABLE) {
3503 rx_enablePeerRPCStats();
3505 if (flags & AFSCALL_RXSTATS_DISABLE) {
3506 rx_disablePeerRPCStats();
3508 if (flags & AFSCALL_RXSTATS_CLEAR) {
3509 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);