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)
200 struct afs_ioctl32 dst32;
202 #ifdef AFS_SPARC64_LINUX20_ENV
203 if (current->tss.flags & SPARC_FLAG_32BIT) {
205 #error Not done for this linux type
207 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
209 afs_ioctl32_to_afs_ioctl(&dst32, dst);
212 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
214 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
218 HandleIoctl(avc, acom, adata)
219 register struct vcache *avc;
220 register afs_int32 acom;
221 struct afs_ioctl *adata; {
222 register afs_int32 code;
225 AFS_STATCNT(HandleIoctl);
227 switch(acom & 0xff) {
229 avc->states |= CSafeStore;
233 /* case 2 used to be abort store, but this is no longer provided,
234 since it is impossible to implement under normal Unix.
238 /* return the name of the cell this file is open on */
239 register struct cell *tcell;
240 register afs_int32 i;
242 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
244 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
246 if (i > adata->out_size) {
247 /* 0 means we're not interested in the output */
248 if (adata->out_size != 0) code = EFAULT;
252 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
254 afs_PutCell(tcell, READ_LOCK);
260 case 49: /* VIOC_GETINITPARAMS */
261 if (adata->out_size < sizeof(struct cm_initparams)) {
265 AFS_COPYOUT(&cm_initParams, adata->out,
266 sizeof(struct cm_initparams), code);
275 return code; /* so far, none implemented */
280 /* For aix we don't temporarily bypass ioctl(2) but rather do our
281 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
282 * is now called from afs_gn_ioctl.
284 afs_ioctl(tvc, cmd, arg)
289 struct afs_ioctl data;
292 AFS_STATCNT(afs_ioctl);
293 if (((cmd >> 8) & 0xff) == 'V') {
294 /* This is a VICEIOCTL call */
295 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
298 error = HandleIoctl(tvc, cmd, &data);
301 /* No-op call; just return. */
305 #endif /* AFS_AIX_ENV */
307 #if defined(AFS_SGI_ENV)
308 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
314 struct afs_ioctl data;
320 AFS_STATCNT(afs_ioctl);
321 if (((cmd >> 8) & 0xff) == 'V') {
322 /* This is a VICEIOCTL call */
323 error = copyin_afs_ioctl(arg, &data);
326 locked = ISAFS_GLOCK();
329 error = HandleIoctl(tvc, cmd, &data);
334 /* No-op call; just return. */
338 #endif /* AFS_SGI_ENV */
341 /* unlike most calls here, this one uses u.u_error to return error conditions,
342 since this is really an intercepted chapter 2 call, rather than a vnode
345 /* AFS_HPUX102 and up uses VNODE ioctl instead */
346 #ifndef AFS_HPUX102_ENV
347 #if !defined(AFS_SGI_ENV)
349 kioctl(fdes, com, arg, ext)
356 } u_uap, *uap = &u_uap;
360 struct afs_ioctl_sys {
366 afs_xioctl (uap, rvp)
367 struct afs_ioctl_sys *uap;
372 afs_xioctl (p, args, retval)
381 } *uap = (struct a *)args;
382 #else /* AFS_OSF_ENV */
383 #ifdef AFS_LINUX22_ENV
384 struct afs_ioctl_sys {
388 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
389 unsigned int com, unsigned long arg)
391 struct afs_ioctl_sys ua, *uap = &ua;
399 } *uap = (struct a *)u.u_ap;
400 #endif /* AFS_LINUX22_ENV */
401 #endif /* AFS_OSF_ENV */
402 #endif /* AFS_SUN5_ENV */
404 #ifndef AFS_LINUX22_ENV
405 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
408 register struct file *fd;
411 register struct vcache *tvc;
412 register int ioctlDone = 0, code = 0;
414 AFS_STATCNT(afs_xioctl);
415 #ifdef AFS_LINUX22_ENV
423 if (setuerror(getf(uap->fd, &fd))) {
429 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
431 #else /* AFS_OSF_ENV */
433 #if defined(AFS_SUN57_ENV)
435 if (!fd) return(EBADF);
436 #elif defined(AFS_SUN54_ENV)
438 if (!fd) return(EBADF);
440 if (code = getf(uap->fd, &fd)) {
452 /* first determine whether this is any sort of vnode */
453 #ifdef AFS_LINUX22_ENV
454 tvc = (struct vcache *)ip;
458 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
460 if (fd->f_type == DTYPE_VNODE) {
462 /* good, this is a vnode; next see if it is an AFS vnode */
463 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
464 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
466 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
468 #endif /* AFS_LINUX22_ENV */
469 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
471 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
472 if (!tvc) { /* shouldn't happen with held gnodes */
477 /* This is an AFS vnode */
478 if (((uap->com >> 8) & 0xff) == 'V') {
479 register struct afs_ioctl *datap;
481 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
482 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
484 osi_FreeSmallSpace(datap);
486 #if defined(AFS_SUN5_ENV)
501 #else /* AFS_OSF_ENV */
505 #ifdef AFS_LINUX22_ENV
514 code = HandleIoctl(tvc, uap->com, datap);
515 osi_FreeSmallSpace(datap);
529 #if defined(AFS_LINUX22_ENV)
539 code = okioctl(fdes, com, arg, ext);
543 okioctl(fdes, com, arg, ext);
545 #if defined(AFS_SUN5_ENV)
546 #if defined(AFS_SUN57_ENV)
548 #elif defined(AFS_SUN54_ENV)
553 code = ioctl(uap, rvp);
556 code = ioctl(p, args, retval);
563 #else /* AFS_OSF_ENV */
564 #ifndef AFS_LINUX22_ENV
581 #ifdef AFS_LINUX22_ENV
584 #if !defined(AFS_OSF_ENV)
587 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
588 return (getuerror() ? -1 : u.u_ioctlrv);
590 return getuerror() ? -1 : 0;
593 #endif /* AFS_LINUX22_ENV */
594 #endif /* AFS_SUN5_ENV */
599 #endif /* AFS_SGI_ENV */
600 #endif /* AFS_HPUX102_ENV */
602 #if defined(AFS_SGI_ENV)
603 /* "pioctl" system call entry point; just pass argument to the parameterized
612 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
616 AFS_STATCNT(afs_pioctl);
618 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
626 #endif /* AFS_SGI_ENV */
629 afs_pioctl(p, args, retval)
639 } *uap = (struct a *) args;
641 AFS_STATCNT(afs_pioctl);
642 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
645 extern struct mount *afs_globalVFS;
646 #else /* AFS_OSF_ENV */
647 extern struct vfs *afs_globalVFS;
650 /* macro to avoid adding any more #ifdef's to pioctl code. */
651 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
652 #define PIOCTL_FREE_CRED() crfree(credp)
654 #define PIOCTL_FREE_CRED()
658 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
660 struct AFS_UCRED *credp;
662 afs_syscall_pioctl(path, com, cmarg, follow)
669 struct afs_ioctl data;
670 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
671 register afs_int32 code = 0;
677 struct ucred *credp = crref(); /* don't free until done! */
679 #ifdef AFS_LINUX22_ENV
680 cred_t *credp = crref(); /* don't free until done! */
683 AFS_STATCNT(afs_syscall_pioctl);
684 if (follow) follow = 1; /* compat. with old venus */
686 if (! _VALIDVICEIOCTL(com)) {
690 #else /* AFS_OSF_ENV */
691 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
700 code = copyin_afs_ioctl(cmarg, &data);
703 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
710 if ((com & 0xff) == PSetClientContext) {
711 #ifdef AFS_LINUX22_ENV
712 return EINVAL; /* Not handling these yet. */
714 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
715 code = HandleClientContext(&data, &com, &foreigncreds, credp);
717 #if defined(AFS_HPUX101_ENV)
718 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
721 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
723 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
724 #endif /* AFS_SGI_ENV */
729 crfree(foreigncreds);
732 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
735 return (setuerror(code), code);
739 #ifndef AFS_LINUX22_ENV
742 * We could have done without temporary setting the u.u_cred below
743 * (foreigncreds could be passed as param the pioctl modules)
744 * but calls such as afs_osi_suser() doesn't allow that since it
745 * references u.u_cred directly. We could, of course, do something
746 * like afs_osi_suser(cred) which, I think, is better since it
747 * generalizes and supports multi cred environments...
751 credp = foreigncreds;
754 tmpcred = crref(); /* XXX */
757 #if defined(AFS_HPUX101_ENV)
758 tmpcred = p_cred(u.u_procp);
759 set_p_cred(u.u_procp, foreigncreds);
762 tmpcred = OSI_GET_CURRENT_CRED();
763 OSI_SET_CURRENT_CRED(foreigncreds);
766 u.u_cred = foreigncreds;
767 #endif /* AFS_SGI64_ENV */
768 #endif /* AFS_HPUX101_ENV */
773 if ((com & 0xff) == 15) {
774 /* special case prefetch so entire pathname eval occurs in helper process.
775 otherwise, the pioctl call is essentially useless */
776 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
777 code = Prefetch(path, &data, follow,
778 foreigncreds ? foreigncreds : credp);
780 #if defined(AFS_HPUX101_ENV)
781 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
784 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
786 code = Prefetch(path, &data, follow, u.u_cred);
787 #endif /* AFS_SGI64_ENV */
788 #endif /* AFS_HPUX101_ENV */
790 #ifndef AFS_LINUX22_ENV
793 crset(tmpcred); /* restore original credentials */
795 #if defined(AFS_HPUX101_ENV)
796 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
800 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
802 u.u_cred = tmpcred; /* restore original credentials */
805 #endif /* AFS_HPUX101_ENV */
806 crfree(foreigncreds);
809 #endif /* AFS_LINUX22_ENV */
811 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
814 return (setuerror(code), code);
820 code = lookupname(path, USR, follow, NULL, &vp,
821 foreigncreds ? foreigncreds : credp);
823 #ifdef AFS_LINUX22_ENV
824 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
826 vp = (struct vnode *)dp->d_inode;
828 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
829 #endif /* AFS_LINUX22_ENV */
830 #endif /* AFS_AIX41_ENV */
833 #ifndef AFS_LINUX22_ENV
836 crset(tmpcred); /* restore original credentials */
838 #if defined(AFS_HPUX101_ENV)
839 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
841 #if !defined(AFS_SUN5_ENV)
843 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
845 u.u_cred = tmpcred; /* restore original credentials */
846 #endif /* AFS_SGI64_ENV */
848 #endif /* AFS_HPUX101_ENV */
849 crfree(foreigncreds);
852 #endif /* AFS_LINUX22_ENV */
854 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
857 return(setuerror(code), code);
861 else vp = (struct vnode *) 0;
863 /* now make the call if we were passed no file, or were passed an AFS file */
864 if (!vp || IsAfsVnode(vp)) {
866 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
867 * So, we must test in this part of the code. Also, must arrange to
868 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
869 * we hold gnodes, whose references hold our vcache entries.
872 gp = vp; /* remember for "put" */
873 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
875 else gp = (struct vnode *) 0;
878 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
882 struct ucred *cred1, *cred2;
885 cred1 = cred2 = foreigncreds;
887 cred1 = cred2 = credp;
889 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
890 if (cred1 != cred2) {
891 /* something changed the creds */
896 #if defined(AFS_HPUX101_ENV)
898 struct ucred *cred = p_cred(u.u_procp);
899 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
905 credp = OSI_GET_CURRENT_CRED();
906 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
909 #ifdef AFS_LINUX22_ENV
910 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
912 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
914 #endif /* AFS_SGI_ENV */
915 #endif /* AFS_HPUX101_ENV */
916 #endif /* AFS_AIX41_ENV */
917 #endif /* AFS_SUN5_ENV */
919 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
920 code = EINVAL; /* not in /afs */
927 vp = (struct vnode *) 0;
932 #ifndef AFS_LINUX22_ENV
937 #if defined(AFS_HPUX101_ENV)
938 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
942 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
944 u.u_cred = tmpcred; /* restore original credentials */
945 #endif /* ASF_SGI64_ENV */
947 #endif /* AFS_HPUX101_ENV */
948 crfree(foreigncreds);
951 #endif /* AFS_LINUX22_ENV */
953 #ifdef AFS_LINUX22_ENV
956 AFS_RELE(vp); /* put vnode back */
960 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
965 return (getuerror());
970 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
971 register struct vcache *avc;
973 struct AFS_UCRED **acred;
974 register struct afs_ioctl *ablob;
977 struct vrequest treq;
978 register afs_int32 code;
979 register afs_int32 function;
980 afs_int32 inSize, outSize;
981 char *inData, *outData;
983 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
984 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
985 AFS_STATCNT(HandlePioctl);
986 if (code = afs_InitReq(&treq, *acred)) return code;
987 function = acom & 0xff;
988 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
989 return EINVAL; /* out of range */
991 inSize = ablob->in_size;
992 if (inSize >= PIGGYSIZE) return E2BIG;
993 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
995 AFS_COPYIN(ablob->in, inData, inSize, code);
999 osi_FreeLargeSpace(inData);
1002 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1004 if (function == 3) /* PSetTokens */
1005 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1007 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1008 osi_FreeLargeSpace(inData);
1009 if (code == 0 && ablob->out_size > 0) {
1010 if (outSize > ablob->out_size) outSize = ablob->out_size;
1011 if (outSize >= PIGGYSIZE) code = E2BIG;
1013 AFS_COPYOUT(outData, ablob->out, outSize, code);
1015 osi_FreeLargeSpace(outData);
1016 return afs_CheckCode(code, &treq, 41);
1019 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1022 struct vrequest *areq;
1025 afs_int32 *aoutSize; /* set this */ {
1026 register afs_int32 code;
1028 AFS_STATCNT(PGetFID);
1029 if (!avc) return EINVAL;
1030 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1031 *aoutSize = sizeof(struct VenusFid);
1035 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1038 struct vrequest *areq;
1041 afs_int32 *aoutSize; /* set this */ {
1042 register afs_int32 code;
1044 struct AFSOpaque acl;
1045 struct AFSVolSync tsync;
1046 struct AFSFetchStatus OutStatus;
1049 AFS_STATCNT(PSetAcl);
1052 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1055 acl.AFSOpaque_val = ain;
1057 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1059 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1060 #ifdef RX_ENABLE_LOCKS
1062 #endif /* RX_ENABLE_LOCKS */
1063 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1064 &acl, &OutStatus, &tsync);
1065 #ifdef RX_ENABLE_LOCKS
1067 #endif /* RX_ENABLE_LOCKS */
1072 (afs_Analyze(tconn, code, &avc->fid, areq,
1073 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1075 /* now we've forgotten all of the access info */
1076 ObtainWriteLock(&afs_xcbhash, 455);
1078 afs_DequeueCallback(avc);
1079 avc->states &= ~(CStatd | CUnique);
1080 ReleaseWriteLock(&afs_xcbhash);
1081 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1082 osi_dnlc_purgedp(avc);
1086 int afs_defaultAsynchrony = 0;
1088 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1091 struct vrequest *areq;
1094 afs_int32 *aoutSize; /* set this */
1095 struct AFS_UCRED *acred;
1098 struct sbstruct *sbr;
1100 sbr = (struct sbstruct *)ain;
1101 if (sbr->sb_default != -1) {
1102 if (afs_osi_suser(acred))
1103 afs_defaultAsynchrony = sbr->sb_default;
1107 if (avc && (sbr->sb_thisfile != -1))
1108 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1109 areq, DONT_CHECK_MODE_BITS))
1110 avc->asynchrony = sbr->sb_thisfile;
1113 *aoutSize = sizeof(struct sbstruct);
1114 sbr = (struct sbstruct *)aout;
1115 sbr->sb_default = afs_defaultAsynchrony;
1117 sbr->sb_thisfile = avc->asynchrony;
1123 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1126 struct vrequest *areq;
1129 afs_int32 *aoutSize; /* set this */
1130 struct AFS_UCRED *acred;
1132 if (!afs_osi_suser(acred)) {
1135 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1139 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1142 struct vrequest *areq;
1145 afs_int32 *aoutSize; /* set this */ {
1146 struct AFSOpaque acl;
1147 struct AFSVolSync tsync;
1148 struct AFSFetchStatus OutStatus;
1154 AFS_STATCNT(PGetAcl);
1155 if (!avc) return EINVAL;
1156 Fid.Volume = avc->fid.Fid.Volume;
1157 Fid.Vnode = avc->fid.Fid.Vnode;
1158 Fid.Unique = avc->fid.Fid.Unique;
1159 if (avc->states & CForeign) {
1161 * For a dfs xlator acl we have a special hack so that the
1162 * xlator will distinguish which type of acl will return. So
1163 * we currently use the top 2-bytes (vals 0-4) to tell which
1164 * type of acl to bring back. Horrible hack but this will
1165 * cause the least number of changes to code size and interfaces.
1167 if (Fid.Vnode & 0xc0000000)
1169 Fid.Vnode |= (ainSize << 30);
1171 acl.AFSOpaque_val = aout;
1173 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1176 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1177 #ifdef RX_ENABLE_LOCKS
1179 #endif /* RX_ENABLE_LOCKS */
1180 code = RXAFS_FetchACL(tconn->id, &Fid,
1181 &acl, &OutStatus, &tsync);
1182 #ifdef RX_ENABLE_LOCKS
1184 #endif /* RX_ENABLE_LOCKS */
1189 (afs_Analyze(tconn, code, &avc->fid, areq,
1190 AFS_STATS_FS_RPCIDX_FETCHACL,
1191 SHARED_LOCK, (struct cell *)0));
1194 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1205 AFS_STATCNT(PBogus);
1209 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1212 struct vrequest *areq;
1216 afs_int32 *aoutSize; /* set this */ {
1217 register struct cell *tcell;
1219 AFS_STATCNT(PGetFileCell);
1220 if (!avc) return EINVAL;
1221 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1222 if (!tcell) return ESRCH;
1223 strcpy(aout, tcell->cellName);
1224 afs_PutCell(tcell, READ_LOCK);
1225 *aoutSize = strlen(aout) + 1;
1229 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1232 struct vrequest *areq;
1236 afs_int32 *aoutSize; /* set this */ {
1237 register struct cell *tcell=0, *cellOne=0;
1238 register struct afs_q *cq, *tq;
1240 AFS_STATCNT(PGetWSCell);
1241 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1242 return EIO; /* Inappropriate ioctl for device */
1244 ObtainReadLock(&afs_xcell);
1245 cellOne = (struct cell *) 0;
1247 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1248 tcell = QTOC(cq); tq = QNext(cq);
1249 if (tcell->states & CPrimary) break;
1250 if (tcell->cell == 1) cellOne = tcell;
1253 ReleaseReadLock(&afs_xcell);
1254 if (!tcell) { /* no primary cell, use cell #1 */
1255 if (!cellOne) return ESRCH;
1258 strcpy(aout, tcell->cellName);
1259 *aoutSize = strlen(aout) + 1;
1263 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1266 struct vrequest *areq;
1270 afs_int32 *aoutSize; /* set this */ {
1271 register afs_int32 i;
1272 register struct unixuser *tu;
1273 register struct cell *tcell;
1275 AFS_STATCNT(PGetUserCell);
1276 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1277 return EIO; /* Inappropriate ioctl for device */
1279 /* return the cell name of the primary cell for this user */
1280 i = UHash(areq->uid);
1281 ObtainWriteLock(&afs_xuser,224);
1282 for(tu = afs_users[i]; tu; tu = tu->next) {
1283 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1285 ReleaseWriteLock(&afs_xuser);
1290 tcell = afs_GetCell(tu->cell, READ_LOCK);
1291 afs_PutUser(tu, WRITE_LOCK);
1292 if (!tcell) return ESRCH;
1294 strcpy(aout, tcell->cellName);
1295 afs_PutCell(tcell, READ_LOCK);
1296 *aoutSize = strlen(aout)+1; /* 1 for the null */
1300 ReleaseWriteLock(&afs_xuser);
1307 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1310 struct vrequest *areq;
1314 afs_int32 *aoutSize; /* set this */
1315 struct AFS_UCRED **acred;
1318 register struct unixuser *tu;
1319 struct ClearToken clear;
1320 register struct cell *tcell;
1323 struct vrequest treq;
1324 afs_int32 flag, set_parent_pag = 0;
1326 AFS_STATCNT(PSetTokens);
1327 if (!afs_resourceinit_flag) {
1330 bcopy(ain, (char *)&i, sizeof(afs_int32));
1331 ain += sizeof(afs_int32);
1332 stp = ain; /* remember where the ticket is */
1333 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1335 ain += i; /* skip over ticket */
1336 bcopy(ain, (char *)&i, sizeof(afs_int32));
1337 ain += sizeof(afs_int32);
1338 if (i != sizeof(struct ClearToken)) {
1341 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1342 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1343 ain += sizeof(struct ClearToken);
1344 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1345 /* still stuff left? we've got primary flag and cell name. Set these */
1346 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1347 ain += sizeof(afs_int32); /* skip id field */
1348 /* rest is cell name, look it up */
1349 if (flag & 0x8000) { /* XXX Use Constant XXX */
1353 tcell = afs_GetCellByName(ain, READ_LOCK);
1362 /* default to cell 1, primary id */
1363 flag = 1; /* primary id */
1364 i = 1; /* cell number */
1365 tcell = afs_GetCell(1, READ_LOCK);
1366 if (!tcell) goto nocell;
1368 afs_PutCell(tcell, READ_LOCK);
1369 if (set_parent_pag) {
1372 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1374 if (!setpag(acred, -1, &pag, 1)) {
1376 afs_InitReq(&treq, *acred);
1380 /* now we just set the tokens */
1381 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1382 tu->vid = clear.ViceId;
1383 if (tu->stp != (char *) 0) {
1384 afs_osi_Free(tu->stp, tu->stLen);
1386 tu->stp = (char *) afs_osi_Alloc(stLen);
1388 bcopy(stp, tu->stp, stLen);
1391 afs_stats_cmfullperf.authent.TicketUpdates++;
1392 afs_ComputePAGStats();
1393 #endif /* AFS_NOSTATS */
1394 tu->states |= UHasTokens;
1395 tu->states &= ~UTokensBad;
1396 afs_SetPrimary(tu, flag);
1397 tu->tokenTime =osi_Time();
1398 afs_ResetUserConns(tu);
1399 afs_PutUser(tu, WRITE_LOCK);
1414 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1417 struct vrequest *areq;
1420 afs_int32 *aoutSize; /* set this */ {
1422 char offLineMsg[256];
1424 register struct conn *tc;
1425 register afs_int32 code;
1426 struct VolumeStatus volstat;
1428 char *Name, *OfflineMsg, *MOTD;
1431 AFS_STATCNT(PGetVolumeStatus);
1432 if (!avc) return EINVAL;
1434 OfflineMsg = offLineMsg;
1437 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1439 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1440 #ifdef RX_ENABLE_LOCKS
1442 #endif /* RX_ENABLE_LOCKS */
1443 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1444 &Name, &OfflineMsg, &MOTD);
1445 #ifdef RX_ENABLE_LOCKS
1447 #endif /* RX_ENABLE_LOCKS */
1452 (afs_Analyze(tc, code, &avc->fid, areq,
1453 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1454 SHARED_LOCK, (struct cell *)0));
1456 if (code) return code;
1457 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1459 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1460 cp += sizeof(VolumeStatus);
1461 strcpy(cp, volName);
1462 cp += strlen(volName)+1;
1463 strcpy(cp, offLineMsg);
1464 cp += strlen(offLineMsg)+1;
1466 cp += strlen(motd)+1;
1467 *aoutSize = (cp - aout);
1471 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1474 struct vrequest *areq;
1477 afs_int32 *aoutSize; /* set this */ {
1479 char offLineMsg[256];
1481 register struct conn *tc;
1482 register afs_int32 code;
1483 struct AFSFetchVolumeStatus volstat;
1484 struct AFSStoreVolumeStatus storeStat;
1485 register struct volume *tvp;
1489 AFS_STATCNT(PSetVolumeStatus);
1490 if (!avc) return EINVAL;
1492 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1494 if (tvp->states & (VRO | VBackup)) {
1495 afs_PutVolume(tvp, READ_LOCK);
1498 afs_PutVolume(tvp, READ_LOCK);
1501 /* Copy the junk out, using cp as a roving pointer. */
1503 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1504 cp += sizeof(AFSFetchVolumeStatus);
1505 if (strlen(cp) >= sizeof(volName))
1507 strcpy(volName, cp);
1508 cp += strlen(volName)+1;
1509 if (strlen(cp) >= sizeof(offLineMsg))
1511 strcpy(offLineMsg, cp);
1512 cp += strlen(offLineMsg)+1;
1513 if (strlen(cp) >= sizeof(motd))
1517 if (volstat.MinQuota != -1) {
1518 storeStat.MinQuota = volstat.MinQuota;
1519 storeStat.Mask |= AFS_SETMINQUOTA;
1521 if (volstat.MaxQuota != -1) {
1522 storeStat.MaxQuota = volstat.MaxQuota;
1523 storeStat.Mask |= AFS_SETMAXQUOTA;
1526 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1528 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1529 #ifdef RX_ENABLE_LOCKS
1531 #endif /* RX_ENABLE_LOCKS */
1532 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1533 &storeStat, volName, offLineMsg, motd);
1534 #ifdef RX_ENABLE_LOCKS
1536 #endif /* RX_ENABLE_LOCKS */
1541 (afs_Analyze(tc, code, &avc->fid, areq,
1542 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1543 SHARED_LOCK, (struct cell *)0));
1545 if (code) return code;
1546 /* we are sending parms back to make compat. with prev system. should
1547 change interface later to not ask for current status, just set new status */
1549 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1550 cp += sizeof(VolumeStatus);
1551 strcpy(cp, volName);
1552 cp += strlen(volName)+1;
1553 strcpy(cp, offLineMsg);
1554 cp += strlen(offLineMsg)+1;
1556 cp += strlen(motd)+1;
1557 *aoutSize = cp - aout;
1561 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1562 register struct vcache *avc;
1564 struct vrequest *areq;
1567 afs_int32 *aoutSize; /* set this */
1568 struct AFS_UCRED *acred;
1571 AFS_STATCNT(PFlush);
1572 if (!avc) return EINVAL;
1573 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1574 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1576 ObtainWriteLock(&avc->lock,225);
1577 ObtainWriteLock(&afs_xcbhash, 456);
1578 afs_DequeueCallback(avc);
1579 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1580 ReleaseWriteLock(&afs_xcbhash);
1581 /* now find the disk cache entries */
1582 afs_TryToSmush(avc, acred, 1);
1583 osi_dnlc_purgedp(avc);
1584 afs_symhint_inval(avc);
1585 if (avc->linkData && !(avc->states & CCore)) {
1586 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1587 avc->linkData = (char *) 0;
1589 ReleaseWriteLock(&avc->lock);
1590 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1591 afs_BozonUnlock(&avc->pvnLock, avc);
1596 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1599 struct vrequest *areq;
1602 afs_int32 *aoutSize; /* set this */ {
1603 register afs_int32 code;
1604 register struct vcache *tvc;
1605 register struct dcache *tdc;
1606 struct VenusFid tfid;
1608 afs_int32 offset, len, hasatsys=0;
1610 AFS_STATCNT(PNewStatMount);
1611 if (!avc) return EINVAL;
1612 code = afs_VerifyVCache(avc, areq);
1613 if (code) return code;
1614 if (vType(avc) != VDIR) {
1617 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1618 if (!tdc) return ENOENT;
1619 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1620 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1625 tfid.Cell = avc->fid.Cell;
1626 tfid.Fid.Volume = avc->fid.Fid.Volume;
1627 afs_PutDCache(tdc); /* we're done with the data */
1628 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1629 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1631 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1638 if (vType(tvc) != VLNK) {
1639 afs_PutVCache(tvc, WRITE_LOCK);
1643 ObtainWriteLock(&tvc->lock,226);
1644 code = afs_HandleLink(tvc, areq);
1646 if (tvc->linkData) {
1647 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1650 /* we have the data */
1651 strcpy(aout, tvc->linkData);
1652 *aoutSize = strlen(tvc->linkData)+1;
1657 ReleaseWriteLock(&tvc->lock);
1658 afs_PutVCache(tvc, WRITE_LOCK);
1660 if (hasatsys) osi_FreeLargeSpace(bufp);
1664 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1667 struct vrequest *areq;
1670 afs_int32 *aoutSize; /* set this */ {
1671 register struct cell *tcell;
1672 register afs_int32 i;
1673 register struct unixuser *tu;
1678 AFS_STATCNT(PGetTokens);
1679 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1680 return EIO; /* Inappropriate ioctl for device */
1682 /* weird interface. If input parameter is present, it is an integer and
1683 we're supposed to return the parm'th tokens for this unix uid.
1684 If not present, we just return tokens for cell 1.
1685 If counter out of bounds, return EDOM.
1686 If no tokens for the particular cell, return ENOTCONN.
1687 Also, if this mysterious parm is present, we return, along with the
1688 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1689 at the end, in that order.
1691 if (newStyle = (ainSize > 0)) {
1692 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1694 i = UHash(areq->uid);
1695 ObtainReadLock(&afs_xuser);
1696 for(tu = afs_users[i]; tu; tu=tu->next) {
1698 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1699 if (iterator-- == 0) break; /* are we done yet? */
1703 if (tu->uid == areq->uid && tu->cell == 1) break;
1708 * No need to hold a read lock on each user entry
1712 ReleaseReadLock(&afs_xuser);
1717 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1718 tu->states |= (UTokensBad | UNeedsReset);
1719 afs_PutUser(tu, READ_LOCK);
1722 /* use iterator for temp */
1724 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1725 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1726 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1727 cp += sizeof(afs_int32);
1728 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1730 iterator = sizeof(struct ClearToken);
1731 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1732 cp += sizeof(afs_int32);
1733 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1734 cp += sizeof(struct ClearToken);
1736 /* put out primary id and cell name, too */
1737 iterator = (tu->states & UPrimary ? 1 : 0);
1738 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1739 cp += sizeof(afs_int32);
1740 tcell = afs_GetCell(tu->cell, READ_LOCK);
1742 strcpy(cp, tcell->cellName);
1743 cp += strlen(tcell->cellName)+1;
1744 afs_PutCell(tcell, READ_LOCK);
1748 *aoutSize = cp - aout;
1749 afs_PutUser(tu, READ_LOCK);
1753 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1756 struct vrequest *areq;
1759 afs_int32 *aoutSize; /* set this */ {
1760 register afs_int32 i;
1761 register struct unixuser *tu;
1763 AFS_STATCNT(PUnlog);
1764 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1765 return EIO; /* Inappropriate ioctl for device */
1767 i = UHash(areq->uid);
1768 ObtainWriteLock(&afs_xuser,227);
1769 for(tu=afs_users[i]; tu; tu=tu->next) {
1770 if (tu->uid == areq->uid) {
1772 tu->states &= ~UHasTokens;
1773 /* security is not having to say you're sorry */
1774 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1776 ReleaseWriteLock(&afs_xuser);
1777 /* We have to drop the lock over the call to afs_ResetUserConns, since
1778 * it obtains the afs_xvcache lock. We could also keep the lock, and
1779 * modify ResetUserConns to take parm saying we obtained the lock
1780 * already, but that is overkill. By keeping the "tu" pointer
1781 * held over the released lock, we guarantee that we won't lose our
1782 * place, and that we'll pass over every user conn that existed when
1783 * we began this call.
1785 afs_ResetUserConns(tu);
1787 ObtainWriteLock(&afs_xuser,228);
1790 ReleaseWriteLock(&afs_xuser);
1794 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1797 struct vrequest *areq;
1800 afs_int32 *aoutSize; /* set this */ {
1801 afs_int32 newHostAddr;
1802 afs_int32 oldHostAddr;
1804 AFS_STATCNT(PMariner);
1806 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1808 oldHostAddr = 0xffffffff; /* disabled */
1810 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1811 if (newHostAddr == 0xffffffff) {
1812 /* disable mariner operations */
1815 else if (newHostAddr) {
1817 afs_marinerHost = newHostAddr;
1819 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1820 *aoutSize = sizeof(afs_int32);
1824 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1827 struct vrequest *areq;
1830 afs_int32 *aoutSize; /* set this */
1831 struct AFS_UCRED *acred;
1833 register char *cp = 0;
1835 register struct server *ts;
1836 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1838 struct chservinfo *pcheck;
1840 AFS_STATCNT(PCheckServers);
1842 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1843 return EIO; /* Inappropriate ioctl for device */
1845 if (*lp == 0x12345678) { /* For afs3.3 version */
1846 pcheck=(struct chservinfo *)ain;
1847 if (pcheck->tinterval >= 0) {
1849 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1850 *aoutSize = sizeof(afs_int32);
1851 if (pcheck->tinterval > 0) {
1852 if (!afs_osi_suser(acred))
1854 PROBE_INTERVAL=pcheck->tinterval;
1860 temp=pcheck->tflags;
1861 cp = pcheck->tbuffer;
1862 } else { /* For pre afs3.3 versions */
1863 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1864 cp = ain+sizeof(afs_int32);
1865 if (ainSize > sizeof(afs_int32))
1870 * 1: fast check, don't contact servers.
1871 * 2: local cell only.
1874 /* have cell name, too */
1875 cellp = afs_GetCellByName(cp, READ_LOCK);
1876 if (!cellp) return ENOENT;
1878 else cellp = (struct cell *) 0;
1879 if (!cellp && (temp & 2)) {
1880 /* use local cell */
1881 cellp = afs_GetCell(1, READ_LOCK);
1883 if (!(temp & 1)) { /* if not fast, call server checker routine */
1884 afs_CheckServers(1, cellp); /* check down servers */
1885 afs_CheckServers(0, cellp); /* check up servers */
1887 /* now return the current down server list */
1889 ObtainReadLock(&afs_xserver);
1890 for(i=0;i<NSERVERS;i++) {
1891 for(ts = afs_servers[i]; ts; ts=ts->next) {
1892 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1893 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1894 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1895 cp += sizeof(afs_int32);
1899 ReleaseReadLock(&afs_xserver);
1900 if (cellp) afs_PutCell(cellp, READ_LOCK);
1901 *aoutSize = cp - aout;
1905 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1908 struct vrequest *areq;
1911 afs_int32 *aoutSize; /* set this */ {
1912 AFS_STATCNT(PCheckVolNames);
1913 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1914 return EIO; /* Inappropriate ioctl for device */
1916 afs_CheckRootVolume();
1917 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1918 AFS_VOLCHECK_EXPIRED |
1920 AFS_VOLCHECK_MTPTS);
1924 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1927 struct vrequest *areq;
1930 afs_int32 *aoutSize; /* set this */ {
1934 struct unixuser *tu;
1936 extern afs_rwlock_t afs_xsrvAddr;
1938 AFS_STATCNT(PCheckAuth);
1939 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1940 return EIO; /* Inappropriate ioctl for device */
1943 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1944 if (!tu) retValue = EACCES;
1946 /* we have a user */
1947 ObtainReadLock(&afs_xsrvAddr);
1948 ObtainReadLock(&afs_xconn);
1950 /* any tokens set? */
1951 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1952 /* all connections in cell 1 working? */
1953 for(i=0;i<NSERVERS;i++) {
1954 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1955 for (tc = sa->conns; tc; tc=tc->next) {
1956 if (tc->user == tu && (tu->states & UTokensBad))
1961 ReleaseReadLock(&afs_xsrvAddr);
1962 ReleaseReadLock(&afs_xconn);
1963 afs_PutUser(tu, READ_LOCK);
1965 bcopy((char *)&retValue, aout, sizeof(afs_int32));
1966 *aoutSize = sizeof(afs_int32);
1970 static Prefetch(apath, adata, afollow, acred)
1972 struct afs_ioctl *adata;
1974 struct AFS_UCRED *acred;
1977 register afs_int32 code;
1980 AFS_STATCNT(Prefetch);
1981 if (!apath) return EINVAL;
1982 tp = osi_AllocLargeSpace(1024);
1983 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1985 osi_FreeLargeSpace(tp);
1988 if (afs_BBusy()) { /* do this as late as possible */
1989 osi_FreeLargeSpace(tp);
1990 return EWOULDBLOCK; /* pretty close */
1992 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
1996 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
1999 struct vrequest *areq;
2002 afs_int32 *aoutSize; /* set this */ {
2003 register struct volume *tvp;
2004 register struct server *ts;
2005 register afs_int32 i;
2008 AFS_STATCNT(PFindVolume);
2009 if (!avc) return EINVAL;
2010 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2013 for(i=0;i<MAXHOSTS;i++) {
2014 ts = tvp->serverHost[i];
2016 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2017 cp += sizeof(afs_int32);
2020 /* still room for terminating NULL, add it on */
2021 ainSize = 0; /* reuse vbl */
2022 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2023 cp += sizeof(afs_int32);
2025 *aoutSize = cp - aout;
2026 afs_PutVolume(tvp, READ_LOCK);
2032 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2035 struct vrequest *areq;
2038 afs_int32 *aoutSize; /* set this */ {
2039 register afs_int32 code;
2042 AFS_STATCNT(PViceAccess);
2043 if (!avc) return EINVAL;
2044 code = afs_VerifyVCache(avc, areq);
2045 if (code) return code;
2046 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2047 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2052 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2055 struct vrequest *areq;
2058 afs_int32 *aoutSize; /* set this */
2059 struct AFS_UCRED *acred;
2064 AFS_STATCNT(PSetCacheSize);
2065 if (!afs_osi_suser(acred))
2067 /* too many things are setup initially in mem cache version */
2068 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2069 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2070 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2072 extern u_int afs_min_cache;
2073 if (newValue < afs_min_cache)
2074 afs_cacheBlocks = afs_min_cache;
2076 afs_cacheBlocks = newValue;
2078 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2079 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2080 afs_MaybeWakeupTruncateDaemon();
2081 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2082 afs_osi_Wait(1000, 0, 0);
2083 afs_MaybeWakeupTruncateDaemon();
2088 #define MAXGCSTATS 16
2089 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2092 struct vrequest *areq;
2095 afs_int32 *aoutSize; /* set this */ {
2096 afs_int32 results[MAXGCSTATS];
2098 AFS_STATCNT(PGetCacheSize);
2099 bzero((char *)results, sizeof(results));
2100 results[0] = afs_cacheBlocks;
2101 results[1] = afs_blocksUsed;
2102 bcopy((char *)results, aout, sizeof(results));
2103 *aoutSize = sizeof(results);
2107 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2110 struct vrequest *areq;
2113 afs_int32 *aoutSize; /* set this */ {
2114 register struct conn *tc;
2115 register afs_int32 code;
2116 struct AFSCallBack CallBacks_Array[1];
2117 struct AFSCBFids theFids;
2118 struct AFSCBs theCBs;
2121 AFS_STATCNT(PRemoveCallBack);
2122 if (!avc) return EINVAL;
2123 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2124 ObtainWriteLock(&avc->lock,229);
2125 theFids.AFSCBFids_len = 1;
2126 theCBs.AFSCBs_len = 1;
2127 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2128 theCBs.AFSCBs_val = CallBacks_Array;
2129 CallBacks_Array[0].CallBackType = CB_DROPPED;
2130 if (avc->callback) {
2132 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2134 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2135 #ifdef RX_ENABLE_LOCKS
2137 #endif /* RX_ENABLE_LOCKS */
2138 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2139 #ifdef RX_ENABLE_LOCKS
2141 #endif /* RX_ENABLE_LOCKS */
2144 /* don't set code on failure since we wouldn't use it */
2146 (afs_Analyze(tc, code, &avc->fid, areq,
2147 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2148 SHARED_LOCK, (struct cell *)0));
2150 ObtainWriteLock(&afs_xcbhash, 457);
2151 afs_DequeueCallback(avc);
2153 avc->states &= ~(CStatd | CUnique);
2154 ReleaseWriteLock(&afs_xcbhash);
2155 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2156 osi_dnlc_purgedp(avc);
2158 ReleaseWriteLock(&avc->lock);
2162 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2165 struct vrequest *areq;
2169 struct AFS_UCRED *acred;
2170 afs_int32 *aoutSize; /* set this */ {
2171 /* create a new cell */
2172 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2173 register struct cell *tcell;
2174 char *newcell=0, *linkedcell=0, *tp= ain;
2175 register afs_int32 code, linkedstate=0, ls;
2176 u_short fsport = 0, vlport = 0;
2179 AFS_STATCNT(PNewCell);
2180 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2181 return EIO; /* Inappropriate ioctl for device */
2183 if (!afs_osi_suser(acred))
2186 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2187 tp += sizeof(afs_int32);
2188 if (magic != 0x12345678)
2191 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2192 * server addresses while the 3.5 fs newcell command passes
2193 * MAXHOSTS. To figure out which is which, check if the cellname
2196 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2197 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2199 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2200 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2201 tp += (scount * sizeof(afs_int32));
2203 lp = (afs_int32 *)tp;
2206 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2207 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2208 tp += (3 * sizeof(afs_int32));
2210 if ((ls = *lp) & 1) {
2211 linkedcell = tp + strlen(newcell)+1;
2212 linkedstate |= CLinkedCell;
2215 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2216 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport);
2220 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2223 struct vrequest *areq;
2226 afs_int32 *aoutSize; /* set this */ {
2227 afs_int32 whichCell;
2228 register struct cell *tcell=0;
2229 register afs_int32 i;
2230 register char *cp, *tp = ain;
2231 register struct afs_q *cq, *tq;
2233 AFS_STATCNT(PListCells);
2234 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2235 return EIO; /* Inappropriate ioctl for device */
2237 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2238 tp += sizeof(afs_int32);
2239 ObtainReadLock(&afs_xcell);
2240 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2241 tcell = QTOC(cq); tq = QNext(cq);
2242 if (whichCell == 0) break;
2243 if (tq == &CellLRU) tcell = 0;
2248 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2249 for(i=0;i<MAXCELLHOSTS;i++) {
2250 if (tcell->cellHosts[i] == 0) break;
2251 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2252 cp += sizeof(afs_int32);
2254 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2255 strcpy(cp, tcell->cellName);
2256 cp += strlen(tcell->cellName)+1;
2257 *aoutSize = cp - aout;
2259 ReleaseReadLock(&afs_xcell);
2260 if (tcell) return 0;
2264 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2267 struct vrequest *areq;
2271 afs_int32 *aoutSize; /* set this */ {
2272 register afs_int32 code;
2274 afs_int32 offset, len, hasatsys = 0;
2275 register struct conn *tc;
2276 register struct dcache *tdc;
2277 register struct vcache *tvc;
2278 struct AFSFetchStatus OutDirStatus;
2279 struct VenusFid tfid;
2280 struct AFSVolSync tsync;
2284 /* "ain" is the name of the file in this dir to remove */
2286 AFS_STATCNT(PRemoveMount);
2287 if (!avc) return EINVAL;
2288 code = afs_VerifyVCache(avc, areq);
2289 if (code) return code;
2290 if (vType(avc) != VDIR) return ENOTDIR;
2292 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2293 if (!tdc) return ENOENT;
2294 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2295 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2300 tfid.Cell = avc->fid.Cell;
2301 tfid.Fid.Volume = avc->fid.Fid.Volume;
2302 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2303 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2305 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2306 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2313 if (vType(tvc) != VLNK) {
2315 afs_PutVCache(tvc, WRITE_LOCK);
2319 ObtainWriteLock(&tvc->lock,230);
2320 code = afs_HandleLink(tvc, areq);
2322 if (tvc->linkData) {
2323 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2328 ReleaseWriteLock(&tvc->lock);
2329 osi_dnlc_purgedp(tvc);
2330 afs_PutVCache(tvc, WRITE_LOCK);
2335 ObtainWriteLock(&avc->lock,231);
2336 osi_dnlc_remove(avc, bufp, tvc);
2338 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2340 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2341 #ifdef RX_ENABLE_LOCKS
2343 #endif /* RX_ENABLE_LOCKS */
2344 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2345 bufp, &OutDirStatus, &tsync);
2346 #ifdef RX_ENABLE_LOCKS
2348 #endif /* RX_ENABLE_LOCKS */
2353 (afs_Analyze(tc, code, &avc->fid, areq,
2354 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2355 SHARED_LOCK, (struct cell *)0));
2358 if (tdc) afs_PutDCache(tdc);
2359 ReleaseWriteLock(&avc->lock);
2363 /* we have the thing in the cache */
2364 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2365 /* we can do it locally */
2366 code = afs_dir_Delete(&tdc->f.inode, bufp);
2368 ZapDCE(tdc); /* surprise error -- invalid value */
2369 DZap(&tdc->f.inode);
2372 afs_PutDCache(tdc); /* drop ref count */
2374 avc->states &= ~CUnique; /* For the dfs xlator */
2375 ReleaseWriteLock(&avc->lock);
2378 if (hasatsys) osi_FreeLargeSpace(bufp);
2382 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2385 struct vrequest *areq;
2389 struct AFS_UCRED *acred;
2390 afs_int32 *aoutSize; /* set this */ {
2391 return EINVAL; /* OBSOLETE */
2394 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2397 struct vrequest *areq;
2400 afs_int32 *aoutSize; /* set this */ {
2401 register struct cell *tcell;
2404 AFS_STATCNT(PGetCellStatus);
2405 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2406 return EIO; /* Inappropriate ioctl for device */
2408 tcell = afs_GetCellByName(ain, READ_LOCK);
2409 if (!tcell) return ENOENT;
2410 temp = tcell->states;
2411 afs_PutCell(tcell, READ_LOCK);
2412 bcopy((char *)&temp, aout, sizeof(afs_int32));
2413 *aoutSize = sizeof(afs_int32);
2417 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2420 struct vrequest *areq;
2423 struct AFS_UCRED *acred;
2424 afs_int32 *aoutSize; /* set this */ {
2425 register struct cell *tcell;
2428 if (!afs_osi_suser(acred))
2430 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2431 return EIO; /* Inappropriate ioctl for device */
2433 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2434 if (!tcell) return ENOENT;
2435 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2437 tcell->states |= CNoSUID;
2439 tcell->states &= ~CNoSUID;
2440 afs_PutCell(tcell, WRITE_LOCK);
2444 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2447 struct vrequest *areq;
2450 afs_int32 *aoutSize; /* set this */
2451 struct AFS_UCRED *acred;
2453 extern struct volume *afs_volumes[NVOLS];
2454 register afs_int32 i;
2455 register struct dcache *tdc;
2456 register struct vcache *tvc;
2457 register struct volume *tv;
2458 afs_int32 cell, volume;
2460 AFS_STATCNT(PFlushVolumeData);
2463 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2464 return EIO; /* Inappropriate ioctl for device */
2466 volume = avc->fid.Fid.Volume; /* who to zap */
2467 cell = avc->fid.Cell;
2470 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2471 * the vcaches associated with the volume.
2473 ObtainReadLock(&afs_xvcache);
2474 for(i = 0; i < VCSIZE; i++) {
2475 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2476 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2477 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2478 VN_HOLD((struct vnode *)tvc);
2482 ReleaseReadLock(&afs_xvcache);
2483 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2484 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2486 ObtainWriteLock(&tvc->lock,232);
2488 ObtainWriteLock(&afs_xcbhash, 458);
2489 afs_DequeueCallback(tvc);
2490 tvc->states &= ~(CStatd | CDirty);
2491 ReleaseWriteLock(&afs_xcbhash);
2492 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2493 osi_dnlc_purgedp(tvc);
2494 afs_TryToSmush(tvc, acred, 1);
2495 ReleaseWriteLock(&tvc->lock);
2496 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2497 afs_BozonUnlock(&tvc->pvnLock, tvc);
2499 ObtainReadLock(&afs_xvcache);
2500 /* our tvc ptr is still good until now */
2505 ReleaseReadLock(&afs_xvcache);
2508 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2509 for(i=0;i<afs_cacheFiles;i++) {
2510 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2511 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2512 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2513 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2514 if (! (afs_indexFlags[i] & IFDataMod)) {
2515 /* if the file is modified, but has a ref cnt of only 1, then
2516 someone probably has the file open and is writing into it.
2517 Better to skip flushing such a file, it will be brought back
2518 immediately on the next write anyway.
2520 If we *must* flush, then this code has to be rearranged to call
2521 afs_storeAllSegments() first */
2522 afs_FlushDCache(tdc);
2526 tdc->refCount--; /* bumped by getdslot */
2528 MReleaseWriteLock(&afs_xdcache);
2530 ObtainReadLock(&afs_xvolume);
2531 for (i=0;i<NVOLS;i++) {
2532 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2533 if (tv->volume == volume) {
2534 afs_ResetVolumeInfo(tv);
2539 ReleaseReadLock(&afs_xvolume);
2541 /* probably, a user is doing this, probably, because things are screwed up.
2542 * maybe it's the dnlc's fault? */
2549 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2552 struct vrequest *areq;
2555 afs_int32 *aoutSize; /* set this */ {
2556 register afs_int32 code;
2557 struct vcxstat stat;
2560 /* AFS_STATCNT(PGetVnodeXStatus); */
2561 if (!avc) return EINVAL;
2562 code = afs_VerifyVCache(avc, areq);
2563 if (code) return code;
2564 if (vType(avc) == VDIR)
2565 mode = PRSFS_LOOKUP;
2568 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2570 stat.fid = avc->fid;
2571 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2572 stat.lock = avc->lock;
2573 stat.parentVnode = avc->parentVnode;
2574 stat.parentUnique = avc->parentUnique;
2575 hset(stat.flushDV, avc->flushDV);
2576 hset(stat.mapDV, avc->mapDV);
2577 stat.truncPos = avc->truncPos;
2578 { /* just grab the first two - won't break anything... */
2579 struct axscache *ac;
2581 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2582 stat.randomUid[i] = ac->uid;
2583 stat.randomAccess[i] = ac->axess;
2586 stat.callback = afs_data_pointer_to_int32(avc->callback);
2587 stat.cbExpires = avc->cbExpires;
2588 stat.anyAccess = avc->anyAccess;
2589 stat.opens = avc->opens;
2590 stat.execsOrWriters = avc->execsOrWriters;
2591 stat.flockCount = avc->flockCount;
2592 stat.mvstat = avc->mvstat;
2593 stat.states = avc->states;
2594 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2595 *aoutSize = sizeof(struct vcxstat);
2600 /* We require root for local sysname changes, but not for remote */
2601 /* (since we don't really believe remote uids anyway) */
2602 /* outname[] shouldn't really be needed- this is left as an excercise */
2603 /* for the reader. */
2605 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2608 struct vrequest *areq;
2611 afs_int32 *aoutSize; /* set this */
2612 register struct AFS_UCRED *acred;
2614 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2615 int setsysname, foundname=0;
2616 register struct afs_exporter *exporter;
2617 extern struct unixuser *afs_FindUser();
2618 extern char *afs_sysname;
2619 register struct unixuser *au;
2620 register afs_int32 pag, error;
2624 AFS_STATCNT(PSetSysName);
2625 if (!afs_globalVFS) {
2626 /* Afsd is NOT running; disable it */
2627 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
2630 return (setuerror(EINVAL), EINVAL);
2633 bzero(inname, MAXSYSNAME);
2634 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2635 ain += sizeof(afs_int32);
2640 bcopy(ain, inname, t+1); /* include terminating null */
2643 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2644 pag = PagInCred(acred);
2646 return EINVAL; /* Better than panicing */
2648 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2649 return EINVAL; /* Better than panicing */
2651 if (!(exporter = au->exporter)) {
2652 afs_PutUser(au, READ_LOCK);
2653 return EINVAL; /* Better than panicing */
2655 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2657 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2659 afs_PutUser(au, READ_LOCK);
2664 afs_PutUser(au, READ_LOCK);
2666 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2668 strcpy(outname, afs_sysname);
2671 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2673 strcpy(afs_sysname, inname);
2678 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2679 cp += sizeof(afs_int32);
2681 strcpy(cp, outname);
2682 cp += strlen(outname)+1;
2684 *aoutSize = cp - aout;
2689 /* sequential search through the list of touched cells is not a good
2690 * long-term solution here. For small n, though, it should be just
2691 * fine. Should consider special-casing the local cell for large n.
2692 * Likewise for PSetSPrefs.
2694 static void ReSortCells(s,l, vlonly)
2695 int s; /* number of ids in array l[] -- NOT index of last id */
2696 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2697 int vlonly; /* sort vl servers or file servers?*/
2699 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2708 tcell = afs_GetCell(l[k], WRITE_LOCK);
2709 if (!tcell) continue;
2710 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2711 afs_PutCell(tcell, WRITE_LOCK);
2716 ObtainReadLock(&afs_xvolume);
2717 for (i= 0; i< NVOLS; i++) {
2718 for (j=afs_volumes[i];j;j=j->next) {
2720 if (j->cell == l[k]) {
2721 ObtainWriteLock(&j->lock,233);
2722 afs_SortServers(j->serverHost, MAXHOSTS);
2723 ReleaseWriteLock(&j->lock);
2728 ReleaseReadLock(&afs_xvolume);
2733 static int afs_setsprefs(sp, num, vlonly)
2736 unsigned int vlonly;
2739 int i,j,k,matches,touchedSize;
2740 struct server *srvr = NULL;
2741 afs_int32 touched[34];
2745 for (k=0; k < num; sp++, k++) {
2747 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2750 ObtainReadLock(&afs_xserver);
2752 i = SHash(sp->host.s_addr);
2753 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2754 if (sa->sa_ip == sp->host.s_addr) {
2756 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2757 || (sa->sa_portal == AFS_FSPORT);
2758 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2765 if (sa && matches) { /* found one! */
2767 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2769 sa->sa_iprank = sp->rank + afs_randomMod15();
2770 afs_SortOneServer(sa->server);
2773 /* if we don't know yet what cell it's in, this is moot */
2774 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2775 /* is it in our list of touched cells ? */ ;
2776 if (j < 0) { /* no, it's not */
2777 touched[touchedSize++] = srvr->cell->cell;
2778 if (touchedSize >= 32) { /* watch for ovrflow */
2779 ReleaseReadLock(&afs_xserver);
2780 ReSortCells(touchedSize, touched, vlonly);
2782 ObtainReadLock(&afs_xserver);
2788 ReleaseReadLock(&afs_xserver);
2789 /* if we didn't find one, start to create one. */
2790 /* Note that it doesn't have a cell yet... */
2792 afs_uint32 temp = sp->host.s_addr;
2793 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2794 WRITE_LOCK, (afsUUID *)0,0);
2795 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2796 afs_PutServer(srvr, WRITE_LOCK);
2798 } /* for all cited preferences */
2800 ReSortCells(touchedSize, touched, vlonly);
2804 /* Note that this may only be performed by the local root user.
2807 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2810 struct vrequest *areq;
2813 struct AFS_UCRED *acred;
2814 afs_int32 *aoutSize;
2816 struct setspref *ssp;
2817 AFS_STATCNT(PSetSPrefs);
2819 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2820 return EIO; /* Inappropriate ioctl for device */
2822 if (!afs_osi_suser(acred))
2825 if (ainSize < sizeof(struct setspref))
2828 ssp = (struct setspref *)ain;
2829 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2832 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2833 (ssp->flags & DBservers));
2838 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2841 struct vrequest *areq;
2844 struct AFS_UCRED *acred;
2845 afs_int32 *aoutSize;
2848 AFS_STATCNT(PSetSPrefs);
2849 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2850 return EIO; /* Inappropriate ioctl for device */
2853 if (!afs_osi_suser(acred))
2856 sp = (struct spref *)ain;
2857 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2861 /* some notes on the following code...
2862 * in the hash table of server structs, all servers with the same IP address
2863 * will be on the same overflow chain.
2864 * This could be sped slightly in some circumstances by having it cache the
2865 * immediately previous slot in the hash table and some supporting information
2866 * Only reports file servers now.
2869 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2872 struct vrequest *areq;
2875 afs_int32 *aoutSize;
2877 struct sprefrequest *spin; /* input */
2878 struct sprefinfo *spout; /* output */
2879 struct spref *srvout; /* one output component */
2880 int i,j; /* counters for hash table traversal */
2881 struct server *srvr; /* one of CM's server structs */
2884 int vlonly; /* just return vlservers ? */
2887 AFS_STATCNT(PGetSPrefs);
2888 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2889 return EIO; /* Inappropriate ioctl for device */
2892 if (ainSize < sizeof (struct sprefrequest_33)) {
2896 spin = ((struct sprefrequest *) ain);
2899 if (ainSize > sizeof (struct sprefrequest_33)) {
2900 vlonly = (spin->flags & DBservers);
2904 /* struct sprefinfo includes 1 server struct... that size gets added
2905 * in during the loop that follows.
2907 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2908 spout = (struct sprefinfo *) aout;
2909 spout->next_offset = spin->offset;
2910 spout->num_servers = 0;
2911 srvout = spout->servers;
2913 ObtainReadLock(&afs_xserver);
2914 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2915 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2916 if (spin->offset > (unsigned short)i) {
2917 continue; /* catch up to where we left off */
2919 spout->next_offset++;
2922 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2923 || (sa->sa_portal == AFS_FSPORT);
2925 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2926 /* only report ranks for vl servers */
2930 srvout->host.s_addr = sa->sa_ip;
2931 srvout->rank = sa->sa_iprank;
2932 *aoutSize += sizeof(struct spref);
2933 spout->num_servers++;
2936 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2937 ReleaseReadLock(&afs_xserver); /* no more room! */
2942 ReleaseReadLock(&afs_xserver);
2944 spout->next_offset = 0; /* start over from the beginning next time */
2948 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2949 int afs_NFSRootOnly = 1;
2950 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2953 struct vrequest *areq;
2956 afs_int32 *aoutSize; /* set this */
2957 struct AFS_UCRED *acred;
2959 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2960 extern struct afs_exporter *exporter_find();
2961 register struct afs_exporter *exporter;
2963 AFS_STATCNT(PExportAfs);
2964 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
2965 type = handleValue >> 24;
2970 exporter = exporter_find(type);
2972 export = handleValue & 3;
2973 changestate = handleValue & 0xff;
2974 smounts = (handleValue >> 2) & 3;
2975 pwsync = (handleValue >> 4) & 3;
2976 convmode = (handleValue >> 6) & 3;
2978 changestate = (handleValue >> 16) & 0x1;
2979 convmode = (handleValue >> 16) & 0x2;
2980 pwsync = (handleValue >> 16) & 0x4;
2981 smounts = (handleValue >> 16) & 0x8;
2982 export = handleValue & 0xff;
2985 /* Failed finding desired exporter; */
2989 handleValue = exporter->exp_states;
2990 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2991 *aoutSize = sizeof(afs_int32);
2993 if (!afs_osi_suser(acred))
2994 return EACCES; /* Only superuser can do this */
2998 exporter->exp_states |= EXP_EXPORTED;
3000 exporter->exp_states &= ~EXP_EXPORTED;
3004 exporter->exp_states |= EXP_UNIXMODE;
3006 exporter->exp_states &= ~EXP_UNIXMODE;
3010 exporter->exp_states |= EXP_PWSYNC;
3012 exporter->exp_states &= ~EXP_PWSYNC;
3016 afs_NFSRootOnly = 0;
3017 exporter->exp_states |= EXP_SUBMOUNTS;
3019 afs_NFSRootOnly = 1;
3020 exporter->exp_states &= ~EXP_SUBMOUNTS;
3023 handleValue = exporter->exp_states;
3024 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3025 *aoutSize = sizeof(afs_int32);
3028 exporter->exp_states |= EXP_EXPORTED;
3030 exporter->exp_states &= ~EXP_EXPORTED;
3032 exporter->exp_states |= EXP_UNIXMODE;
3034 exporter->exp_states &= ~EXP_UNIXMODE;
3036 exporter->exp_states |= EXP_PWSYNC;
3038 exporter->exp_states &= ~EXP_PWSYNC;
3040 afs_NFSRootOnly = 0;
3041 exporter->exp_states |= EXP_SUBMOUNTS;
3043 afs_NFSRootOnly = 1;
3044 exporter->exp_states &= ~EXP_SUBMOUNTS;
3053 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3056 struct vrequest *areq;
3059 struct AFS_UCRED *acred;
3060 afs_int32 *aoutSize; /* set this */
3062 struct gaginfo *gagflags;
3064 if (!afs_osi_suser(acred))
3067 gagflags = (struct gaginfo *) ain;
3068 afs_showflags = gagflags->showflags;
3075 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3078 struct vrequest *areq;
3081 struct AFS_UCRED *acred;
3082 afs_int32 *aoutSize;
3084 struct rxparams *rxp;
3086 if (!afs_osi_suser(acred))
3089 rxp = (struct rxparams *) ain;
3091 if (rxp->rx_initReceiveWindow)
3092 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3093 if (rxp->rx_maxReceiveWindow)
3094 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3095 if (rxp->rx_initSendWindow)
3096 rx_initSendWindow = rxp->rx_initSendWindow;
3097 if (rxp->rx_maxSendWindow)
3098 rx_maxSendWindow = rxp->rx_maxSendWindow;
3099 if (rxp->rxi_nSendFrags)
3100 rxi_nSendFrags = rxp->rxi_nSendFrags;
3101 if (rxp->rxi_nRecvFrags)
3102 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3103 if (rxp->rxi_OrphanFragSize)
3104 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3105 if (rxp->rx_maxReceiveSize)
3107 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3108 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3110 if (rxp->rx_MyMaxSendSize)
3111 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3116 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3119 struct vrequest *areq;
3123 afs_int32 *aoutSize; /* set this */
3125 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3128 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3129 *aoutSize = sizeof(struct cm_initparams);
3133 #ifdef AFS_SGI65_ENV
3134 /* They took crget() from us, so fake it. */
3135 static cred_t *crget(void)
3138 cr = crdup(get_current_cred());
3139 bzero((char*)cr, sizeof(cred_t));
3140 #if CELL || CELL_PREPARE
3148 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3151 struct vrequest *areq;
3154 afs_int32 *aoutSize;
3155 struct AFS_UCRED *acred;
3157 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3158 *aoutSize=sizeof(afs_int32);
3163 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3166 struct vrequest *areq;
3169 afs_int32 *aoutSize;
3170 struct AFS_UCRED *acred;
3174 if (!afs_osi_suser(acred))
3176 if (ainSize != sizeof(afs_int32) || ain == NULL)
3178 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3179 /* if new mappings added later this will need to be changed */
3180 if (tmpval != 0 && tmpval != 1)
3187 * Create new credentials to correspond to a remote user with given
3188 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3189 * provide pioctl (and other) services to foreign clients (i.e. nfs
3190 * clients) by using this call to `become' the client.
3193 #define PIOCTL_HEADER 6
3194 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3197 afs_uint32 hostaddr;
3198 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3199 extern struct afs_exporter *exporter_find();
3200 struct afs_exporter *exporter, *outexporter;
3201 struct AFS_UCRED *newcred;
3202 struct unixuser *au;
3204 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3205 return EINVAL; /* NFS trans not supported for Ultrix */
3207 #if defined(AFS_SGIMP_ENV)
3208 osi_Assert(ISAFS_GLOCK());
3210 AFS_STATCNT(HandleClientContext);
3211 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3212 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3213 return EINVAL; /* Too small to be good */
3215 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3216 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3218 osi_FreeLargeSpace(inData);
3222 /* Extract information for remote user */
3223 hostaddr = *((afs_uint32 *)ain);
3224 ain += sizeof(hostaddr);
3225 uid = *((afs_uint32 *)ain);
3227 g0 = *((afs_uint32 *)ain);
3229 g1 = *((afs_uint32 *)ain);
3231 *com = *((afs_uint32 *)ain);
3232 ain += sizeof(afs_int32);
3233 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3236 * Of course, one must be root for most of these functions, but
3237 * we'll allow (for knfs) you to set things if the pag is 0 and
3238 * you're setting tokens or unlogging.
3241 if (!afs_osi_suser(credp)) {
3243 #ifndef AFS_SGI64_ENV
3244 /* Since SGI's suser() returns explicit failure after the call.. */
3248 /* check for acceptable opcodes for normal folks, which are, so far,
3249 * set tokens and unlog.
3251 if (i != 9 && i != 3 && i != 38 && i != 8) {
3252 osi_FreeLargeSpace(inData);
3257 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3258 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3259 osi_FreeLargeSpace(inData);
3262 * We map uid 0 to nobody to match the mapping that the nfs
3263 * server does and to ensure that the suser() calls in the afs
3264 * code fails for remote client roots.
3266 uid = afs_nobody; /* NFS_NOBODY == -2 */
3269 #ifdef AFS_AIX41_ENV
3272 newcred->cr_gid = RMTUSER_REQ;
3273 newcred->cr_groups[0] = g0;
3274 newcred->cr_groups[1] = g1;
3276 newcred->cr_ngrps = 2;
3278 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3279 newcred->cr_ngroups = 2;
3281 for (i=2; i<NGROUPS; i++)
3282 newcred->cr_groups[i] = NOGROUP;
3285 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3286 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3288 if (!(exporter = exporter_find(exporter_type))) {
3289 /* Exporter wasn't initialized or an invalid exporter type */
3293 if (exporter->exp_states & EXP_PWSYNC) {
3294 if (uid != credp->cr_uid) {
3296 return ENOEXEC; /* XXX Find a better errno XXX */
3299 newcred->cr_uid = uid; /* Only temporary */
3300 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3301 /* The client's pag is the only unique identifier for it */
3302 newcred->cr_uid = pag;
3304 if (!code && *com == PSETPAG) {
3305 /* Special case for 'setpag' */
3306 afs_uint32 pagvalue = genpag();
3308 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3310 * Note that we leave the 'outexporter' struct held so it won't
3313 au->exporter = outexporter;
3314 if (ablob->out_size >= 4) {
3315 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3317 afs_PutUser(au, WRITE_LOCK);
3318 if (code) return code;
3319 return PSETPAG; /* Special return for setpag */
3321 EXP_RELE(outexporter);
3324 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3327 /* get all interface addresses of this client */
3330 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3333 struct vrequest *areq;
3336 afs_int32 *aoutSize;
3338 struct sprefrequest *spin; /* input */
3339 struct sprefinfo *spout; /* output */
3340 struct spref *srvout; /* one output component */
3344 AFS_STATCNT(PGetCPrefs);
3345 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3346 return EIO; /* Inappropriate ioctl for device */
3348 if ( ainSize < sizeof (struct sprefrequest ))
3351 spin = (struct sprefrequest *) ain;
3352 spout = (struct sprefinfo *) aout;
3354 maxNumber = spin->num_servers; /* max addrs this time */
3355 srvout = spout->servers;
3357 ObtainReadLock(&afs_xinterface);
3359 /* copy out the client interface information from the
3360 ** kernel data structure "interface" to the output buffer
3362 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3363 && ( j< maxNumber) ; i++, j++, srvout++)
3364 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3366 spout->num_servers = j;
3367 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3369 if ( i >= afs_cb_interface.numberOfInterfaces )
3370 spout->next_offset = 0; /* start from beginning again */
3372 spout->next_offset = spin->offset + j;
3374 ReleaseReadLock(&afs_xinterface);
3379 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3382 struct vrequest *areq;
3385 afs_int32 *aoutSize;
3387 struct setspref *sin;
3390 AFS_STATCNT(PSetCPrefs);
3391 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3392 return EIO; /* Inappropriate ioctl for device */
3394 sin = (struct setspref *)ain;
3396 if ( ainSize < sizeof(struct setspref) )
3398 #if 0 /* num_servers is unsigned */
3399 if ( sin->num_servers < 0 )
3402 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3405 ObtainWriteLock(&afs_xinterface, 412);
3406 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3407 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3408 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3410 ReleaseWriteLock(&afs_xinterface);
3414 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3417 struct vrequest *areq;
3420 afs_int32 *aoutSize;
3421 struct AFS_UCRED *acred; {
3422 register afs_int32 code;
3423 register struct vcache *tvc;
3424 register struct dcache *tdc;
3425 struct VenusFid tfid;
3427 afs_int32 offset, len, hasatsys=0;
3429 AFS_STATCNT(PFlushMount);
3430 if (!avc) return EINVAL;
3431 code = afs_VerifyVCache(avc, areq);
3432 if (code) return code;
3433 if (vType(avc) != VDIR) {
3436 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3437 if (!tdc) return ENOENT;
3438 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3439 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3444 tfid.Cell = avc->fid.Cell;
3445 tfid.Fid.Volume = avc->fid.Fid.Volume;
3446 afs_PutDCache(tdc); /* we're done with the data */
3447 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3448 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3450 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3457 if (vType(tvc) != VLNK) {
3458 afs_PutVCache(tvc, WRITE_LOCK);
3462 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3463 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3465 ObtainWriteLock(&tvc->lock,645);
3466 ObtainWriteLock(&afs_xcbhash, 646);
3467 afs_DequeueCallback(tvc);
3468 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3469 ReleaseWriteLock(&afs_xcbhash);
3470 /* now find the disk cache entries */
3471 afs_TryToSmush(tvc, acred, 1);
3472 osi_dnlc_purgedp(tvc);
3473 afs_symhint_inval(tvc);
3474 if (tvc->linkData && !(tvc->states & CCore)) {
3475 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3476 tvc->linkData = (char *) 0;
3478 ReleaseWriteLock(&tvc->lock);
3479 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3480 afs_BozonUnlock(&tvc->pvnLock, tvc);
3482 afs_PutVCache(tvc, WRITE_LOCK);
3484 if (hasatsys) osi_FreeLargeSpace(bufp);
3488 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3491 struct vrequest *areq;
3494 afs_int32 *aoutSize;
3495 struct AFS_UCRED *acred;
3500 if (!afs_osi_suser(acred)) {
3504 if (ainSize != sizeof(afs_int32)) {
3508 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3509 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3513 if (flags & AFSCALL_RXSTATS_ENABLE) {
3514 rx_enableProcessRPCStats();
3516 if (flags & AFSCALL_RXSTATS_DISABLE) {
3517 rx_disableProcessRPCStats();
3519 if (flags & AFSCALL_RXSTATS_CLEAR) {
3520 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3528 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3531 struct vrequest *areq;
3534 afs_int32 *aoutSize;
3535 struct AFS_UCRED *acred;
3540 if (!afs_osi_suser(acred)) {
3544 if (ainSize != sizeof(afs_int32)) {
3548 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3549 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3553 if (flags & AFSCALL_RXSTATS_ENABLE) {
3554 rx_enablePeerRPCStats();
3556 if (flags & AFSCALL_RXSTATS_DISABLE) {
3557 rx_disablePeerRPCStats();
3559 if (flags & AFSCALL_RXSTATS_CLEAR) {
3560 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3567 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3570 struct vrequest *areq;
3573 afs_int32 *aoutSize; /* set this */
3575 register afs_int32 code, code1;
3578 struct rx_call *tcall;
3579 struct AFSVolSync tsync;
3580 struct AFSFetchStatus OutStatus;
3581 struct AFSCallBack CallBack;
3582 struct VenusFid tfid;
3587 AFS_STATCNT(PSetAcl);
3591 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3592 Fid = (struct AFSFid *) ain;
3594 Fid = &avc->fid.Fid;
3595 tfid.Cell = avc->fid.Cell;
3596 tfid.Fid.Volume = Fid->Volume;
3597 tfid.Fid.Vnode = Fid->Vnode;
3598 tfid.Fid.Unique = Fid->Unique;
3600 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3603 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3604 ICL_TYPE_POINTER, tvc,
3605 ICL_TYPE_FID, &tfid,
3606 ICL_TYPE_FID, &avc->fid);
3609 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3610 ICL_TYPE_POINTER, tvc,
3611 ICL_TYPE_FID, &tfid,
3612 ICL_TYPE_FID, &tvc->fid);
3615 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3618 #ifdef RX_ENABLE_LOCKS
3620 #endif /* RX_ENABLE_LOCKS */
3621 tcall = rx_NewCall(tc->id);
3622 code = StartRXAFS_FetchData(tcall,
3623 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3625 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3626 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3628 code1 = rx_EndCall(tcall, code);
3629 #ifdef RX_ENABLE_LOCKS
3631 #endif /* RX_ENABLE_LOCKS */
3635 (afs_Analyze(tc, code, &tvc->fid, areq,
3636 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3638 /* This call is done only to have the callback things handled correctly */
3639 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3640 afs_PutVCache(tvc, WRITE_LOCK);
3643 *aoutSize = sizeof(afs_int32);
3648 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3651 struct vrequest *areq;
3654 afs_int32 *aoutSize; /* set this */
3656 register afs_int32 code;
3659 struct ResidencyCmdInputs *Inputs;
3660 struct ResidencyCmdOutputs *Outputs;
3661 struct VenusFid tfid;
3664 Inputs = (struct ResidencyCmdInputs *) ain;
3665 Outputs = (struct ResidencyCmdOutputs *) aout;
3666 if (!avc) return EINVAL;
3667 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3671 Fid = &avc->fid.Fid;
3673 tfid.Cell = avc->fid.Cell;
3674 tfid.Fid.Volume = Fid->Volume;
3675 tfid.Fid.Vnode = Fid->Vnode;
3676 tfid.Fid.Unique = Fid->Unique;
3678 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3680 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3681 ICL_TYPE_POINTER, tvc,
3682 ICL_TYPE_INT32, Inputs->command,
3683 ICL_TYPE_FID, &tfid);
3687 if (Inputs->command) {
3689 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3691 #ifdef RX_ENABLE_LOCKS
3693 #endif /* RX_ENABLE_LOCKS */
3694 code = RXAFS_ResidencyCmd(tc->id, Fid,
3696 (struct ResidencyCmdOutputs *) aout);
3697 #ifdef RX_ENABLE_LOCKS
3699 #endif /* RX_ENABLE_LOCKS */
3703 (afs_Analyze(tc, code, &tvc->fid, areq,
3704 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3706 /* This call is done to have the callback things handled correctly */
3707 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3708 } else { /* just a status request, return also link data */
3710 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3711 Outputs->chars[0] = 0;
3712 if (vType(tvc) == VLNK) {
3713 ObtainWriteLock(&tvc->lock,555);
3714 if (afs_HandleLink(tvc, areq) == 0)
3715 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3716 ReleaseWriteLock(&tvc->lock);
3720 afs_PutVCache(tvc, WRITE_LOCK);
3723 *aoutSize = sizeof(struct ResidencyCmdOutputs);