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();
63 static int PGetRxkcrypt(), PSetRxkcrypt();
64 static int PPrefetchFromTape(), PResidencyCmd();
67 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
69 extern struct cm_initparams cm_initParams;
71 static int (*(pioctlSw[]))() = {
76 PGetVolumeStatus, /* 4 */
77 PSetVolumeStatus, /* 5 */
82 PCheckServers, /* 10 */
83 PCheckVolNames, /* 11 */
85 PBogus, /* 13 -- used to be quick check time */
87 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
88 PBogus, /* 16 -- used to be testing code */
89 PNoop, /* 17 -- used to be enable group */
90 PNoop, /* 18 -- used to be disable group */
91 PBogus, /* 19 -- used to be list group */
93 PUnlog, /* 21 -- unlog *is* unpag in this system */
94 PGetFID, /* 22 -- get file ID */
95 PBogus, /* 23 -- used to be waitforever */
96 PSetCacheSize, /* 24 */
97 PRemoveCallBack, /* 25 -- flush only the callback */
100 PRemoveMount, /* 28 -- delete mount point */
101 PNewStatMount, /* 29 -- new style mount point stat */
102 PGetFileCell, /* 30 -- get cell name for input file */
103 PGetWSCell, /* 31 -- get cell name for workstation */
104 PMariner, /* 32 - set/get mariner host */
105 PGetUserCell, /* 33 -- get cell name for user */
106 PVenusLogging, /* 34 -- Enable/Disable logging */
107 PGetCellStatus, /* 35 */
108 PSetCellStatus, /* 36 */
109 PFlushVolumeData, /* 37 -- flush all data from a volume */
110 PSetSysName, /* 38 - Set system name */
111 PExportAfs, /* 39 - Export Afs to remote nfs clients */
112 PGetCacheSize, /* 40 - get cache size and usage */
113 PGetVnodeXStatus, /* 41 - get vcache's special status */
114 PSetSPrefs33, /* 42 - Set CM Server preferences... */
115 PGetSPrefs, /* 43 - Get CM Server preferences... */
116 PGag, /* 44 - turn off/on all CM messages */
117 PTwiddleRx, /* 45 - adjust some RX params */
118 PSetSPrefs, /* 46 - Set CM Server preferences... */
119 PStoreBehind, /* 47 - set degree of store behind to be done */
120 PGCPAGs, /* 48 - disable automatic pag gc-ing */
121 PGetInitParams, /* 49 - get initial cm params */
122 PGetCPrefs, /* 50 - get client interface addresses */
123 PSetCPrefs, /* 51 - set client interface addresses */
124 PFlushMount, /* 52 - flush mount symlink data */
125 PRxStatProc, /* 53 - control process RX statistics */
126 PRxStatPeer, /* 54 - control peer RX statistics */
127 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
128 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
129 PNoop, /* 57 -- arla: set file prio */
130 PNoop, /* 58 -- arla: fallback getfh */
131 PNoop, /* 59 -- arla: fallback fhopen */
132 PNoop, /* 60 -- arla: controls xfsdebug */
133 PNoop, /* 61 -- arla: controls arla debug */
134 PNoop, /* 62 -- arla: debug interface */
135 PNoop, /* 63 -- arla: print xfs status */
136 PNoop, /* 64 -- arla: force cache check */
137 PNoop, /* 65 -- arla: break callback */
138 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
139 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
142 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
143 int afs_nobody = NFS_NOBODY;
146 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
148 dst->in = (char *)(unsigned long)src->in;
149 dst->out = (char *)(unsigned long)src->out;
150 dst->in_size = src->in_size;
151 dst->out_size = src->out_size;
155 * If you need to change copyin_afs_ioctl(), you may also need to change
160 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
164 #if defined(AFS_HPUX_64BIT_ENV)
165 struct afs_ioctl32 dst32;
167 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
169 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
171 afs_ioctl32_to_afs_ioctl(&dst32, dst);
174 #endif /* defined(AFS_HPUX_64BIT_ENV) */
176 #if defined(AFS_SUN57_64BIT_ENV)
177 struct afs_ioctl32 dst32;
179 if (get_udatamodel() == DATAMODEL_ILP32) {
180 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
182 afs_ioctl32_to_afs_ioctl(&dst32, dst);
185 #endif /* defined(AFS_SUN57_64BIT_ENV) */
187 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
188 struct afs_ioctl32 dst32;
190 if (!ABI_IS_64BIT(get_current_abi()))
192 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
194 afs_ioctl32_to_afs_ioctl(&dst32, dst);
197 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
199 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV)
200 struct afs_ioctl32 dst32;
202 #ifdef AFS_SPARC64_LINUX24_ENV
203 if (current->thread.flags & SPARC_FLAG_32BIT)
204 #elif AFS_SPARC64_LINUX20_ENV
205 if (current->tss.flags & SPARC_FLAG_32BIT)
207 #error Not done for this linux type
208 #endif /* AFS_SPARC64_LINUX20_ENV */
210 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
212 afs_ioctl32_to_afs_ioctl(&dst32, dst);
215 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
217 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
221 HandleIoctl(avc, acom, adata)
222 register struct vcache *avc;
223 register afs_int32 acom;
224 struct afs_ioctl *adata; {
225 register afs_int32 code;
228 AFS_STATCNT(HandleIoctl);
230 switch(acom & 0xff) {
232 avc->states |= CSafeStore;
236 /* case 2 used to be abort store, but this is no longer provided,
237 since it is impossible to implement under normal Unix.
241 /* return the name of the cell this file is open on */
242 register struct cell *tcell;
243 register afs_int32 i;
245 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
247 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
249 if (i > adata->out_size) {
250 /* 0 means we're not interested in the output */
251 if (adata->out_size != 0) code = EFAULT;
255 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
257 afs_PutCell(tcell, READ_LOCK);
263 case 49: /* VIOC_GETINITPARAMS */
264 if (adata->out_size < sizeof(struct cm_initparams)) {
268 AFS_COPYOUT(&cm_initParams, adata->out,
269 sizeof(struct cm_initparams), code);
278 return code; /* so far, none implemented */
283 /* For aix we don't temporarily bypass ioctl(2) but rather do our
284 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
285 * is now called from afs_gn_ioctl.
287 afs_ioctl(tvc, cmd, arg)
292 struct afs_ioctl data;
295 AFS_STATCNT(afs_ioctl);
296 if (((cmd >> 8) & 0xff) == 'V') {
297 /* This is a VICEIOCTL call */
298 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
301 error = HandleIoctl(tvc, cmd, &data);
304 /* No-op call; just return. */
308 #endif /* AFS_AIX_ENV */
310 #if defined(AFS_SGI_ENV)
311 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
317 struct afs_ioctl data;
323 AFS_STATCNT(afs_ioctl);
324 if (((cmd >> 8) & 0xff) == 'V') {
325 /* This is a VICEIOCTL call */
326 error = copyin_afs_ioctl(arg, &data);
329 locked = ISAFS_GLOCK();
332 error = HandleIoctl(tvc, cmd, &data);
337 /* No-op call; just return. */
341 #endif /* AFS_SGI_ENV */
344 /* unlike most calls here, this one uses u.u_error to return error conditions,
345 since this is really an intercepted chapter 2 call, rather than a vnode
348 /* AFS_HPUX102 and up uses VNODE ioctl instead */
349 #ifndef AFS_HPUX102_ENV
350 #if !defined(AFS_SGI_ENV)
352 kioctl(fdes, com, arg, ext)
359 } u_uap, *uap = &u_uap;
363 struct afs_ioctl_sys {
369 afs_xioctl (uap, rvp)
370 struct afs_ioctl_sys *uap;
375 afs_xioctl (p, args, retval)
384 } *uap = (struct a *)args;
385 #else /* AFS_OSF_ENV */
386 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
392 afs_xioctl(p, uap, retval)
394 register struct ioctl_args *uap;
398 #ifdef AFS_LINUX22_ENV
399 struct afs_ioctl_sys {
403 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
404 unsigned int com, unsigned long arg)
406 struct afs_ioctl_sys ua, *uap = &ua;
414 } *uap = (struct a *)u.u_ap;
415 #endif /* AFS_LINUX22_ENV */
416 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
417 #endif /* AFS_OSF_ENV */
418 #endif /* AFS_SUN5_ENV */
420 #ifndef AFS_LINUX22_ENV
421 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
424 register struct file *fd;
427 register struct vcache *tvc;
428 register int ioctlDone = 0, code = 0;
430 AFS_STATCNT(afs_xioctl);
431 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
432 if ((code=fdgetf(p, uap->fd, &fd)))
435 #ifdef AFS_LINUX22_ENV
443 if (setuerror(getf(uap->fd, &fd))) {
449 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
451 #else /* AFS_OSF_ENV */
453 #if defined(AFS_SUN57_ENV)
455 if (!fd) return(EBADF);
456 #elif defined(AFS_SUN54_ENV)
458 if (!fd) return(EBADF);
460 if (code = getf(uap->fd, &fd)) {
473 /* first determine whether this is any sort of vnode */
474 #ifdef AFS_LINUX22_ENV
475 tvc = (struct vcache *)ip;
479 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
481 if (fd->f_type == DTYPE_VNODE) {
483 /* good, this is a vnode; next see if it is an AFS vnode */
484 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
485 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
487 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
489 #endif /* AFS_LINUX22_ENV */
490 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
492 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
493 if (!tvc) { /* shouldn't happen with held gnodes */
498 /* This is an AFS vnode */
499 if (((uap->com >> 8) & 0xff) == 'V') {
500 register struct afs_ioctl *datap;
502 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
503 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
505 osi_FreeSmallSpace(datap);
507 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
510 #if defined(AFS_SUN5_ENV)
525 #else /* AFS_OSF_ENV */
529 #ifdef AFS_LINUX22_ENV
539 code = HandleIoctl(tvc, uap->com, datap);
540 osi_FreeSmallSpace(datap);
554 #if defined(AFS_LINUX22_ENV)
564 code = okioctl(fdes, com, arg, ext);
568 okioctl(fdes, com, arg, ext);
570 #if defined(AFS_SUN5_ENV)
571 #if defined(AFS_SUN57_ENV)
573 #elif defined(AFS_SUN54_ENV)
578 code = ioctl(uap, rvp);
580 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
581 return ioctl(p, uap, retval);
584 code = ioctl(p, args, retval);
591 #else /* AFS_OSF_ENV */
592 #ifndef AFS_LINUX22_ENV
610 #ifdef AFS_LINUX22_ENV
613 #if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
616 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
617 return (getuerror() ? -1 : u.u_ioctlrv);
619 return getuerror() ? -1 : 0;
622 #endif /* AFS_LINUX22_ENV */
623 #endif /* AFS_SUN5_ENV */
624 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
628 #endif /* AFS_SGI_ENV */
629 #endif /* AFS_HPUX102_ENV */
631 #if defined(AFS_SGI_ENV)
632 /* "pioctl" system call entry point; just pass argument to the parameterized
641 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
645 AFS_STATCNT(afs_pioctl);
647 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
655 #endif /* AFS_SGI_ENV */
658 afs_pioctl(p, args, retval)
668 } *uap = (struct a *) args;
670 AFS_STATCNT(afs_pioctl);
671 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
674 extern struct mount *afs_globalVFS;
675 #else /* AFS_OSF_ENV */
676 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
677 afs_pioctl(p, args, retval)
687 } *uap = (struct a *) args;
689 AFS_STATCNT(afs_pioctl);
690 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
693 extern struct mount *afs_globalVFS;
694 #else /* AFS_OSF_ENV */
695 extern struct vfs *afs_globalVFS;
699 /* macro to avoid adding any more #ifdef's to pioctl code. */
700 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
701 #define PIOCTL_FREE_CRED() crfree(credp)
703 #define PIOCTL_FREE_CRED()
707 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
709 struct AFS_UCRED *credp;
711 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
712 afs_syscall_pioctl(path, com, cmarg, follow, credp)
713 struct AFS_UCRED *credp;
715 afs_syscall_pioctl(path, com, cmarg, follow)
723 struct afs_ioctl data;
724 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
725 register afs_int32 code = 0;
731 struct ucred *credp = crref(); /* don't free until done! */
733 #ifdef AFS_LINUX22_ENV
734 cred_t *credp = crref(); /* don't free until done! */
737 AFS_STATCNT(afs_syscall_pioctl);
738 if (follow) follow = 1; /* compat. with old venus */
740 if (! _VALIDVICEIOCTL(com)) {
742 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
744 #else /* AFS_OSF_ENV */
745 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
754 code = copyin_afs_ioctl(cmarg, &data);
757 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
764 if ((com & 0xff) == PSetClientContext) {
765 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
766 return EINVAL; /* Not handling these yet. */
768 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
769 code = HandleClientContext(&data, &com, &foreigncreds, credp);
771 #if defined(AFS_HPUX101_ENV)
772 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
775 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
777 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
778 #endif /* AFS_SGI_ENV */
784 crfree(foreigncreds);
787 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
790 return (setuerror(code), code);
794 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
797 * We could have done without temporary setting the u.u_cred below
798 * (foreigncreds could be passed as param the pioctl modules)
799 * but calls such as afs_osi_suser() doesn't allow that since it
800 * references u.u_cred directly. We could, of course, do something
801 * like afs_osi_suser(cred) which, I think, is better since it
802 * generalizes and supports multi cred environments...
806 credp = foreigncreds;
809 tmpcred = crref(); /* XXX */
812 #if defined(AFS_HPUX101_ENV)
813 tmpcred = p_cred(u.u_procp);
814 set_p_cred(u.u_procp, foreigncreds);
817 tmpcred = OSI_GET_CURRENT_CRED();
818 OSI_SET_CURRENT_CRED(foreigncreds);
821 u.u_cred = foreigncreds;
822 #endif /* AFS_SGI64_ENV */
823 #endif /* AFS_HPUX101_ENV */
828 if ((com & 0xff) == 15) {
829 /* special case prefetch so entire pathname eval occurs in helper process.
830 otherwise, the pioctl call is essentially useless */
831 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
832 code = Prefetch(path, &data, follow,
833 foreigncreds ? foreigncreds : credp);
835 #if defined(AFS_HPUX101_ENV)
836 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
839 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
841 code = Prefetch(path, &data, follow, u.u_cred);
842 #endif /* AFS_SGI64_ENV */
843 #endif /* AFS_HPUX101_ENV */
845 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
848 crset(tmpcred); /* restore original credentials */
850 #if defined(AFS_HPUX101_ENV)
851 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
855 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
857 u.u_cred = tmpcred; /* restore original credentials */
860 #endif /* AFS_HPUX101_ENV */
861 crfree(foreigncreds);
864 #endif /* AFS_LINUX22_ENV */
866 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
869 return (setuerror(code), code);
875 code = lookupname(path, USR, follow, NULL, &vp,
876 foreigncreds ? foreigncreds : credp);
878 #ifdef AFS_LINUX22_ENV
879 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
881 vp = (struct vnode *)dp->d_inode;
883 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
884 #endif /* AFS_LINUX22_ENV */
885 #endif /* AFS_AIX41_ENV */
888 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
891 crset(tmpcred); /* restore original credentials */
893 #if defined(AFS_HPUX101_ENV)
894 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
896 #if !defined(AFS_SUN5_ENV)
898 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
900 u.u_cred = tmpcred; /* restore original credentials */
901 #endif /* AFS_SGI64_ENV */
903 #endif /* AFS_HPUX101_ENV */
904 crfree(foreigncreds);
907 #endif /* AFS_LINUX22_ENV */
909 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
912 return(setuerror(code), code);
916 else vp = (struct vnode *) 0;
918 /* now make the call if we were passed no file, or were passed an AFS file */
919 if (!vp || IsAfsVnode(vp)) {
921 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
922 * So, we must test in this part of the code. Also, must arrange to
923 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
924 * we hold gnodes, whose references hold our vcache entries.
927 gp = vp; /* remember for "put" */
928 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
930 else gp = (struct vnode *) 0;
933 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
937 struct ucred *cred1, *cred2;
940 cred1 = cred2 = foreigncreds;
942 cred1 = cred2 = credp;
944 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
945 if (cred1 != cred2) {
946 /* something changed the creds */
951 #if defined(AFS_HPUX101_ENV)
953 struct ucred *cred = p_cred(u.u_procp);
954 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
960 credp = OSI_GET_CURRENT_CRED();
961 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
964 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
965 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
967 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
969 #endif /* AFS_SGI_ENV */
970 #endif /* AFS_HPUX101_ENV */
971 #endif /* AFS_AIX41_ENV */
972 #endif /* AFS_SUN5_ENV */
974 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
975 code = EINVAL; /* not in /afs */
982 vp = (struct vnode *) 0;
987 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
992 #if defined(AFS_HPUX101_ENV)
993 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
997 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
999 u.u_cred = tmpcred; /* restore original credentials */
1000 #endif /* ASF_SGI64_ENV */
1002 #endif /* AFS_HPUX101_ENV */
1003 crfree(foreigncreds);
1006 #endif /* AFS_LINUX22_ENV */
1008 #ifdef AFS_LINUX22_ENV
1011 AFS_RELE(vp); /* put vnode back */
1015 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1020 return (getuerror());
1025 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
1026 register struct vcache *avc;
1028 struct AFS_UCRED **acred;
1029 register struct afs_ioctl *ablob;
1032 struct vrequest treq;
1033 register afs_int32 code;
1034 register afs_int32 function;
1035 afs_int32 inSize, outSize;
1036 char *inData, *outData;
1038 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1039 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1040 AFS_STATCNT(HandlePioctl);
1041 if (code = afs_InitReq(&treq, *acred)) return code;
1042 function = acom & 0xff;
1043 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
1044 return EINVAL; /* out of range */
1046 inSize = ablob->in_size;
1047 if (inSize >= PIGGYSIZE) return E2BIG;
1048 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1050 AFS_COPYIN(ablob->in, inData, inSize, code);
1054 osi_FreeLargeSpace(inData);
1057 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1059 if (function == 3) /* PSetTokens */
1060 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1062 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1063 osi_FreeLargeSpace(inData);
1064 if (code == 0 && ablob->out_size > 0) {
1065 if (outSize > ablob->out_size) outSize = ablob->out_size;
1066 if (outSize >= PIGGYSIZE) code = E2BIG;
1068 AFS_COPYOUT(outData, ablob->out, outSize, code);
1070 osi_FreeLargeSpace(outData);
1071 return afs_CheckCode(code, &treq, 41);
1074 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1077 struct vrequest *areq;
1080 afs_int32 *aoutSize; /* set this */ {
1081 register afs_int32 code;
1083 AFS_STATCNT(PGetFID);
1084 if (!avc) return EINVAL;
1085 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1086 *aoutSize = sizeof(struct VenusFid);
1090 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1093 struct vrequest *areq;
1096 afs_int32 *aoutSize; /* set this */ {
1097 register afs_int32 code;
1099 struct AFSOpaque acl;
1100 struct AFSVolSync tsync;
1101 struct AFSFetchStatus OutStatus;
1104 AFS_STATCNT(PSetAcl);
1107 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1110 acl.AFSOpaque_val = ain;
1112 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1114 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1115 #ifdef RX_ENABLE_LOCKS
1117 #endif /* RX_ENABLE_LOCKS */
1118 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1119 &acl, &OutStatus, &tsync);
1120 #ifdef RX_ENABLE_LOCKS
1122 #endif /* RX_ENABLE_LOCKS */
1127 (afs_Analyze(tconn, code, &avc->fid, areq,
1128 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1130 /* now we've forgotten all of the access info */
1131 ObtainWriteLock(&afs_xcbhash, 455);
1133 afs_DequeueCallback(avc);
1134 avc->states &= ~(CStatd | CUnique);
1135 ReleaseWriteLock(&afs_xcbhash);
1136 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1137 osi_dnlc_purgedp(avc);
1141 int afs_defaultAsynchrony = 0;
1143 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1146 struct vrequest *areq;
1149 afs_int32 *aoutSize; /* set this */
1150 struct AFS_UCRED *acred;
1153 struct sbstruct *sbr;
1155 sbr = (struct sbstruct *)ain;
1156 if (sbr->sb_default != -1) {
1157 if (afs_osi_suser(acred))
1158 afs_defaultAsynchrony = sbr->sb_default;
1162 if (avc && (sbr->sb_thisfile != -1))
1163 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1164 areq, DONT_CHECK_MODE_BITS))
1165 avc->asynchrony = sbr->sb_thisfile;
1168 *aoutSize = sizeof(struct sbstruct);
1169 sbr = (struct sbstruct *)aout;
1170 sbr->sb_default = afs_defaultAsynchrony;
1172 sbr->sb_thisfile = avc->asynchrony;
1178 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1181 struct vrequest *areq;
1184 afs_int32 *aoutSize; /* set this */
1185 struct AFS_UCRED *acred;
1187 if (!afs_osi_suser(acred)) {
1190 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1194 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1197 struct vrequest *areq;
1200 afs_int32 *aoutSize; /* set this */ {
1201 struct AFSOpaque acl;
1202 struct AFSVolSync tsync;
1203 struct AFSFetchStatus OutStatus;
1209 AFS_STATCNT(PGetAcl);
1210 if (!avc) return EINVAL;
1211 Fid.Volume = avc->fid.Fid.Volume;
1212 Fid.Vnode = avc->fid.Fid.Vnode;
1213 Fid.Unique = avc->fid.Fid.Unique;
1214 if (avc->states & CForeign) {
1216 * For a dfs xlator acl we have a special hack so that the
1217 * xlator will distinguish which type of acl will return. So
1218 * we currently use the top 2-bytes (vals 0-4) to tell which
1219 * type of acl to bring back. Horrible hack but this will
1220 * cause the least number of changes to code size and interfaces.
1222 if (Fid.Vnode & 0xc0000000)
1224 Fid.Vnode |= (ainSize << 30);
1226 acl.AFSOpaque_val = aout;
1228 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1231 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1232 #ifdef RX_ENABLE_LOCKS
1234 #endif /* RX_ENABLE_LOCKS */
1235 code = RXAFS_FetchACL(tconn->id, &Fid,
1236 &acl, &OutStatus, &tsync);
1237 #ifdef RX_ENABLE_LOCKS
1239 #endif /* RX_ENABLE_LOCKS */
1244 (afs_Analyze(tconn, code, &avc->fid, areq,
1245 AFS_STATS_FS_RPCIDX_FETCHACL,
1246 SHARED_LOCK, (struct cell *)0));
1249 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1260 AFS_STATCNT(PBogus);
1264 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1267 struct vrequest *areq;
1271 afs_int32 *aoutSize; /* set this */ {
1272 register struct cell *tcell;
1274 AFS_STATCNT(PGetFileCell);
1275 if (!avc) return EINVAL;
1276 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1277 if (!tcell) return ESRCH;
1278 strcpy(aout, tcell->cellName);
1279 afs_PutCell(tcell, READ_LOCK);
1280 *aoutSize = strlen(aout) + 1;
1284 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1287 struct vrequest *areq;
1291 afs_int32 *aoutSize; /* set this */ {
1292 register struct cell *tcell=0, *cellOne=0;
1293 register struct afs_q *cq, *tq;
1295 AFS_STATCNT(PGetWSCell);
1296 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1297 return EIO; /* Inappropriate ioctl for device */
1299 ObtainReadLock(&afs_xcell);
1300 cellOne = (struct cell *) 0;
1302 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1303 tcell = QTOC(cq); tq = QNext(cq);
1304 if (tcell->states & CPrimary) break;
1305 if (tcell->cell == 1) cellOne = tcell;
1308 ReleaseReadLock(&afs_xcell);
1309 if (!tcell) { /* no primary cell, use cell #1 */
1310 if (!cellOne) return ESRCH;
1313 strcpy(aout, tcell->cellName);
1314 *aoutSize = strlen(aout) + 1;
1318 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1321 struct vrequest *areq;
1325 afs_int32 *aoutSize; /* set this */ {
1326 register afs_int32 i;
1327 register struct unixuser *tu;
1328 register struct cell *tcell;
1330 AFS_STATCNT(PGetUserCell);
1331 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1332 return EIO; /* Inappropriate ioctl for device */
1334 /* return the cell name of the primary cell for this user */
1335 i = UHash(areq->uid);
1336 ObtainWriteLock(&afs_xuser,224);
1337 for(tu = afs_users[i]; tu; tu = tu->next) {
1338 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1340 ReleaseWriteLock(&afs_xuser);
1345 tcell = afs_GetCell(tu->cell, READ_LOCK);
1346 afs_PutUser(tu, WRITE_LOCK);
1347 if (!tcell) return ESRCH;
1349 strcpy(aout, tcell->cellName);
1350 afs_PutCell(tcell, READ_LOCK);
1351 *aoutSize = strlen(aout)+1; /* 1 for the null */
1355 ReleaseWriteLock(&afs_xuser);
1362 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1365 struct vrequest *areq;
1369 afs_int32 *aoutSize; /* set this */
1370 struct AFS_UCRED **acred;
1373 register struct unixuser *tu;
1374 struct ClearToken clear;
1375 register struct cell *tcell;
1378 struct vrequest treq;
1379 afs_int32 flag, set_parent_pag = 0;
1381 AFS_STATCNT(PSetTokens);
1382 if (!afs_resourceinit_flag) {
1385 bcopy(ain, (char *)&i, sizeof(afs_int32));
1386 ain += sizeof(afs_int32);
1387 stp = ain; /* remember where the ticket is */
1388 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1390 ain += i; /* skip over ticket */
1391 bcopy(ain, (char *)&i, sizeof(afs_int32));
1392 ain += sizeof(afs_int32);
1393 if (i != sizeof(struct ClearToken)) {
1396 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1397 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1398 ain += sizeof(struct ClearToken);
1399 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1400 /* still stuff left? we've got primary flag and cell name. Set these */
1401 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1402 ain += sizeof(afs_int32); /* skip id field */
1403 /* rest is cell name, look it up */
1404 if (flag & 0x8000) { /* XXX Use Constant XXX */
1408 tcell = afs_GetCellByName(ain, READ_LOCK);
1417 /* default to cell 1, primary id */
1418 flag = 1; /* primary id */
1419 i = 1; /* cell number */
1420 tcell = afs_GetCell(1, READ_LOCK);
1421 if (!tcell) goto nocell;
1423 afs_PutCell(tcell, READ_LOCK);
1424 if (set_parent_pag) {
1426 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1427 struct proc *p=current_proc(); /* XXX */
1428 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1429 p->p_pid, p->p_comm);
1430 if (!setpag(p, acred, -1, &pag, 1)) {
1433 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1435 if (!setpag(acred, -1, &pag, 1)) {
1438 afs_InitReq(&treq, *acred);
1442 /* now we just set the tokens */
1443 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1444 tu->vid = clear.ViceId;
1445 if (tu->stp != (char *) 0) {
1446 afs_osi_Free(tu->stp, tu->stLen);
1448 tu->stp = (char *) afs_osi_Alloc(stLen);
1450 bcopy(stp, tu->stp, stLen);
1453 afs_stats_cmfullperf.authent.TicketUpdates++;
1454 afs_ComputePAGStats();
1455 #endif /* AFS_NOSTATS */
1456 tu->states |= UHasTokens;
1457 tu->states &= ~UTokensBad;
1458 afs_SetPrimary(tu, flag);
1459 tu->tokenTime =osi_Time();
1460 afs_ResetUserConns(tu);
1461 afs_PutUser(tu, WRITE_LOCK);
1476 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1479 struct vrequest *areq;
1482 afs_int32 *aoutSize; /* set this */ {
1484 char offLineMsg[256];
1486 register struct conn *tc;
1487 register afs_int32 code;
1488 struct VolumeStatus volstat;
1490 char *Name, *OfflineMsg, *MOTD;
1493 AFS_STATCNT(PGetVolumeStatus);
1494 if (!avc) return EINVAL;
1496 OfflineMsg = offLineMsg;
1499 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1501 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1502 #ifdef RX_ENABLE_LOCKS
1504 #endif /* RX_ENABLE_LOCKS */
1505 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1506 &Name, &OfflineMsg, &MOTD);
1507 #ifdef RX_ENABLE_LOCKS
1509 #endif /* RX_ENABLE_LOCKS */
1514 (afs_Analyze(tc, code, &avc->fid, areq,
1515 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1516 SHARED_LOCK, (struct cell *)0));
1518 if (code) return code;
1519 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1521 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1522 cp += sizeof(VolumeStatus);
1523 strcpy(cp, volName);
1524 cp += strlen(volName)+1;
1525 strcpy(cp, offLineMsg);
1526 cp += strlen(offLineMsg)+1;
1528 cp += strlen(motd)+1;
1529 *aoutSize = (cp - aout);
1533 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1536 struct vrequest *areq;
1539 afs_int32 *aoutSize; /* set this */ {
1541 char offLineMsg[256];
1543 register struct conn *tc;
1544 register afs_int32 code;
1545 struct AFSFetchVolumeStatus volstat;
1546 struct AFSStoreVolumeStatus storeStat;
1547 register struct volume *tvp;
1551 AFS_STATCNT(PSetVolumeStatus);
1552 if (!avc) return EINVAL;
1554 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1556 if (tvp->states & (VRO | VBackup)) {
1557 afs_PutVolume(tvp, READ_LOCK);
1560 afs_PutVolume(tvp, READ_LOCK);
1563 /* Copy the junk out, using cp as a roving pointer. */
1565 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1566 cp += sizeof(AFSFetchVolumeStatus);
1567 if (strlen(cp) >= sizeof(volName))
1569 strcpy(volName, cp);
1570 cp += strlen(volName)+1;
1571 if (strlen(cp) >= sizeof(offLineMsg))
1573 strcpy(offLineMsg, cp);
1574 cp += strlen(offLineMsg)+1;
1575 if (strlen(cp) >= sizeof(motd))
1579 if (volstat.MinQuota != -1) {
1580 storeStat.MinQuota = volstat.MinQuota;
1581 storeStat.Mask |= AFS_SETMINQUOTA;
1583 if (volstat.MaxQuota != -1) {
1584 storeStat.MaxQuota = volstat.MaxQuota;
1585 storeStat.Mask |= AFS_SETMAXQUOTA;
1588 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1590 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1591 #ifdef RX_ENABLE_LOCKS
1593 #endif /* RX_ENABLE_LOCKS */
1594 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1595 &storeStat, volName, offLineMsg, motd);
1596 #ifdef RX_ENABLE_LOCKS
1598 #endif /* RX_ENABLE_LOCKS */
1603 (afs_Analyze(tc, code, &avc->fid, areq,
1604 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1605 SHARED_LOCK, (struct cell *)0));
1607 if (code) return code;
1608 /* we are sending parms back to make compat. with prev system. should
1609 change interface later to not ask for current status, just set new status */
1611 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1612 cp += sizeof(VolumeStatus);
1613 strcpy(cp, volName);
1614 cp += strlen(volName)+1;
1615 strcpy(cp, offLineMsg);
1616 cp += strlen(offLineMsg)+1;
1618 cp += strlen(motd)+1;
1619 *aoutSize = cp - aout;
1623 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1624 register struct vcache *avc;
1626 struct vrequest *areq;
1629 afs_int32 *aoutSize; /* set this */
1630 struct AFS_UCRED *acred;
1633 AFS_STATCNT(PFlush);
1634 if (!avc) return EINVAL;
1635 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1636 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1638 ObtainWriteLock(&avc->lock,225);
1639 ObtainWriteLock(&afs_xcbhash, 456);
1640 afs_DequeueCallback(avc);
1641 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1642 ReleaseWriteLock(&afs_xcbhash);
1643 /* now find the disk cache entries */
1644 afs_TryToSmush(avc, acred, 1);
1645 osi_dnlc_purgedp(avc);
1646 afs_symhint_inval(avc);
1647 if (avc->linkData && !(avc->states & CCore)) {
1648 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1649 avc->linkData = (char *) 0;
1651 ReleaseWriteLock(&avc->lock);
1652 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1653 afs_BozonUnlock(&avc->pvnLock, avc);
1658 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1661 struct vrequest *areq;
1664 afs_int32 *aoutSize; /* set this */ {
1665 register afs_int32 code;
1666 register struct vcache *tvc;
1667 register struct dcache *tdc;
1668 struct VenusFid tfid;
1670 struct sysname_info sysState;
1671 afs_int32 offset, len;
1673 AFS_STATCNT(PNewStatMount);
1674 if (!avc) return EINVAL;
1675 code = afs_VerifyVCache(avc, areq);
1676 if (code) return code;
1677 if (vType(avc) != VDIR) {
1680 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1681 if (!tdc) return ENOENT;
1682 Check_AtSys(avc, ain, &sysState, areq);
1684 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1685 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1686 bufp = sysState.name;
1691 tfid.Cell = avc->fid.Cell;
1692 tfid.Fid.Volume = avc->fid.Fid.Volume;
1693 afs_PutDCache(tdc); /* we're done with the data */
1694 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1695 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1697 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1704 if (vType(tvc) != VLNK) {
1705 afs_PutVCache(tvc, WRITE_LOCK);
1709 ObtainWriteLock(&tvc->lock,226);
1710 code = afs_HandleLink(tvc, areq);
1712 if (tvc->linkData) {
1713 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1716 /* we have the data */
1717 strcpy(aout, tvc->linkData);
1718 *aoutSize = strlen(tvc->linkData)+1;
1723 ReleaseWriteLock(&tvc->lock);
1724 afs_PutVCache(tvc, WRITE_LOCK);
1726 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1730 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1733 struct vrequest *areq;
1736 afs_int32 *aoutSize; /* set this */ {
1737 register struct cell *tcell;
1738 register afs_int32 i;
1739 register struct unixuser *tu;
1744 AFS_STATCNT(PGetTokens);
1745 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1746 return EIO; /* Inappropriate ioctl for device */
1748 /* weird interface. If input parameter is present, it is an integer and
1749 we're supposed to return the parm'th tokens for this unix uid.
1750 If not present, we just return tokens for cell 1.
1751 If counter out of bounds, return EDOM.
1752 If no tokens for the particular cell, return ENOTCONN.
1753 Also, if this mysterious parm is present, we return, along with the
1754 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1755 at the end, in that order.
1757 if (newStyle = (ainSize > 0)) {
1758 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1760 i = UHash(areq->uid);
1761 ObtainReadLock(&afs_xuser);
1762 for(tu = afs_users[i]; tu; tu=tu->next) {
1764 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1765 if (iterator-- == 0) break; /* are we done yet? */
1769 if (tu->uid == areq->uid && tu->cell == 1) break;
1774 * No need to hold a read lock on each user entry
1778 ReleaseReadLock(&afs_xuser);
1783 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1784 tu->states |= (UTokensBad | UNeedsReset);
1785 afs_PutUser(tu, READ_LOCK);
1788 /* use iterator for temp */
1790 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1791 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1792 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1793 cp += sizeof(afs_int32);
1794 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1796 iterator = sizeof(struct ClearToken);
1797 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1798 cp += sizeof(afs_int32);
1799 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1800 cp += sizeof(struct ClearToken);
1802 /* put out primary id and cell name, too */
1803 iterator = (tu->states & UPrimary ? 1 : 0);
1804 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1805 cp += sizeof(afs_int32);
1806 tcell = afs_GetCell(tu->cell, READ_LOCK);
1808 strcpy(cp, tcell->cellName);
1809 cp += strlen(tcell->cellName)+1;
1810 afs_PutCell(tcell, READ_LOCK);
1814 *aoutSize = cp - aout;
1815 afs_PutUser(tu, READ_LOCK);
1819 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1822 struct vrequest *areq;
1825 afs_int32 *aoutSize; /* set this */ {
1826 register afs_int32 i;
1827 register struct unixuser *tu;
1829 AFS_STATCNT(PUnlog);
1830 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1831 return EIO; /* Inappropriate ioctl for device */
1833 i = UHash(areq->uid);
1834 ObtainWriteLock(&afs_xuser,227);
1835 for(tu=afs_users[i]; tu; tu=tu->next) {
1836 if (tu->uid == areq->uid) {
1838 tu->states &= ~UHasTokens;
1839 /* security is not having to say you're sorry */
1840 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1842 ReleaseWriteLock(&afs_xuser);
1843 /* We have to drop the lock over the call to afs_ResetUserConns, since
1844 * it obtains the afs_xvcache lock. We could also keep the lock, and
1845 * modify ResetUserConns to take parm saying we obtained the lock
1846 * already, but that is overkill. By keeping the "tu" pointer
1847 * held over the released lock, we guarantee that we won't lose our
1848 * place, and that we'll pass over every user conn that existed when
1849 * we began this call.
1851 afs_ResetUserConns(tu);
1853 ObtainWriteLock(&afs_xuser,228);
1855 /* set the expire times to 0, causes
1856 * afs_GCUserData to remove this entry
1858 tu->ct.EndTimestamp = 0;
1860 #endif /* UKERNEL */
1863 ReleaseWriteLock(&afs_xuser);
1867 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1870 struct vrequest *areq;
1873 afs_int32 *aoutSize; /* set this */ {
1874 afs_int32 newHostAddr;
1875 afs_int32 oldHostAddr;
1877 AFS_STATCNT(PMariner);
1879 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1881 oldHostAddr = 0xffffffff; /* disabled */
1883 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1884 if (newHostAddr == 0xffffffff) {
1885 /* disable mariner operations */
1888 else if (newHostAddr) {
1890 afs_marinerHost = newHostAddr;
1892 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1893 *aoutSize = sizeof(afs_int32);
1897 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1900 struct vrequest *areq;
1903 afs_int32 *aoutSize; /* set this */
1904 struct AFS_UCRED *acred;
1906 register char *cp = 0;
1908 register struct server *ts;
1909 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1911 struct chservinfo *pcheck;
1913 AFS_STATCNT(PCheckServers);
1915 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1916 return EIO; /* Inappropriate ioctl for device */
1918 if (*lp == 0x12345678) { /* For afs3.3 version */
1919 pcheck=(struct chservinfo *)ain;
1920 if (pcheck->tinterval >= 0) {
1922 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1923 *aoutSize = sizeof(afs_int32);
1924 if (pcheck->tinterval > 0) {
1925 if (!afs_osi_suser(acred))
1927 PROBE_INTERVAL=pcheck->tinterval;
1933 temp=pcheck->tflags;
1934 cp = pcheck->tbuffer;
1935 } else { /* For pre afs3.3 versions */
1936 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1937 cp = ain+sizeof(afs_int32);
1938 if (ainSize > sizeof(afs_int32))
1943 * 1: fast check, don't contact servers.
1944 * 2: local cell only.
1947 /* have cell name, too */
1948 cellp = afs_GetCellByName(cp, READ_LOCK);
1949 if (!cellp) return ENOENT;
1951 else cellp = (struct cell *) 0;
1952 if (!cellp && (temp & 2)) {
1953 /* use local cell */
1954 cellp = afs_GetCell(1, READ_LOCK);
1956 if (!(temp & 1)) { /* if not fast, call server checker routine */
1957 afs_CheckServers(1, cellp); /* check down servers */
1958 afs_CheckServers(0, cellp); /* check up servers */
1960 /* now return the current down server list */
1962 ObtainReadLock(&afs_xserver);
1963 for(i=0;i<NSERVERS;i++) {
1964 for(ts = afs_servers[i]; ts; ts=ts->next) {
1965 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1966 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1967 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1968 cp += sizeof(afs_int32);
1972 ReleaseReadLock(&afs_xserver);
1973 if (cellp) afs_PutCell(cellp, READ_LOCK);
1974 *aoutSize = cp - aout;
1978 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1981 struct vrequest *areq;
1984 afs_int32 *aoutSize; /* set this */ {
1985 AFS_STATCNT(PCheckVolNames);
1986 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1987 return EIO; /* Inappropriate ioctl for device */
1989 afs_CheckRootVolume();
1990 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1991 AFS_VOLCHECK_EXPIRED |
1993 AFS_VOLCHECK_MTPTS);
1997 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
2000 struct vrequest *areq;
2003 afs_int32 *aoutSize; /* set this */ {
2007 struct unixuser *tu;
2009 extern afs_rwlock_t afs_xsrvAddr;
2011 AFS_STATCNT(PCheckAuth);
2012 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2013 return EIO; /* Inappropriate ioctl for device */
2016 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2017 if (!tu) retValue = EACCES;
2019 /* we have a user */
2020 ObtainReadLock(&afs_xsrvAddr);
2021 ObtainReadLock(&afs_xconn);
2023 /* any tokens set? */
2024 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
2025 /* all connections in cell 1 working? */
2026 for(i=0;i<NSERVERS;i++) {
2027 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
2028 for (tc = sa->conns; tc; tc=tc->next) {
2029 if (tc->user == tu && (tu->states & UTokensBad))
2034 ReleaseReadLock(&afs_xsrvAddr);
2035 ReleaseReadLock(&afs_xconn);
2036 afs_PutUser(tu, READ_LOCK);
2038 bcopy((char *)&retValue, aout, sizeof(afs_int32));
2039 *aoutSize = sizeof(afs_int32);
2043 static Prefetch(apath, adata, afollow, acred)
2045 struct afs_ioctl *adata;
2047 struct AFS_UCRED *acred;
2050 register afs_int32 code;
2051 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2057 AFS_STATCNT(Prefetch);
2058 if (!apath) return EINVAL;
2059 tp = osi_AllocLargeSpace(1024);
2060 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2062 osi_FreeLargeSpace(tp);
2065 if (afs_BBusy()) { /* do this as late as possible */
2066 osi_FreeLargeSpace(tp);
2067 return EWOULDBLOCK; /* pretty close */
2069 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
2073 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
2076 struct vrequest *areq;
2079 afs_int32 *aoutSize; /* set this */ {
2080 register struct volume *tvp;
2081 register struct server *ts;
2082 register afs_int32 i;
2085 AFS_STATCNT(PFindVolume);
2086 if (!avc) return EINVAL;
2087 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2090 for(i=0;i<MAXHOSTS;i++) {
2091 ts = tvp->serverHost[i];
2093 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2094 cp += sizeof(afs_int32);
2097 /* still room for terminating NULL, add it on */
2098 ainSize = 0; /* reuse vbl */
2099 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2100 cp += sizeof(afs_int32);
2102 *aoutSize = cp - aout;
2103 afs_PutVolume(tvp, READ_LOCK);
2109 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2112 struct vrequest *areq;
2115 afs_int32 *aoutSize; /* set this */ {
2116 register afs_int32 code;
2119 AFS_STATCNT(PViceAccess);
2120 if (!avc) return EINVAL;
2121 code = afs_VerifyVCache(avc, areq);
2122 if (code) return code;
2123 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2124 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2129 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2132 struct vrequest *areq;
2135 afs_int32 *aoutSize; /* set this */
2136 struct AFS_UCRED *acred;
2141 AFS_STATCNT(PSetCacheSize);
2142 if (!afs_osi_suser(acred))
2144 /* too many things are setup initially in mem cache version */
2145 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2146 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2147 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2149 extern u_int afs_min_cache;
2150 if (newValue < afs_min_cache)
2151 afs_cacheBlocks = afs_min_cache;
2153 afs_cacheBlocks = newValue;
2155 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2156 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2157 afs_MaybeWakeupTruncateDaemon();
2158 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2159 afs_osi_Wait(1000, 0, 0);
2160 afs_MaybeWakeupTruncateDaemon();
2165 #define MAXGCSTATS 16
2166 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2169 struct vrequest *areq;
2172 afs_int32 *aoutSize; /* set this */ {
2173 afs_int32 results[MAXGCSTATS];
2175 AFS_STATCNT(PGetCacheSize);
2176 bzero((char *)results, sizeof(results));
2177 results[0] = afs_cacheBlocks;
2178 results[1] = afs_blocksUsed;
2179 bcopy((char *)results, aout, sizeof(results));
2180 *aoutSize = sizeof(results);
2184 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2187 struct vrequest *areq;
2190 afs_int32 *aoutSize; /* set this */ {
2191 register struct conn *tc;
2192 register afs_int32 code;
2193 struct AFSCallBack CallBacks_Array[1];
2194 struct AFSCBFids theFids;
2195 struct AFSCBs theCBs;
2198 AFS_STATCNT(PRemoveCallBack);
2199 if (!avc) return EINVAL;
2200 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2201 ObtainWriteLock(&avc->lock,229);
2202 theFids.AFSCBFids_len = 1;
2203 theCBs.AFSCBs_len = 1;
2204 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2205 theCBs.AFSCBs_val = CallBacks_Array;
2206 CallBacks_Array[0].CallBackType = CB_DROPPED;
2207 if (avc->callback) {
2209 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2211 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2212 #ifdef RX_ENABLE_LOCKS
2214 #endif /* RX_ENABLE_LOCKS */
2215 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2216 #ifdef RX_ENABLE_LOCKS
2218 #endif /* RX_ENABLE_LOCKS */
2221 /* don't set code on failure since we wouldn't use it */
2223 (afs_Analyze(tc, code, &avc->fid, areq,
2224 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2225 SHARED_LOCK, (struct cell *)0));
2227 ObtainWriteLock(&afs_xcbhash, 457);
2228 afs_DequeueCallback(avc);
2230 avc->states &= ~(CStatd | CUnique);
2231 ReleaseWriteLock(&afs_xcbhash);
2232 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2233 osi_dnlc_purgedp(avc);
2235 ReleaseWriteLock(&avc->lock);
2239 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2242 struct vrequest *areq;
2246 struct AFS_UCRED *acred;
2247 afs_int32 *aoutSize; /* set this */ {
2248 /* create a new cell */
2249 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2250 register struct cell *tcell;
2251 char *newcell=0, *linkedcell=0, *tp= ain;
2252 register afs_int32 code, linkedstate=0, ls;
2253 u_short fsport = 0, vlport = 0;
2256 AFS_STATCNT(PNewCell);
2257 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2258 return EIO; /* Inappropriate ioctl for device */
2260 if (!afs_osi_suser(acred))
2263 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2264 tp += sizeof(afs_int32);
2265 if (magic != 0x12345678)
2268 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2269 * server addresses while the 3.5 fs newcell command passes
2270 * MAXHOSTS. To figure out which is which, check if the cellname
2273 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2274 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2276 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2277 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2278 tp += (scount * sizeof(afs_int32));
2280 lp = (afs_int32 *)tp;
2283 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2284 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2285 tp += (3 * sizeof(afs_int32));
2287 if ((ls = *lp) & 1) {
2288 linkedcell = tp + strlen(newcell)+1;
2289 linkedstate |= CLinkedCell;
2292 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2293 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
2297 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2300 struct vrequest *areq;
2303 afs_int32 *aoutSize; /* set this */ {
2304 afs_int32 whichCell;
2305 register struct cell *tcell=0;
2306 register afs_int32 i;
2307 register char *cp, *tp = ain;
2308 register struct afs_q *cq, *tq;
2310 AFS_STATCNT(PListCells);
2311 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2312 return EIO; /* Inappropriate ioctl for device */
2314 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2315 tp += sizeof(afs_int32);
2316 ObtainReadLock(&afs_xcell);
2317 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2318 tcell = QTOC(cq); tq = QNext(cq);
2319 if (whichCell == 0) break;
2320 if (tq == &CellLRU) tcell = 0;
2325 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2326 for(i=0;i<MAXCELLHOSTS;i++) {
2327 if (tcell->cellHosts[i] == 0) break;
2328 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2329 cp += sizeof(afs_int32);
2331 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2332 strcpy(cp, tcell->cellName);
2333 cp += strlen(tcell->cellName)+1;
2334 *aoutSize = cp - aout;
2336 ReleaseReadLock(&afs_xcell);
2337 if (tcell) return 0;
2341 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2344 struct vrequest *areq;
2348 afs_int32 *aoutSize; /* set this */ {
2349 register afs_int32 code;
2351 struct sysname_info sysState;
2352 afs_int32 offset, len;
2353 register struct conn *tc;
2354 register struct dcache *tdc;
2355 register struct vcache *tvc;
2356 struct AFSFetchStatus OutDirStatus;
2357 struct VenusFid tfid;
2358 struct AFSVolSync tsync;
2362 /* "ain" is the name of the file in this dir to remove */
2364 AFS_STATCNT(PRemoveMount);
2365 if (!avc) return EINVAL;
2366 code = afs_VerifyVCache(avc, areq);
2367 if (code) return code;
2368 if (vType(avc) != VDIR) return ENOTDIR;
2370 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2371 if (!tdc) return ENOENT;
2372 Check_AtSys(avc, ain, &sysState, areq);
2374 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2375 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2376 bufp = sysState.name;
2381 tfid.Cell = avc->fid.Cell;
2382 tfid.Fid.Volume = avc->fid.Fid.Volume;
2383 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2384 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2386 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2387 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2394 if (vType(tvc) != VLNK) {
2396 afs_PutVCache(tvc, WRITE_LOCK);
2400 ObtainWriteLock(&tvc->lock,230);
2401 code = afs_HandleLink(tvc, areq);
2403 if (tvc->linkData) {
2404 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2409 ReleaseWriteLock(&tvc->lock);
2410 osi_dnlc_purgedp(tvc);
2411 afs_PutVCache(tvc, WRITE_LOCK);
2416 ObtainWriteLock(&avc->lock,231);
2417 osi_dnlc_remove(avc, bufp, tvc);
2419 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2421 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2422 #ifdef RX_ENABLE_LOCKS
2424 #endif /* RX_ENABLE_LOCKS */
2425 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2426 bufp, &OutDirStatus, &tsync);
2427 #ifdef RX_ENABLE_LOCKS
2429 #endif /* RX_ENABLE_LOCKS */
2434 (afs_Analyze(tc, code, &avc->fid, areq,
2435 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2436 SHARED_LOCK, (struct cell *)0));
2439 if (tdc) afs_PutDCache(tdc);
2440 ReleaseWriteLock(&avc->lock);
2444 /* we have the thing in the cache */
2445 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2446 /* we can do it locally */
2447 code = afs_dir_Delete(&tdc->f.inode, bufp);
2449 ZapDCE(tdc); /* surprise error -- invalid value */
2450 DZap(&tdc->f.inode);
2453 afs_PutDCache(tdc); /* drop ref count */
2455 avc->states &= ~CUnique; /* For the dfs xlator */
2456 ReleaseWriteLock(&avc->lock);
2459 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2463 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2466 struct vrequest *areq;
2470 struct AFS_UCRED *acred;
2471 afs_int32 *aoutSize; /* set this */ {
2472 return EINVAL; /* OBSOLETE */
2475 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2478 struct vrequest *areq;
2481 afs_int32 *aoutSize; /* set this */ {
2482 register struct cell *tcell;
2485 AFS_STATCNT(PGetCellStatus);
2486 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2487 return EIO; /* Inappropriate ioctl for device */
2489 tcell = afs_GetCellByName(ain, READ_LOCK);
2490 if (!tcell) return ENOENT;
2491 temp = tcell->states;
2492 afs_PutCell(tcell, READ_LOCK);
2493 bcopy((char *)&temp, aout, sizeof(afs_int32));
2494 *aoutSize = sizeof(afs_int32);
2498 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2501 struct vrequest *areq;
2504 struct AFS_UCRED *acred;
2505 afs_int32 *aoutSize; /* set this */ {
2506 register struct cell *tcell;
2509 if (!afs_osi_suser(acred))
2511 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2512 return EIO; /* Inappropriate ioctl for device */
2514 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2515 if (!tcell) return ENOENT;
2516 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2518 tcell->states |= CNoSUID;
2520 tcell->states &= ~CNoSUID;
2521 afs_PutCell(tcell, WRITE_LOCK);
2525 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2528 struct vrequest *areq;
2531 afs_int32 *aoutSize; /* set this */
2532 struct AFS_UCRED *acred;
2534 extern struct volume *afs_volumes[NVOLS];
2535 register afs_int32 i;
2536 register struct dcache *tdc;
2537 register struct vcache *tvc;
2538 register struct volume *tv;
2539 afs_int32 cell, volume;
2541 AFS_STATCNT(PFlushVolumeData);
2544 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2545 return EIO; /* Inappropriate ioctl for device */
2547 volume = avc->fid.Fid.Volume; /* who to zap */
2548 cell = avc->fid.Cell;
2551 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2552 * the vcaches associated with the volume.
2554 ObtainReadLock(&afs_xvcache);
2555 for(i = 0; i < VCSIZE; i++) {
2556 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2557 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2558 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2559 VN_HOLD((struct vnode *)tvc);
2561 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2567 ReleaseReadLock(&afs_xvcache);
2568 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2569 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2571 ObtainWriteLock(&tvc->lock,232);
2573 ObtainWriteLock(&afs_xcbhash, 458);
2574 afs_DequeueCallback(tvc);
2575 tvc->states &= ~(CStatd | CDirty);
2576 ReleaseWriteLock(&afs_xcbhash);
2577 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2578 osi_dnlc_purgedp(tvc);
2579 afs_TryToSmush(tvc, acred, 1);
2580 ReleaseWriteLock(&tvc->lock);
2581 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2582 afs_BozonUnlock(&tvc->pvnLock, tvc);
2584 ObtainReadLock(&afs_xvcache);
2585 /* our tvc ptr is still good until now */
2590 ReleaseReadLock(&afs_xvcache);
2593 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2594 for(i=0;i<afs_cacheFiles;i++) {
2595 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2596 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2597 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2598 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2599 if (! (afs_indexFlags[i] & IFDataMod)) {
2600 /* if the file is modified, but has a ref cnt of only 1, then
2601 someone probably has the file open and is writing into it.
2602 Better to skip flushing such a file, it will be brought back
2603 immediately on the next write anyway.
2605 If we *must* flush, then this code has to be rearranged to call
2606 afs_storeAllSegments() first */
2607 afs_FlushDCache(tdc);
2611 tdc->refCount--; /* bumped by getdslot */
2613 MReleaseWriteLock(&afs_xdcache);
2615 ObtainReadLock(&afs_xvolume);
2616 for (i=0;i<NVOLS;i++) {
2617 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2618 if (tv->volume == volume) {
2619 afs_ResetVolumeInfo(tv);
2624 ReleaseReadLock(&afs_xvolume);
2626 /* probably, a user is doing this, probably, because things are screwed up.
2627 * maybe it's the dnlc's fault? */
2634 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2637 struct vrequest *areq;
2640 afs_int32 *aoutSize; /* set this */ {
2641 register afs_int32 code;
2642 struct vcxstat stat;
2645 /* AFS_STATCNT(PGetVnodeXStatus); */
2646 if (!avc) return EINVAL;
2647 code = afs_VerifyVCache(avc, areq);
2648 if (code) return code;
2649 if (vType(avc) == VDIR)
2650 mode = PRSFS_LOOKUP;
2653 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2655 stat.fid = avc->fid;
2656 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2657 stat.lock = avc->lock;
2658 stat.parentVnode = avc->parentVnode;
2659 stat.parentUnique = avc->parentUnique;
2660 hset(stat.flushDV, avc->flushDV);
2661 hset(stat.mapDV, avc->mapDV);
2662 stat.truncPos = avc->truncPos;
2663 { /* just grab the first two - won't break anything... */
2664 struct axscache *ac;
2666 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2667 stat.randomUid[i] = ac->uid;
2668 stat.randomAccess[i] = ac->axess;
2671 stat.callback = afs_data_pointer_to_int32(avc->callback);
2672 stat.cbExpires = avc->cbExpires;
2673 stat.anyAccess = avc->anyAccess;
2674 stat.opens = avc->opens;
2675 stat.execsOrWriters = avc->execsOrWriters;
2676 stat.flockCount = avc->flockCount;
2677 stat.mvstat = avc->mvstat;
2678 stat.states = avc->states;
2679 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2680 *aoutSize = sizeof(struct vcxstat);
2685 /* We require root for local sysname changes, but not for remote */
2686 /* (since we don't really believe remote uids anyway) */
2687 /* outname[] shouldn't really be needed- this is left as an excercise */
2688 /* for the reader. */
2689 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2692 struct vrequest *areq;
2695 afs_int32 *aoutSize; /* set this */
2696 register struct AFS_UCRED *acred;
2698 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2699 int setsysname, foundname=0;
2700 register struct afs_exporter *exporter;
2701 extern struct unixuser *afs_FindUser();
2702 extern char *afs_sysname;
2703 extern char *afs_sysnamelist[];
2704 extern int afs_sysnamecount;
2705 register struct unixuser *au;
2706 register afs_int32 pag, error;
2710 AFS_STATCNT(PSetSysName);
2711 if (!afs_globalVFS) {
2712 /* Afsd is NOT running; disable it */
2713 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2716 return (setuerror(EINVAL), EINVAL);
2719 bzero(inname, MAXSYSNAME);
2720 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2721 ain += sizeof(afs_int32);
2725 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2727 for(cp = ain,count = 0;count < setsysname;count++) {
2728 /* won't go past end of ain since maxsysname*num < ain length */
2730 if (t >= MAXSYSNAME || t <= 0)
2732 /* check for names that can shoot us in the foot */
2733 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2739 /* inname gets first entry in case we're being a translater */
2741 bcopy(ain, inname, t+1); /* include terminating null */
2744 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2745 pag = PagInCred(acred);
2747 return EINVAL; /* Better than panicing */
2749 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2750 return EINVAL; /* Better than panicing */
2752 if (!(exporter = au->exporter)) {
2753 afs_PutUser(au, READ_LOCK);
2754 return EINVAL; /* Better than panicing */
2756 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2758 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2760 afs_PutUser(au, READ_LOCK);
2765 afs_PutUser(au, READ_LOCK);
2768 /* Not xlating, so local case */
2769 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2770 if (!setsysname) { /* user just wants the info */
2771 strcpy(outname, afs_sysname);
2772 foundname = afs_sysnamecount;
2773 } else { /* Local guy; only root can change sysname */
2774 if (!afs_osi_suser(acred))
2777 /* clear @sys entries from the dnlc, once afs_lookup can
2778 do lookups of @sys entries and thinks it can trust them */
2779 /* privs ok, store the entry, ... */
2780 strcpy(afs_sysname, inname);
2781 if (setsysname > 1) { /* ... or list */
2783 for(count=1; count < setsysname;++count) {
2784 if (!afs_sysnamelist[count])
2785 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2787 bcopy(cp, afs_sysnamelist[count], t+1); /* include null */
2791 afs_sysnamecount = setsysname;
2795 cp = aout; /* not changing so report back the count and ... */
2796 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2797 cp += sizeof(afs_int32);
2799 strcpy(cp, outname); /* ... the entry, ... */
2800 cp += strlen(outname)+1;
2801 for(count=1; count < foundname; ++count) { /* ... or list. */
2802 /* Note: we don't support @sys lists for exporters */
2803 if (!afs_sysnamelist[count])
2804 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2805 t = strlen(afs_sysnamelist[count]);
2806 if (t >= MAXSYSNAME)
2807 osi_Panic("PSetSysName: sysname entry garbled\n");
2808 strcpy(cp, afs_sysnamelist[count]);
2812 *aoutSize = cp - aout;
2817 /* sequential search through the list of touched cells is not a good
2818 * long-term solution here. For small n, though, it should be just
2819 * fine. Should consider special-casing the local cell for large n.
2820 * Likewise for PSetSPrefs.
2822 static void ReSortCells(s,l, vlonly)
2823 int s; /* number of ids in array l[] -- NOT index of last id */
2824 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2825 int vlonly; /* sort vl servers or file servers?*/
2827 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2836 tcell = afs_GetCell(l[k], WRITE_LOCK);
2837 if (!tcell) continue;
2838 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2839 afs_PutCell(tcell, WRITE_LOCK);
2844 ObtainReadLock(&afs_xvolume);
2845 for (i= 0; i< NVOLS; i++) {
2846 for (j=afs_volumes[i];j;j=j->next) {
2848 if (j->cell == l[k]) {
2849 ObtainWriteLock(&j->lock,233);
2850 afs_SortServers(j->serverHost, MAXHOSTS);
2851 ReleaseWriteLock(&j->lock);
2856 ReleaseReadLock(&afs_xvolume);
2861 static int afs_setsprefs(sp, num, vlonly)
2864 unsigned int vlonly;
2867 int i,j,k,matches,touchedSize;
2868 struct server *srvr = NULL;
2869 afs_int32 touched[34];
2873 for (k=0; k < num; sp++, k++) {
2875 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2878 ObtainReadLock(&afs_xserver);
2880 i = SHash(sp->host.s_addr);
2881 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2882 if (sa->sa_ip == sp->host.s_addr) {
2884 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2885 || (sa->sa_portal == AFS_FSPORT);
2886 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2893 if (sa && matches) { /* found one! */
2895 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2897 sa->sa_iprank = sp->rank + afs_randomMod15();
2898 afs_SortOneServer(sa->server);
2901 /* if we don't know yet what cell it's in, this is moot */
2902 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2903 /* is it in our list of touched cells ? */ ;
2904 if (j < 0) { /* no, it's not */
2905 touched[touchedSize++] = srvr->cell->cell;
2906 if (touchedSize >= 32) { /* watch for ovrflow */
2907 ReleaseReadLock(&afs_xserver);
2908 ReSortCells(touchedSize, touched, vlonly);
2910 ObtainReadLock(&afs_xserver);
2916 ReleaseReadLock(&afs_xserver);
2917 /* if we didn't find one, start to create one. */
2918 /* Note that it doesn't have a cell yet... */
2920 afs_uint32 temp = sp->host.s_addr;
2921 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2922 WRITE_LOCK, (afsUUID *)0,0);
2923 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2924 afs_PutServer(srvr, WRITE_LOCK);
2926 } /* for all cited preferences */
2928 ReSortCells(touchedSize, touched, vlonly);
2932 /* Note that this may only be performed by the local root user.
2935 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2938 struct vrequest *areq;
2941 struct AFS_UCRED *acred;
2942 afs_int32 *aoutSize;
2944 struct setspref *ssp;
2945 AFS_STATCNT(PSetSPrefs);
2947 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2948 return EIO; /* Inappropriate ioctl for device */
2950 if (!afs_osi_suser(acred))
2953 if (ainSize < sizeof(struct setspref))
2956 ssp = (struct setspref *)ain;
2957 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2960 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2961 (ssp->flags & DBservers));
2966 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2969 struct vrequest *areq;
2972 struct AFS_UCRED *acred;
2973 afs_int32 *aoutSize;
2976 AFS_STATCNT(PSetSPrefs);
2977 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2978 return EIO; /* Inappropriate ioctl for device */
2981 if (!afs_osi_suser(acred))
2984 sp = (struct spref *)ain;
2985 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2989 /* some notes on the following code...
2990 * in the hash table of server structs, all servers with the same IP address
2991 * will be on the same overflow chain.
2992 * This could be sped slightly in some circumstances by having it cache the
2993 * immediately previous slot in the hash table and some supporting information
2994 * Only reports file servers now.
2997 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3000 struct vrequest *areq;
3003 afs_int32 *aoutSize;
3005 struct sprefrequest *spin; /* input */
3006 struct sprefinfo *spout; /* output */
3007 struct spref *srvout; /* one output component */
3008 int i,j; /* counters for hash table traversal */
3009 struct server *srvr; /* one of CM's server structs */
3012 int vlonly; /* just return vlservers ? */
3015 AFS_STATCNT(PGetSPrefs);
3016 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3017 return EIO; /* Inappropriate ioctl for device */
3020 if (ainSize < sizeof (struct sprefrequest_33)) {
3024 spin = ((struct sprefrequest *) ain);
3027 if (ainSize > sizeof (struct sprefrequest_33)) {
3028 vlonly = (spin->flags & DBservers);
3032 /* struct sprefinfo includes 1 server struct... that size gets added
3033 * in during the loop that follows.
3035 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
3036 spout = (struct sprefinfo *) aout;
3037 spout->next_offset = spin->offset;
3038 spout->num_servers = 0;
3039 srvout = spout->servers;
3041 ObtainReadLock(&afs_xserver);
3042 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
3043 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
3044 if (spin->offset > (unsigned short)i) {
3045 continue; /* catch up to where we left off */
3047 spout->next_offset++;
3050 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3051 || (sa->sa_portal == AFS_FSPORT);
3053 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3054 /* only report ranks for vl servers */
3058 srvout->host.s_addr = sa->sa_ip;
3059 srvout->rank = sa->sa_iprank;
3060 *aoutSize += sizeof(struct spref);
3061 spout->num_servers++;
3064 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3065 ReleaseReadLock(&afs_xserver); /* no more room! */
3070 ReleaseReadLock(&afs_xserver);
3072 spout->next_offset = 0; /* start over from the beginning next time */
3076 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3077 int afs_NFSRootOnly = 1;
3078 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3081 struct vrequest *areq;
3084 afs_int32 *aoutSize; /* set this */
3085 struct AFS_UCRED *acred;
3087 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
3088 extern struct afs_exporter *exporter_find();
3089 register struct afs_exporter *exporter;
3091 AFS_STATCNT(PExportAfs);
3092 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
3093 type = handleValue >> 24;
3098 exporter = exporter_find(type);
3100 export = handleValue & 3;
3101 changestate = handleValue & 0xff;
3102 smounts = (handleValue >> 2) & 3;
3103 pwsync = (handleValue >> 4) & 3;
3104 convmode = (handleValue >> 6) & 3;
3106 changestate = (handleValue >> 16) & 0x1;
3107 convmode = (handleValue >> 16) & 0x2;
3108 pwsync = (handleValue >> 16) & 0x4;
3109 smounts = (handleValue >> 16) & 0x8;
3110 export = handleValue & 0xff;
3113 /* Failed finding desired exporter; */
3117 handleValue = exporter->exp_states;
3118 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3119 *aoutSize = sizeof(afs_int32);
3121 if (!afs_osi_suser(acred))
3122 return EACCES; /* Only superuser can do this */
3126 exporter->exp_states |= EXP_EXPORTED;
3128 exporter->exp_states &= ~EXP_EXPORTED;
3132 exporter->exp_states |= EXP_UNIXMODE;
3134 exporter->exp_states &= ~EXP_UNIXMODE;
3138 exporter->exp_states |= EXP_PWSYNC;
3140 exporter->exp_states &= ~EXP_PWSYNC;
3144 afs_NFSRootOnly = 0;
3145 exporter->exp_states |= EXP_SUBMOUNTS;
3147 afs_NFSRootOnly = 1;
3148 exporter->exp_states &= ~EXP_SUBMOUNTS;
3151 handleValue = exporter->exp_states;
3152 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3153 *aoutSize = sizeof(afs_int32);
3156 exporter->exp_states |= EXP_EXPORTED;
3158 exporter->exp_states &= ~EXP_EXPORTED;
3160 exporter->exp_states |= EXP_UNIXMODE;
3162 exporter->exp_states &= ~EXP_UNIXMODE;
3164 exporter->exp_states |= EXP_PWSYNC;
3166 exporter->exp_states &= ~EXP_PWSYNC;
3168 afs_NFSRootOnly = 0;
3169 exporter->exp_states |= EXP_SUBMOUNTS;
3171 afs_NFSRootOnly = 1;
3172 exporter->exp_states &= ~EXP_SUBMOUNTS;
3181 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3184 struct vrequest *areq;
3187 struct AFS_UCRED *acred;
3188 afs_int32 *aoutSize; /* set this */
3190 struct gaginfo *gagflags;
3192 if (!afs_osi_suser(acred))
3195 gagflags = (struct gaginfo *) ain;
3196 afs_showflags = gagflags->showflags;
3203 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3206 struct vrequest *areq;
3209 struct AFS_UCRED *acred;
3210 afs_int32 *aoutSize;
3212 struct rxparams *rxp;
3214 if (!afs_osi_suser(acred))
3217 rxp = (struct rxparams *) ain;
3219 if (rxp->rx_initReceiveWindow)
3220 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3221 if (rxp->rx_maxReceiveWindow)
3222 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3223 if (rxp->rx_initSendWindow)
3224 rx_initSendWindow = rxp->rx_initSendWindow;
3225 if (rxp->rx_maxSendWindow)
3226 rx_maxSendWindow = rxp->rx_maxSendWindow;
3227 if (rxp->rxi_nSendFrags)
3228 rxi_nSendFrags = rxp->rxi_nSendFrags;
3229 if (rxp->rxi_nRecvFrags)
3230 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3231 if (rxp->rxi_OrphanFragSize)
3232 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3233 if (rxp->rx_maxReceiveSize)
3235 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3236 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3238 if (rxp->rx_MyMaxSendSize)
3239 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3244 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3247 struct vrequest *areq;
3251 afs_int32 *aoutSize; /* set this */
3253 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3256 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3257 *aoutSize = sizeof(struct cm_initparams);
3261 #ifdef AFS_SGI65_ENV
3262 /* They took crget() from us, so fake it. */
3263 static cred_t *crget(void)
3266 cr = crdup(get_current_cred());
3267 bzero((char*)cr, sizeof(cred_t));
3268 #if CELL || CELL_PREPARE
3276 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3279 struct vrequest *areq;
3282 afs_int32 *aoutSize;
3283 struct AFS_UCRED *acred;
3285 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3286 *aoutSize=sizeof(afs_int32);
3291 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3294 struct vrequest *areq;
3297 afs_int32 *aoutSize;
3298 struct AFS_UCRED *acred;
3302 if (!afs_osi_suser(acred))
3304 if (ainSize != sizeof(afs_int32) || ain == NULL)
3306 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3307 /* if new mappings added later this will need to be changed */
3308 if (tmpval != 0 && tmpval != 1)
3315 * Create new credentials to correspond to a remote user with given
3316 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3317 * provide pioctl (and other) services to foreign clients (i.e. nfs
3318 * clients) by using this call to `become' the client.
3321 #define PIOCTL_HEADER 6
3322 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3325 afs_uint32 hostaddr;
3326 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3327 extern struct afs_exporter *exporter_find();
3328 struct afs_exporter *exporter, *outexporter;
3329 struct AFS_UCRED *newcred;
3330 struct unixuser *au;
3332 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3333 return EINVAL; /* NFS trans not supported for Ultrix */
3335 #if defined(AFS_SGIMP_ENV)
3336 osi_Assert(ISAFS_GLOCK());
3338 AFS_STATCNT(HandleClientContext);
3339 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3340 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3341 return EINVAL; /* Too small to be good */
3343 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3344 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3346 osi_FreeLargeSpace(inData);
3350 /* Extract information for remote user */
3351 hostaddr = *((afs_uint32 *)ain);
3352 ain += sizeof(hostaddr);
3353 uid = *((afs_uint32 *)ain);
3355 g0 = *((afs_uint32 *)ain);
3357 g1 = *((afs_uint32 *)ain);
3359 *com = *((afs_uint32 *)ain);
3360 ain += sizeof(afs_int32);
3361 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3364 * Of course, one must be root for most of these functions, but
3365 * we'll allow (for knfs) you to set things if the pag is 0 and
3366 * you're setting tokens or unlogging.
3369 if (!afs_osi_suser(credp)) {
3371 #ifndef AFS_SGI64_ENV
3372 /* Since SGI's suser() returns explicit failure after the call.. */
3376 /* check for acceptable opcodes for normal folks, which are, so far,
3377 * set tokens and unlog.
3379 if (i != 9 && i != 3 && i != 38 && i != 8) {
3380 osi_FreeLargeSpace(inData);
3385 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3386 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3387 osi_FreeLargeSpace(inData);
3390 * We map uid 0 to nobody to match the mapping that the nfs
3391 * server does and to ensure that the suser() calls in the afs
3392 * code fails for remote client roots.
3394 uid = afs_nobody; /* NFS_NOBODY == -2 */
3397 #ifdef AFS_AIX41_ENV
3400 newcred->cr_gid = RMTUSER_REQ;
3401 newcred->cr_groups[0] = g0;
3402 newcred->cr_groups[1] = g1;
3404 newcred->cr_ngrps = 2;
3406 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3407 newcred->cr_ngroups = 2;
3409 for (i=2; i<NGROUPS; i++)
3410 newcred->cr_groups[i] = NOGROUP;
3413 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3414 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3416 if (!(exporter = exporter_find(exporter_type))) {
3417 /* Exporter wasn't initialized or an invalid exporter type */
3421 if (exporter->exp_states & EXP_PWSYNC) {
3422 if (uid != credp->cr_uid) {
3424 return ENOEXEC; /* XXX Find a better errno XXX */
3427 newcred->cr_uid = uid; /* Only temporary */
3428 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3429 /* The client's pag is the only unique identifier for it */
3430 newcred->cr_uid = pag;
3432 if (!code && *com == PSETPAG) {
3433 /* Special case for 'setpag' */
3434 afs_uint32 pagvalue = genpag();
3436 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3438 * Note that we leave the 'outexporter' struct held so it won't
3441 au->exporter = outexporter;
3442 if (ablob->out_size >= 4) {
3443 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3445 afs_PutUser(au, WRITE_LOCK);
3446 if (code) return code;
3447 return PSETPAG; /* Special return for setpag */
3449 EXP_RELE(outexporter);
3452 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3455 /* get all interface addresses of this client */
3458 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3461 struct vrequest *areq;
3464 afs_int32 *aoutSize;
3466 struct sprefrequest *spin; /* input */
3467 struct sprefinfo *spout; /* output */
3468 struct spref *srvout; /* one output component */
3472 AFS_STATCNT(PGetCPrefs);
3473 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3474 return EIO; /* Inappropriate ioctl for device */
3476 if ( ainSize < sizeof (struct sprefrequest ))
3479 spin = (struct sprefrequest *) ain;
3480 spout = (struct sprefinfo *) aout;
3482 maxNumber = spin->num_servers; /* max addrs this time */
3483 srvout = spout->servers;
3485 ObtainReadLock(&afs_xinterface);
3487 /* copy out the client interface information from the
3488 ** kernel data structure "interface" to the output buffer
3490 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3491 && ( j< maxNumber) ; i++, j++, srvout++)
3492 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3494 spout->num_servers = j;
3495 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3497 if ( i >= afs_cb_interface.numberOfInterfaces )
3498 spout->next_offset = 0; /* start from beginning again */
3500 spout->next_offset = spin->offset + j;
3502 ReleaseReadLock(&afs_xinterface);
3507 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3510 struct vrequest *areq;
3513 afs_int32 *aoutSize;
3515 struct setspref *sin;
3518 AFS_STATCNT(PSetCPrefs);
3519 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3520 return EIO; /* Inappropriate ioctl for device */
3522 sin = (struct setspref *)ain;
3524 if ( ainSize < sizeof(struct setspref) )
3526 #if 0 /* num_servers is unsigned */
3527 if ( sin->num_servers < 0 )
3530 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3533 ObtainWriteLock(&afs_xinterface, 412);
3534 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3535 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3536 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3538 ReleaseWriteLock(&afs_xinterface);
3542 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3545 struct vrequest *areq;
3548 afs_int32 *aoutSize;
3549 struct AFS_UCRED *acred; {
3550 register afs_int32 code;
3551 register struct vcache *tvc;
3552 register struct dcache *tdc;
3553 struct VenusFid tfid;
3555 struct sysname_info sysState;
3556 afs_int32 offset, len;
3558 AFS_STATCNT(PFlushMount);
3559 if (!avc) return EINVAL;
3560 code = afs_VerifyVCache(avc, areq);
3561 if (code) return code;
3562 if (vType(avc) != VDIR) {
3565 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3566 if (!tdc) return ENOENT;
3567 Check_AtSys(avc, ain, &sysState, areq);
3569 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3570 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3571 bufp = sysState.name;
3576 tfid.Cell = avc->fid.Cell;
3577 tfid.Fid.Volume = avc->fid.Fid.Volume;
3578 afs_PutDCache(tdc); /* we're done with the data */
3579 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3580 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3582 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3589 if (vType(tvc) != VLNK) {
3590 afs_PutVCache(tvc, WRITE_LOCK);
3594 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3595 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3597 ObtainWriteLock(&tvc->lock,645);
3598 ObtainWriteLock(&afs_xcbhash, 646);
3599 afs_DequeueCallback(tvc);
3600 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3601 ReleaseWriteLock(&afs_xcbhash);
3602 /* now find the disk cache entries */
3603 afs_TryToSmush(tvc, acred, 1);
3604 osi_dnlc_purgedp(tvc);
3605 afs_symhint_inval(tvc);
3606 if (tvc->linkData && !(tvc->states & CCore)) {
3607 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3608 tvc->linkData = (char *) 0;
3610 ReleaseWriteLock(&tvc->lock);
3611 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3612 afs_BozonUnlock(&tvc->pvnLock, tvc);
3614 afs_PutVCache(tvc, WRITE_LOCK);
3616 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3620 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3623 struct vrequest *areq;
3626 afs_int32 *aoutSize;
3627 struct AFS_UCRED *acred;
3632 if (!afs_osi_suser(acred)) {
3636 if (ainSize != sizeof(afs_int32)) {
3640 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3641 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3645 if (flags & AFSCALL_RXSTATS_ENABLE) {
3646 rx_enableProcessRPCStats();
3648 if (flags & AFSCALL_RXSTATS_DISABLE) {
3649 rx_disableProcessRPCStats();
3651 if (flags & AFSCALL_RXSTATS_CLEAR) {
3652 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3660 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3663 struct vrequest *areq;
3666 afs_int32 *aoutSize;
3667 struct AFS_UCRED *acred;
3672 if (!afs_osi_suser(acred)) {
3676 if (ainSize != sizeof(afs_int32)) {
3680 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3681 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3685 if (flags & AFSCALL_RXSTATS_ENABLE) {
3686 rx_enablePeerRPCStats();
3688 if (flags & AFSCALL_RXSTATS_DISABLE) {
3689 rx_disablePeerRPCStats();
3691 if (flags & AFSCALL_RXSTATS_CLEAR) {
3692 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3699 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3702 struct vrequest *areq;
3705 afs_int32 *aoutSize; /* set this */
3707 register afs_int32 code, code1;
3710 struct rx_call *tcall;
3711 struct AFSVolSync tsync;
3712 struct AFSFetchStatus OutStatus;
3713 struct AFSCallBack CallBack;
3714 struct VenusFid tfid;
3719 AFS_STATCNT(PSetAcl);
3723 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3724 Fid = (struct AFSFid *) ain;
3726 Fid = &avc->fid.Fid;
3727 tfid.Cell = avc->fid.Cell;
3728 tfid.Fid.Volume = Fid->Volume;
3729 tfid.Fid.Vnode = Fid->Vnode;
3730 tfid.Fid.Unique = Fid->Unique;
3732 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3735 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3736 ICL_TYPE_POINTER, tvc,
3737 ICL_TYPE_FID, &tfid,
3738 ICL_TYPE_FID, &avc->fid);
3741 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3742 ICL_TYPE_POINTER, tvc,
3743 ICL_TYPE_FID, &tfid,
3744 ICL_TYPE_FID, &tvc->fid);
3747 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3750 #ifdef RX_ENABLE_LOCKS
3752 #endif /* RX_ENABLE_LOCKS */
3753 tcall = rx_NewCall(tc->id);
3754 code = StartRXAFS_FetchData(tcall,
3755 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3757 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3758 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3760 code1 = rx_EndCall(tcall, code);
3761 #ifdef RX_ENABLE_LOCKS
3763 #endif /* RX_ENABLE_LOCKS */
3767 (afs_Analyze(tc, code, &tvc->fid, areq,
3768 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3770 /* This call is done only to have the callback things handled correctly */
3771 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3772 afs_PutVCache(tvc, WRITE_LOCK);
3775 *aoutSize = sizeof(afs_int32);
3780 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3783 struct vrequest *areq;
3786 afs_int32 *aoutSize; /* set this */
3788 register afs_int32 code;
3791 struct ResidencyCmdInputs *Inputs;
3792 struct ResidencyCmdOutputs *Outputs;
3793 struct VenusFid tfid;
3796 Inputs = (struct ResidencyCmdInputs *) ain;
3797 Outputs = (struct ResidencyCmdOutputs *) aout;
3798 if (!avc) return EINVAL;
3799 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3803 Fid = &avc->fid.Fid;
3805 tfid.Cell = avc->fid.Cell;
3806 tfid.Fid.Volume = Fid->Volume;
3807 tfid.Fid.Vnode = Fid->Vnode;
3808 tfid.Fid.Unique = Fid->Unique;
3810 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3812 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3813 ICL_TYPE_POINTER, tvc,
3814 ICL_TYPE_INT32, Inputs->command,
3815 ICL_TYPE_FID, &tfid);
3819 if (Inputs->command) {
3821 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3823 #ifdef RX_ENABLE_LOCKS
3825 #endif /* RX_ENABLE_LOCKS */
3826 code = RXAFS_ResidencyCmd(tc->id, Fid,
3828 (struct ResidencyCmdOutputs *) aout);
3829 #ifdef RX_ENABLE_LOCKS
3831 #endif /* RX_ENABLE_LOCKS */
3835 (afs_Analyze(tc, code, &tvc->fid, areq,
3836 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3838 /* This call is done to have the callback things handled correctly */
3839 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3840 } else { /* just a status request, return also link data */
3842 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3843 Outputs->chars[0] = 0;
3844 if (vType(tvc) == VLNK) {
3845 ObtainWriteLock(&tvc->lock,555);
3846 if (afs_HandleLink(tvc, areq) == 0)
3847 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3848 ReleaseWriteLock(&tvc->lock);
3852 afs_PutVCache(tvc, WRITE_LOCK);
3855 *aoutSize = sizeof(struct ResidencyCmdOutputs);