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_LINUX20_ENV
203 if (current->tss.flags & SPARC_FLAG_32BIT)
205 #error Not done for this linux type
206 #endif /* AFS_SPARC64_LINUX20_ENV */
208 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
210 afs_ioctl32_to_afs_ioctl(&dst32, dst);
213 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
215 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
219 HandleIoctl(avc, acom, adata)
220 register struct vcache *avc;
221 register afs_int32 acom;
222 struct afs_ioctl *adata; {
223 register afs_int32 code;
226 AFS_STATCNT(HandleIoctl);
228 switch(acom & 0xff) {
230 avc->states |= CSafeStore;
234 /* case 2 used to be abort store, but this is no longer provided,
235 since it is impossible to implement under normal Unix.
239 /* return the name of the cell this file is open on */
240 register struct cell *tcell;
241 register afs_int32 i;
243 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
245 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
247 if (i > adata->out_size) {
248 /* 0 means we're not interested in the output */
249 if (adata->out_size != 0) code = EFAULT;
253 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
255 afs_PutCell(tcell, READ_LOCK);
261 case 49: /* VIOC_GETINITPARAMS */
262 if (adata->out_size < sizeof(struct cm_initparams)) {
266 AFS_COPYOUT(&cm_initParams, adata->out,
267 sizeof(struct cm_initparams), code);
276 return code; /* so far, none implemented */
281 /* For aix we don't temporarily bypass ioctl(2) but rather do our
282 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
283 * is now called from afs_gn_ioctl.
285 afs_ioctl(tvc, cmd, arg)
290 struct afs_ioctl data;
293 AFS_STATCNT(afs_ioctl);
294 if (((cmd >> 8) & 0xff) == 'V') {
295 /* This is a VICEIOCTL call */
296 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
299 error = HandleIoctl(tvc, cmd, &data);
302 /* No-op call; just return. */
306 #endif /* AFS_AIX_ENV */
308 #if defined(AFS_SGI_ENV)
309 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
315 struct afs_ioctl data;
321 AFS_STATCNT(afs_ioctl);
322 if (((cmd >> 8) & 0xff) == 'V') {
323 /* This is a VICEIOCTL call */
324 error = copyin_afs_ioctl(arg, &data);
327 locked = ISAFS_GLOCK();
330 error = HandleIoctl(tvc, cmd, &data);
335 /* No-op call; just return. */
339 #endif /* AFS_SGI_ENV */
342 /* unlike most calls here, this one uses u.u_error to return error conditions,
343 since this is really an intercepted chapter 2 call, rather than a vnode
346 /* AFS_HPUX102 and up uses VNODE ioctl instead */
347 #ifndef AFS_HPUX102_ENV
348 #if !defined(AFS_SGI_ENV)
350 kioctl(fdes, com, arg, ext)
357 } u_uap, *uap = &u_uap;
361 struct afs_ioctl_sys {
367 afs_xioctl (uap, rvp)
368 struct afs_ioctl_sys *uap;
373 afs_xioctl (p, args, retval)
382 } *uap = (struct a *)args;
383 #else /* AFS_OSF_ENV */
384 #ifdef AFS_DARWIN_ENV
390 afs_xioctl(p, uap, retval)
392 register struct ioctl_args *uap;
396 #ifdef AFS_LINUX22_ENV
397 struct afs_ioctl_sys {
401 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
402 unsigned int com, unsigned long arg)
404 struct afs_ioctl_sys ua, *uap = &ua;
412 } *uap = (struct a *)u.u_ap;
413 #endif /* AFS_LINUX22_ENV */
414 #endif /* AFS_DARWIN_ENV */
415 #endif /* AFS_OSF_ENV */
416 #endif /* AFS_SUN5_ENV */
418 #ifndef AFS_LINUX22_ENV
419 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
422 register struct file *fd;
425 register struct vcache *tvc;
426 register int ioctlDone = 0, code = 0;
428 AFS_STATCNT(afs_xioctl);
429 #ifdef AFS_DARWIN_ENV
430 if ((code=fdgetf(p, uap->fd, &fd)))
433 #ifdef AFS_LINUX22_ENV
441 if (setuerror(getf(uap->fd, &fd))) {
447 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
449 #else /* AFS_OSF_ENV */
451 #if defined(AFS_SUN57_ENV)
453 if (!fd) return(EBADF);
454 #elif defined(AFS_SUN54_ENV)
456 if (!fd) return(EBADF);
458 if (code = getf(uap->fd, &fd)) {
471 /* first determine whether this is any sort of vnode */
472 #ifdef AFS_LINUX22_ENV
473 tvc = (struct vcache *)ip;
477 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
479 if (fd->f_type == DTYPE_VNODE) {
481 /* good, this is a vnode; next see if it is an AFS vnode */
482 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
483 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
485 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
487 #endif /* AFS_LINUX22_ENV */
488 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
490 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
491 if (!tvc) { /* shouldn't happen with held gnodes */
496 /* This is an AFS vnode */
497 if (((uap->com >> 8) & 0xff) == 'V') {
498 register struct afs_ioctl *datap;
500 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
501 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
503 osi_FreeSmallSpace(datap);
505 #ifdef AFS_DARWIN_ENV
508 #if defined(AFS_SUN5_ENV)
523 #else /* AFS_OSF_ENV */
527 #ifdef AFS_LINUX22_ENV
537 code = HandleIoctl(tvc, uap->com, datap);
538 osi_FreeSmallSpace(datap);
552 #if defined(AFS_LINUX22_ENV)
562 code = okioctl(fdes, com, arg, ext);
566 okioctl(fdes, com, arg, ext);
568 #if defined(AFS_SUN5_ENV)
569 #if defined(AFS_SUN57_ENV)
571 #elif defined(AFS_SUN54_ENV)
576 code = ioctl(uap, rvp);
578 #if defined(AFS_DARWIN_ENV)
579 return ioctl(p, uap, retval);
582 code = ioctl(p, args, retval);
589 #else /* AFS_OSF_ENV */
590 #ifndef AFS_LINUX22_ENV
608 #ifdef AFS_LINUX22_ENV
611 #if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV)
614 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
615 return (getuerror() ? -1 : u.u_ioctlrv);
617 return getuerror() ? -1 : 0;
620 #endif /* AFS_LINUX22_ENV */
621 #endif /* AFS_SUN5_ENV */
622 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
626 #endif /* AFS_SGI_ENV */
627 #endif /* AFS_HPUX102_ENV */
629 #if defined(AFS_SGI_ENV)
630 /* "pioctl" system call entry point; just pass argument to the parameterized
639 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
643 AFS_STATCNT(afs_pioctl);
645 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
653 #endif /* AFS_SGI_ENV */
656 afs_pioctl(p, args, retval)
666 } *uap = (struct a *) args;
668 AFS_STATCNT(afs_pioctl);
669 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
672 extern struct mount *afs_globalVFS;
673 #else /* AFS_OSF_ENV */
674 #ifdef AFS_DARWIN_ENV
675 afs_pioctl(p, args, retval)
685 } *uap = (struct a *) args;
687 AFS_STATCNT(afs_pioctl);
688 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
691 extern struct mount *afs_globalVFS;
692 #else /* AFS_OSF_ENV */
693 extern struct vfs *afs_globalVFS;
697 /* macro to avoid adding any more #ifdef's to pioctl code. */
698 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
699 #define PIOCTL_FREE_CRED() crfree(credp)
701 #define PIOCTL_FREE_CRED()
705 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
707 struct AFS_UCRED *credp;
709 #ifdef AFS_DARWIN_ENV
710 afs_syscall_pioctl(path, com, cmarg, follow, credp)
711 struct AFS_UCRED *credp;
713 afs_syscall_pioctl(path, com, cmarg, follow)
721 struct afs_ioctl data;
722 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
723 register afs_int32 code = 0;
729 struct ucred *credp = crref(); /* don't free until done! */
731 #ifdef AFS_LINUX22_ENV
732 cred_t *credp = crref(); /* don't free until done! */
735 AFS_STATCNT(afs_syscall_pioctl);
736 if (follow) follow = 1; /* compat. with old venus */
738 if (! _VALIDVICEIOCTL(com)) {
740 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
742 #else /* AFS_OSF_ENV */
743 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
752 code = copyin_afs_ioctl(cmarg, &data);
755 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
762 if ((com & 0xff) == PSetClientContext) {
763 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
764 return EINVAL; /* Not handling these yet. */
766 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
767 code = HandleClientContext(&data, &com, &foreigncreds, credp);
769 #if defined(AFS_HPUX101_ENV)
770 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
773 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
775 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
776 #endif /* AFS_SGI_ENV */
782 crfree(foreigncreds);
785 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
788 return (setuerror(code), code);
792 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV)
795 * We could have done without temporary setting the u.u_cred below
796 * (foreigncreds could be passed as param the pioctl modules)
797 * but calls such as afs_osi_suser() doesn't allow that since it
798 * references u.u_cred directly. We could, of course, do something
799 * like afs_osi_suser(cred) which, I think, is better since it
800 * generalizes and supports multi cred environments...
804 credp = foreigncreds;
807 tmpcred = crref(); /* XXX */
810 #if defined(AFS_HPUX101_ENV)
811 tmpcred = p_cred(u.u_procp);
812 set_p_cred(u.u_procp, foreigncreds);
815 tmpcred = OSI_GET_CURRENT_CRED();
816 OSI_SET_CURRENT_CRED(foreigncreds);
819 u.u_cred = foreigncreds;
820 #endif /* AFS_SGI64_ENV */
821 #endif /* AFS_HPUX101_ENV */
826 if ((com & 0xff) == 15) {
827 /* special case prefetch so entire pathname eval occurs in helper process.
828 otherwise, the pioctl call is essentially useless */
829 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
830 code = Prefetch(path, &data, follow,
831 foreigncreds ? foreigncreds : credp);
833 #if defined(AFS_HPUX101_ENV)
834 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
837 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
839 code = Prefetch(path, &data, follow, u.u_cred);
840 #endif /* AFS_SGI64_ENV */
841 #endif /* AFS_HPUX101_ENV */
843 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV)
846 crset(tmpcred); /* restore original credentials */
848 #if defined(AFS_HPUX101_ENV)
849 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
853 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
855 u.u_cred = tmpcred; /* restore original credentials */
858 #endif /* AFS_HPUX101_ENV */
859 crfree(foreigncreds);
862 #endif /* AFS_LINUX22_ENV */
864 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
867 return (setuerror(code), code);
873 code = lookupname(path, USR, follow, NULL, &vp,
874 foreigncreds ? foreigncreds : credp);
876 #ifdef AFS_LINUX22_ENV
877 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
879 vp = (struct vnode *)dp->d_inode;
881 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
882 #endif /* AFS_LINUX22_ENV */
883 #endif /* AFS_AIX41_ENV */
886 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV)
889 crset(tmpcred); /* restore original credentials */
891 #if defined(AFS_HPUX101_ENV)
892 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
894 #if !defined(AFS_SUN5_ENV)
896 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
898 u.u_cred = tmpcred; /* restore original credentials */
899 #endif /* AFS_SGI64_ENV */
901 #endif /* AFS_HPUX101_ENV */
902 crfree(foreigncreds);
905 #endif /* AFS_LINUX22_ENV */
907 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
910 return(setuerror(code), code);
914 else vp = (struct vnode *) 0;
916 /* now make the call if we were passed no file, or were passed an AFS file */
917 if (!vp || IsAfsVnode(vp)) {
919 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
920 * So, we must test in this part of the code. Also, must arrange to
921 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
922 * we hold gnodes, whose references hold our vcache entries.
925 gp = vp; /* remember for "put" */
926 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
928 else gp = (struct vnode *) 0;
931 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
935 struct ucred *cred1, *cred2;
938 cred1 = cred2 = foreigncreds;
940 cred1 = cred2 = credp;
942 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
943 if (cred1 != cred2) {
944 /* something changed the creds */
949 #if defined(AFS_HPUX101_ENV)
951 struct ucred *cred = p_cred(u.u_procp);
952 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
958 credp = OSI_GET_CURRENT_CRED();
959 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
962 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
963 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
965 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
967 #endif /* AFS_SGI_ENV */
968 #endif /* AFS_HPUX101_ENV */
969 #endif /* AFS_AIX41_ENV */
970 #endif /* AFS_SUN5_ENV */
972 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
973 code = EINVAL; /* not in /afs */
980 vp = (struct vnode *) 0;
985 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV)
990 #if defined(AFS_HPUX101_ENV)
991 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
995 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
997 u.u_cred = tmpcred; /* restore original credentials */
998 #endif /* ASF_SGI64_ENV */
1000 #endif /* AFS_HPUX101_ENV */
1001 crfree(foreigncreds);
1004 #endif /* AFS_LINUX22_ENV */
1006 #ifdef AFS_LINUX22_ENV
1009 AFS_RELE(vp); /* put vnode back */
1013 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
1018 return (getuerror());
1023 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
1024 register struct vcache *avc;
1026 struct AFS_UCRED **acred;
1027 register struct afs_ioctl *ablob;
1030 struct vrequest treq;
1031 register afs_int32 code;
1032 register afs_int32 function;
1033 afs_int32 inSize, outSize;
1034 char *inData, *outData;
1036 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1037 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1038 AFS_STATCNT(HandlePioctl);
1039 if (code = afs_InitReq(&treq, *acred)) return code;
1040 function = acom & 0xff;
1041 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
1042 return EINVAL; /* out of range */
1044 inSize = ablob->in_size;
1045 if (inSize >= PIGGYSIZE) return E2BIG;
1046 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1048 AFS_COPYIN(ablob->in, inData, inSize, code);
1052 osi_FreeLargeSpace(inData);
1055 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1057 if (function == 3) /* PSetTokens */
1058 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1060 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1061 osi_FreeLargeSpace(inData);
1062 if (code == 0 && ablob->out_size > 0) {
1063 if (outSize > ablob->out_size) outSize = ablob->out_size;
1064 if (outSize >= PIGGYSIZE) code = E2BIG;
1066 AFS_COPYOUT(outData, ablob->out, outSize, code);
1068 osi_FreeLargeSpace(outData);
1069 return afs_CheckCode(code, &treq, 41);
1072 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1075 struct vrequest *areq;
1078 afs_int32 *aoutSize; /* set this */ {
1079 register afs_int32 code;
1081 AFS_STATCNT(PGetFID);
1082 if (!avc) return EINVAL;
1083 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1084 *aoutSize = sizeof(struct VenusFid);
1088 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1091 struct vrequest *areq;
1094 afs_int32 *aoutSize; /* set this */ {
1095 register afs_int32 code;
1097 struct AFSOpaque acl;
1098 struct AFSVolSync tsync;
1099 struct AFSFetchStatus OutStatus;
1102 AFS_STATCNT(PSetAcl);
1105 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1108 acl.AFSOpaque_val = ain;
1110 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1112 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1113 #ifdef RX_ENABLE_LOCKS
1115 #endif /* RX_ENABLE_LOCKS */
1116 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1117 &acl, &OutStatus, &tsync);
1118 #ifdef RX_ENABLE_LOCKS
1120 #endif /* RX_ENABLE_LOCKS */
1125 (afs_Analyze(tconn, code, &avc->fid, areq,
1126 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1128 /* now we've forgotten all of the access info */
1129 ObtainWriteLock(&afs_xcbhash, 455);
1131 afs_DequeueCallback(avc);
1132 avc->states &= ~(CStatd | CUnique);
1133 ReleaseWriteLock(&afs_xcbhash);
1134 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1135 osi_dnlc_purgedp(avc);
1139 int afs_defaultAsynchrony = 0;
1141 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1144 struct vrequest *areq;
1147 afs_int32 *aoutSize; /* set this */
1148 struct AFS_UCRED *acred;
1151 struct sbstruct *sbr;
1153 sbr = (struct sbstruct *)ain;
1154 if (sbr->sb_default != -1) {
1155 if (afs_osi_suser(acred))
1156 afs_defaultAsynchrony = sbr->sb_default;
1160 if (avc && (sbr->sb_thisfile != -1))
1161 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1162 areq, DONT_CHECK_MODE_BITS))
1163 avc->asynchrony = sbr->sb_thisfile;
1166 *aoutSize = sizeof(struct sbstruct);
1167 sbr = (struct sbstruct *)aout;
1168 sbr->sb_default = afs_defaultAsynchrony;
1170 sbr->sb_thisfile = avc->asynchrony;
1176 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1179 struct vrequest *areq;
1182 afs_int32 *aoutSize; /* set this */
1183 struct AFS_UCRED *acred;
1185 if (!afs_osi_suser(acred)) {
1188 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1192 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1195 struct vrequest *areq;
1198 afs_int32 *aoutSize; /* set this */ {
1199 struct AFSOpaque acl;
1200 struct AFSVolSync tsync;
1201 struct AFSFetchStatus OutStatus;
1207 AFS_STATCNT(PGetAcl);
1208 if (!avc) return EINVAL;
1209 Fid.Volume = avc->fid.Fid.Volume;
1210 Fid.Vnode = avc->fid.Fid.Vnode;
1211 Fid.Unique = avc->fid.Fid.Unique;
1212 if (avc->states & CForeign) {
1214 * For a dfs xlator acl we have a special hack so that the
1215 * xlator will distinguish which type of acl will return. So
1216 * we currently use the top 2-bytes (vals 0-4) to tell which
1217 * type of acl to bring back. Horrible hack but this will
1218 * cause the least number of changes to code size and interfaces.
1220 if (Fid.Vnode & 0xc0000000)
1222 Fid.Vnode |= (ainSize << 30);
1224 acl.AFSOpaque_val = aout;
1226 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1229 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1230 #ifdef RX_ENABLE_LOCKS
1232 #endif /* RX_ENABLE_LOCKS */
1233 code = RXAFS_FetchACL(tconn->id, &Fid,
1234 &acl, &OutStatus, &tsync);
1235 #ifdef RX_ENABLE_LOCKS
1237 #endif /* RX_ENABLE_LOCKS */
1242 (afs_Analyze(tconn, code, &avc->fid, areq,
1243 AFS_STATS_FS_RPCIDX_FETCHACL,
1244 SHARED_LOCK, (struct cell *)0));
1247 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1258 AFS_STATCNT(PBogus);
1262 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1265 struct vrequest *areq;
1269 afs_int32 *aoutSize; /* set this */ {
1270 register struct cell *tcell;
1272 AFS_STATCNT(PGetFileCell);
1273 if (!avc) return EINVAL;
1274 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1275 if (!tcell) return ESRCH;
1276 strcpy(aout, tcell->cellName);
1277 afs_PutCell(tcell, READ_LOCK);
1278 *aoutSize = strlen(aout) + 1;
1282 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1285 struct vrequest *areq;
1289 afs_int32 *aoutSize; /* set this */ {
1290 register struct cell *tcell=0, *cellOne=0;
1291 register struct afs_q *cq, *tq;
1293 AFS_STATCNT(PGetWSCell);
1294 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1295 return EIO; /* Inappropriate ioctl for device */
1297 ObtainReadLock(&afs_xcell);
1298 cellOne = (struct cell *) 0;
1300 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1301 tcell = QTOC(cq); tq = QNext(cq);
1302 if (tcell->states & CPrimary) break;
1303 if (tcell->cell == 1) cellOne = tcell;
1306 ReleaseReadLock(&afs_xcell);
1307 if (!tcell) { /* no primary cell, use cell #1 */
1308 if (!cellOne) return ESRCH;
1311 strcpy(aout, tcell->cellName);
1312 *aoutSize = strlen(aout) + 1;
1316 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1319 struct vrequest *areq;
1323 afs_int32 *aoutSize; /* set this */ {
1324 register afs_int32 i;
1325 register struct unixuser *tu;
1326 register struct cell *tcell;
1328 AFS_STATCNT(PGetUserCell);
1329 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1330 return EIO; /* Inappropriate ioctl for device */
1332 /* return the cell name of the primary cell for this user */
1333 i = UHash(areq->uid);
1334 ObtainWriteLock(&afs_xuser,224);
1335 for(tu = afs_users[i]; tu; tu = tu->next) {
1336 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1338 ReleaseWriteLock(&afs_xuser);
1343 tcell = afs_GetCell(tu->cell, READ_LOCK);
1344 afs_PutUser(tu, WRITE_LOCK);
1345 if (!tcell) return ESRCH;
1347 strcpy(aout, tcell->cellName);
1348 afs_PutCell(tcell, READ_LOCK);
1349 *aoutSize = strlen(aout)+1; /* 1 for the null */
1353 ReleaseWriteLock(&afs_xuser);
1360 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1363 struct vrequest *areq;
1367 afs_int32 *aoutSize; /* set this */
1368 struct AFS_UCRED **acred;
1371 register struct unixuser *tu;
1372 struct ClearToken clear;
1373 register struct cell *tcell;
1376 struct vrequest treq;
1377 afs_int32 flag, set_parent_pag = 0;
1379 AFS_STATCNT(PSetTokens);
1380 if (!afs_resourceinit_flag) {
1383 bcopy(ain, (char *)&i, sizeof(afs_int32));
1384 ain += sizeof(afs_int32);
1385 stp = ain; /* remember where the ticket is */
1386 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1388 ain += i; /* skip over ticket */
1389 bcopy(ain, (char *)&i, sizeof(afs_int32));
1390 ain += sizeof(afs_int32);
1391 if (i != sizeof(struct ClearToken)) {
1394 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1395 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1396 ain += sizeof(struct ClearToken);
1397 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1398 /* still stuff left? we've got primary flag and cell name. Set these */
1399 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1400 ain += sizeof(afs_int32); /* skip id field */
1401 /* rest is cell name, look it up */
1402 if (flag & 0x8000) { /* XXX Use Constant XXX */
1406 tcell = afs_GetCellByName(ain, READ_LOCK);
1415 /* default to cell 1, primary id */
1416 flag = 1; /* primary id */
1417 i = 1; /* cell number */
1418 tcell = afs_GetCell(1, READ_LOCK);
1419 if (!tcell) goto nocell;
1421 afs_PutCell(tcell, READ_LOCK);
1422 if (set_parent_pag) {
1424 #ifdef AFS_DARWIN_ENV
1425 struct proc *p=current_proc(); /* XXX */
1426 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1427 p->p_pid, p->p_comm);
1428 if (!setpag(p, acred, -1, &pag, 1)) {
1431 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1433 if (!setpag(acred, -1, &pag, 1)) {
1436 afs_InitReq(&treq, *acred);
1440 /* now we just set the tokens */
1441 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1442 tu->vid = clear.ViceId;
1443 if (tu->stp != (char *) 0) {
1444 afs_osi_Free(tu->stp, tu->stLen);
1446 tu->stp = (char *) afs_osi_Alloc(stLen);
1448 bcopy(stp, tu->stp, stLen);
1451 afs_stats_cmfullperf.authent.TicketUpdates++;
1452 afs_ComputePAGStats();
1453 #endif /* AFS_NOSTATS */
1454 tu->states |= UHasTokens;
1455 tu->states &= ~UTokensBad;
1456 afs_SetPrimary(tu, flag);
1457 tu->tokenTime =osi_Time();
1458 afs_ResetUserConns(tu);
1459 afs_PutUser(tu, WRITE_LOCK);
1474 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1477 struct vrequest *areq;
1480 afs_int32 *aoutSize; /* set this */ {
1482 char offLineMsg[256];
1484 register struct conn *tc;
1485 register afs_int32 code;
1486 struct VolumeStatus volstat;
1488 char *Name, *OfflineMsg, *MOTD;
1491 AFS_STATCNT(PGetVolumeStatus);
1492 if (!avc) return EINVAL;
1494 OfflineMsg = offLineMsg;
1497 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1499 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1500 #ifdef RX_ENABLE_LOCKS
1502 #endif /* RX_ENABLE_LOCKS */
1503 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1504 &Name, &OfflineMsg, &MOTD);
1505 #ifdef RX_ENABLE_LOCKS
1507 #endif /* RX_ENABLE_LOCKS */
1512 (afs_Analyze(tc, code, &avc->fid, areq,
1513 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1514 SHARED_LOCK, (struct cell *)0));
1516 if (code) return code;
1517 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1519 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1520 cp += sizeof(VolumeStatus);
1521 strcpy(cp, volName);
1522 cp += strlen(volName)+1;
1523 strcpy(cp, offLineMsg);
1524 cp += strlen(offLineMsg)+1;
1526 cp += strlen(motd)+1;
1527 *aoutSize = (cp - aout);
1531 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1534 struct vrequest *areq;
1537 afs_int32 *aoutSize; /* set this */ {
1539 char offLineMsg[256];
1541 register struct conn *tc;
1542 register afs_int32 code;
1543 struct AFSFetchVolumeStatus volstat;
1544 struct AFSStoreVolumeStatus storeStat;
1545 register struct volume *tvp;
1549 AFS_STATCNT(PSetVolumeStatus);
1550 if (!avc) return EINVAL;
1552 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1554 if (tvp->states & (VRO | VBackup)) {
1555 afs_PutVolume(tvp, READ_LOCK);
1558 afs_PutVolume(tvp, READ_LOCK);
1561 /* Copy the junk out, using cp as a roving pointer. */
1563 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1564 cp += sizeof(AFSFetchVolumeStatus);
1565 if (strlen(cp) >= sizeof(volName))
1567 strcpy(volName, cp);
1568 cp += strlen(volName)+1;
1569 if (strlen(cp) >= sizeof(offLineMsg))
1571 strcpy(offLineMsg, cp);
1572 cp += strlen(offLineMsg)+1;
1573 if (strlen(cp) >= sizeof(motd))
1577 if (volstat.MinQuota != -1) {
1578 storeStat.MinQuota = volstat.MinQuota;
1579 storeStat.Mask |= AFS_SETMINQUOTA;
1581 if (volstat.MaxQuota != -1) {
1582 storeStat.MaxQuota = volstat.MaxQuota;
1583 storeStat.Mask |= AFS_SETMAXQUOTA;
1586 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1588 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1589 #ifdef RX_ENABLE_LOCKS
1591 #endif /* RX_ENABLE_LOCKS */
1592 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1593 &storeStat, volName, offLineMsg, motd);
1594 #ifdef RX_ENABLE_LOCKS
1596 #endif /* RX_ENABLE_LOCKS */
1601 (afs_Analyze(tc, code, &avc->fid, areq,
1602 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1603 SHARED_LOCK, (struct cell *)0));
1605 if (code) return code;
1606 /* we are sending parms back to make compat. with prev system. should
1607 change interface later to not ask for current status, just set new status */
1609 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1610 cp += sizeof(VolumeStatus);
1611 strcpy(cp, volName);
1612 cp += strlen(volName)+1;
1613 strcpy(cp, offLineMsg);
1614 cp += strlen(offLineMsg)+1;
1616 cp += strlen(motd)+1;
1617 *aoutSize = cp - aout;
1621 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1622 register struct vcache *avc;
1624 struct vrequest *areq;
1627 afs_int32 *aoutSize; /* set this */
1628 struct AFS_UCRED *acred;
1631 AFS_STATCNT(PFlush);
1632 if (!avc) return EINVAL;
1633 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1634 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1636 ObtainWriteLock(&avc->lock,225);
1637 ObtainWriteLock(&afs_xcbhash, 456);
1638 afs_DequeueCallback(avc);
1639 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1640 ReleaseWriteLock(&afs_xcbhash);
1641 /* now find the disk cache entries */
1642 afs_TryToSmush(avc, acred, 1);
1643 osi_dnlc_purgedp(avc);
1644 afs_symhint_inval(avc);
1645 if (avc->linkData && !(avc->states & CCore)) {
1646 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1647 avc->linkData = (char *) 0;
1649 ReleaseWriteLock(&avc->lock);
1650 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1651 afs_BozonUnlock(&avc->pvnLock, avc);
1656 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1659 struct vrequest *areq;
1662 afs_int32 *aoutSize; /* set this */ {
1663 register afs_int32 code;
1664 register struct vcache *tvc;
1665 register struct dcache *tdc;
1666 struct VenusFid tfid;
1668 afs_int32 offset, len, hasatsys=0;
1670 AFS_STATCNT(PNewStatMount);
1671 if (!avc) return EINVAL;
1672 code = afs_VerifyVCache(avc, areq);
1673 if (code) return code;
1674 if (vType(avc) != VDIR) {
1677 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1678 if (!tdc) return ENOENT;
1679 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1680 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1685 tfid.Cell = avc->fid.Cell;
1686 tfid.Fid.Volume = avc->fid.Fid.Volume;
1687 afs_PutDCache(tdc); /* we're done with the data */
1688 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1689 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1691 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1698 if (vType(tvc) != VLNK) {
1699 afs_PutVCache(tvc, WRITE_LOCK);
1703 ObtainWriteLock(&tvc->lock,226);
1704 code = afs_HandleLink(tvc, areq);
1706 if (tvc->linkData) {
1707 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1710 /* we have the data */
1711 strcpy(aout, tvc->linkData);
1712 *aoutSize = strlen(tvc->linkData)+1;
1717 ReleaseWriteLock(&tvc->lock);
1718 afs_PutVCache(tvc, WRITE_LOCK);
1720 if (hasatsys) osi_FreeLargeSpace(bufp);
1724 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1727 struct vrequest *areq;
1730 afs_int32 *aoutSize; /* set this */ {
1731 register struct cell *tcell;
1732 register afs_int32 i;
1733 register struct unixuser *tu;
1738 AFS_STATCNT(PGetTokens);
1739 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1740 return EIO; /* Inappropriate ioctl for device */
1742 /* weird interface. If input parameter is present, it is an integer and
1743 we're supposed to return the parm'th tokens for this unix uid.
1744 If not present, we just return tokens for cell 1.
1745 If counter out of bounds, return EDOM.
1746 If no tokens for the particular cell, return ENOTCONN.
1747 Also, if this mysterious parm is present, we return, along with the
1748 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1749 at the end, in that order.
1751 if (newStyle = (ainSize > 0)) {
1752 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1754 i = UHash(areq->uid);
1755 ObtainReadLock(&afs_xuser);
1756 for(tu = afs_users[i]; tu; tu=tu->next) {
1758 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1759 if (iterator-- == 0) break; /* are we done yet? */
1763 if (tu->uid == areq->uid && tu->cell == 1) break;
1768 * No need to hold a read lock on each user entry
1772 ReleaseReadLock(&afs_xuser);
1777 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1778 tu->states |= (UTokensBad | UNeedsReset);
1779 afs_PutUser(tu, READ_LOCK);
1782 /* use iterator for temp */
1784 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1785 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1786 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1787 cp += sizeof(afs_int32);
1788 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1790 iterator = sizeof(struct ClearToken);
1791 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1792 cp += sizeof(afs_int32);
1793 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1794 cp += sizeof(struct ClearToken);
1796 /* put out primary id and cell name, too */
1797 iterator = (tu->states & UPrimary ? 1 : 0);
1798 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1799 cp += sizeof(afs_int32);
1800 tcell = afs_GetCell(tu->cell, READ_LOCK);
1802 strcpy(cp, tcell->cellName);
1803 cp += strlen(tcell->cellName)+1;
1804 afs_PutCell(tcell, READ_LOCK);
1808 *aoutSize = cp - aout;
1809 afs_PutUser(tu, READ_LOCK);
1813 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1816 struct vrequest *areq;
1819 afs_int32 *aoutSize; /* set this */ {
1820 register afs_int32 i;
1821 register struct unixuser *tu;
1823 AFS_STATCNT(PUnlog);
1824 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1825 return EIO; /* Inappropriate ioctl for device */
1827 i = UHash(areq->uid);
1828 ObtainWriteLock(&afs_xuser,227);
1829 for(tu=afs_users[i]; tu; tu=tu->next) {
1830 if (tu->uid == areq->uid) {
1832 tu->states &= ~UHasTokens;
1833 /* security is not having to say you're sorry */
1834 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1836 ReleaseWriteLock(&afs_xuser);
1837 /* We have to drop the lock over the call to afs_ResetUserConns, since
1838 * it obtains the afs_xvcache lock. We could also keep the lock, and
1839 * modify ResetUserConns to take parm saying we obtained the lock
1840 * already, but that is overkill. By keeping the "tu" pointer
1841 * held over the released lock, we guarantee that we won't lose our
1842 * place, and that we'll pass over every user conn that existed when
1843 * we began this call.
1845 afs_ResetUserConns(tu);
1847 ObtainWriteLock(&afs_xuser,228);
1849 /* set the expire times to 0, causes
1850 * afs_GCUserData to remove this entry
1852 tu->ct.EndTimestamp = 0;
1854 #endif /* UKERNEL */
1857 ReleaseWriteLock(&afs_xuser);
1861 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1864 struct vrequest *areq;
1867 afs_int32 *aoutSize; /* set this */ {
1868 afs_int32 newHostAddr;
1869 afs_int32 oldHostAddr;
1871 AFS_STATCNT(PMariner);
1873 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1875 oldHostAddr = 0xffffffff; /* disabled */
1877 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1878 if (newHostAddr == 0xffffffff) {
1879 /* disable mariner operations */
1882 else if (newHostAddr) {
1884 afs_marinerHost = newHostAddr;
1886 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1887 *aoutSize = sizeof(afs_int32);
1891 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1894 struct vrequest *areq;
1897 afs_int32 *aoutSize; /* set this */
1898 struct AFS_UCRED *acred;
1900 register char *cp = 0;
1902 register struct server *ts;
1903 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1905 struct chservinfo *pcheck;
1907 AFS_STATCNT(PCheckServers);
1909 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1910 return EIO; /* Inappropriate ioctl for device */
1912 if (*lp == 0x12345678) { /* For afs3.3 version */
1913 pcheck=(struct chservinfo *)ain;
1914 if (pcheck->tinterval >= 0) {
1916 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1917 *aoutSize = sizeof(afs_int32);
1918 if (pcheck->tinterval > 0) {
1919 if (!afs_osi_suser(acred))
1921 PROBE_INTERVAL=pcheck->tinterval;
1927 temp=pcheck->tflags;
1928 cp = pcheck->tbuffer;
1929 } else { /* For pre afs3.3 versions */
1930 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1931 cp = ain+sizeof(afs_int32);
1932 if (ainSize > sizeof(afs_int32))
1937 * 1: fast check, don't contact servers.
1938 * 2: local cell only.
1941 /* have cell name, too */
1942 cellp = afs_GetCellByName(cp, READ_LOCK);
1943 if (!cellp) return ENOENT;
1945 else cellp = (struct cell *) 0;
1946 if (!cellp && (temp & 2)) {
1947 /* use local cell */
1948 cellp = afs_GetCell(1, READ_LOCK);
1950 if (!(temp & 1)) { /* if not fast, call server checker routine */
1951 afs_CheckServers(1, cellp); /* check down servers */
1952 afs_CheckServers(0, cellp); /* check up servers */
1954 /* now return the current down server list */
1956 ObtainReadLock(&afs_xserver);
1957 for(i=0;i<NSERVERS;i++) {
1958 for(ts = afs_servers[i]; ts; ts=ts->next) {
1959 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1960 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1961 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1962 cp += sizeof(afs_int32);
1966 ReleaseReadLock(&afs_xserver);
1967 if (cellp) afs_PutCell(cellp, READ_LOCK);
1968 *aoutSize = cp - aout;
1972 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1975 struct vrequest *areq;
1978 afs_int32 *aoutSize; /* set this */ {
1979 AFS_STATCNT(PCheckVolNames);
1980 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1981 return EIO; /* Inappropriate ioctl for device */
1983 afs_CheckRootVolume();
1984 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1985 AFS_VOLCHECK_EXPIRED |
1987 AFS_VOLCHECK_MTPTS);
1991 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1994 struct vrequest *areq;
1997 afs_int32 *aoutSize; /* set this */ {
2001 struct unixuser *tu;
2003 extern afs_rwlock_t afs_xsrvAddr;
2005 AFS_STATCNT(PCheckAuth);
2006 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2007 return EIO; /* Inappropriate ioctl for device */
2010 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2011 if (!tu) retValue = EACCES;
2013 /* we have a user */
2014 ObtainReadLock(&afs_xsrvAddr);
2015 ObtainReadLock(&afs_xconn);
2017 /* any tokens set? */
2018 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
2019 /* all connections in cell 1 working? */
2020 for(i=0;i<NSERVERS;i++) {
2021 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
2022 for (tc = sa->conns; tc; tc=tc->next) {
2023 if (tc->user == tu && (tu->states & UTokensBad))
2028 ReleaseReadLock(&afs_xsrvAddr);
2029 ReleaseReadLock(&afs_xconn);
2030 afs_PutUser(tu, READ_LOCK);
2032 bcopy((char *)&retValue, aout, sizeof(afs_int32));
2033 *aoutSize = sizeof(afs_int32);
2037 static Prefetch(apath, adata, afollow, acred)
2039 struct afs_ioctl *adata;
2041 struct AFS_UCRED *acred;
2044 register afs_int32 code;
2045 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV)
2051 AFS_STATCNT(Prefetch);
2052 if (!apath) return EINVAL;
2053 tp = osi_AllocLargeSpace(1024);
2054 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2056 osi_FreeLargeSpace(tp);
2059 if (afs_BBusy()) { /* do this as late as possible */
2060 osi_FreeLargeSpace(tp);
2061 return EWOULDBLOCK; /* pretty close */
2063 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
2067 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
2070 struct vrequest *areq;
2073 afs_int32 *aoutSize; /* set this */ {
2074 register struct volume *tvp;
2075 register struct server *ts;
2076 register afs_int32 i;
2079 AFS_STATCNT(PFindVolume);
2080 if (!avc) return EINVAL;
2081 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2084 for(i=0;i<MAXHOSTS;i++) {
2085 ts = tvp->serverHost[i];
2087 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2088 cp += sizeof(afs_int32);
2091 /* still room for terminating NULL, add it on */
2092 ainSize = 0; /* reuse vbl */
2093 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2094 cp += sizeof(afs_int32);
2096 *aoutSize = cp - aout;
2097 afs_PutVolume(tvp, READ_LOCK);
2103 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2106 struct vrequest *areq;
2109 afs_int32 *aoutSize; /* set this */ {
2110 register afs_int32 code;
2113 AFS_STATCNT(PViceAccess);
2114 if (!avc) return EINVAL;
2115 code = afs_VerifyVCache(avc, areq);
2116 if (code) return code;
2117 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2118 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2123 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2126 struct vrequest *areq;
2129 afs_int32 *aoutSize; /* set this */
2130 struct AFS_UCRED *acred;
2135 AFS_STATCNT(PSetCacheSize);
2136 if (!afs_osi_suser(acred))
2138 /* too many things are setup initially in mem cache version */
2139 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2140 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2141 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2143 extern u_int afs_min_cache;
2144 if (newValue < afs_min_cache)
2145 afs_cacheBlocks = afs_min_cache;
2147 afs_cacheBlocks = newValue;
2149 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2150 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2151 afs_MaybeWakeupTruncateDaemon();
2152 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2153 afs_osi_Wait(1000, 0, 0);
2154 afs_MaybeWakeupTruncateDaemon();
2159 #define MAXGCSTATS 16
2160 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2163 struct vrequest *areq;
2166 afs_int32 *aoutSize; /* set this */ {
2167 afs_int32 results[MAXGCSTATS];
2169 AFS_STATCNT(PGetCacheSize);
2170 bzero((char *)results, sizeof(results));
2171 results[0] = afs_cacheBlocks;
2172 results[1] = afs_blocksUsed;
2173 bcopy((char *)results, aout, sizeof(results));
2174 *aoutSize = sizeof(results);
2178 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2181 struct vrequest *areq;
2184 afs_int32 *aoutSize; /* set this */ {
2185 register struct conn *tc;
2186 register afs_int32 code;
2187 struct AFSCallBack CallBacks_Array[1];
2188 struct AFSCBFids theFids;
2189 struct AFSCBs theCBs;
2192 AFS_STATCNT(PRemoveCallBack);
2193 if (!avc) return EINVAL;
2194 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2195 ObtainWriteLock(&avc->lock,229);
2196 theFids.AFSCBFids_len = 1;
2197 theCBs.AFSCBs_len = 1;
2198 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2199 theCBs.AFSCBs_val = CallBacks_Array;
2200 CallBacks_Array[0].CallBackType = CB_DROPPED;
2201 if (avc->callback) {
2203 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2205 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2206 #ifdef RX_ENABLE_LOCKS
2208 #endif /* RX_ENABLE_LOCKS */
2209 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2210 #ifdef RX_ENABLE_LOCKS
2212 #endif /* RX_ENABLE_LOCKS */
2215 /* don't set code on failure since we wouldn't use it */
2217 (afs_Analyze(tc, code, &avc->fid, areq,
2218 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2219 SHARED_LOCK, (struct cell *)0));
2221 ObtainWriteLock(&afs_xcbhash, 457);
2222 afs_DequeueCallback(avc);
2224 avc->states &= ~(CStatd | CUnique);
2225 ReleaseWriteLock(&afs_xcbhash);
2226 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2227 osi_dnlc_purgedp(avc);
2229 ReleaseWriteLock(&avc->lock);
2233 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2236 struct vrequest *areq;
2240 struct AFS_UCRED *acred;
2241 afs_int32 *aoutSize; /* set this */ {
2242 /* create a new cell */
2243 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2244 register struct cell *tcell;
2245 char *newcell=0, *linkedcell=0, *tp= ain;
2246 register afs_int32 code, linkedstate=0, ls;
2247 u_short fsport = 0, vlport = 0;
2250 AFS_STATCNT(PNewCell);
2251 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2252 return EIO; /* Inappropriate ioctl for device */
2254 if (!afs_osi_suser(acred))
2257 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2258 tp += sizeof(afs_int32);
2259 if (magic != 0x12345678)
2262 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2263 * server addresses while the 3.5 fs newcell command passes
2264 * MAXHOSTS. To figure out which is which, check if the cellname
2267 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2268 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2270 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2271 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2272 tp += (scount * sizeof(afs_int32));
2274 lp = (afs_int32 *)tp;
2277 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2278 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2279 tp += (3 * sizeof(afs_int32));
2281 if ((ls = *lp) & 1) {
2282 linkedcell = tp + strlen(newcell)+1;
2283 linkedstate |= CLinkedCell;
2286 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2287 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
2291 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2294 struct vrequest *areq;
2297 afs_int32 *aoutSize; /* set this */ {
2298 afs_int32 whichCell;
2299 register struct cell *tcell=0;
2300 register afs_int32 i;
2301 register char *cp, *tp = ain;
2302 register struct afs_q *cq, *tq;
2304 AFS_STATCNT(PListCells);
2305 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2306 return EIO; /* Inappropriate ioctl for device */
2308 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2309 tp += sizeof(afs_int32);
2310 ObtainReadLock(&afs_xcell);
2311 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2312 tcell = QTOC(cq); tq = QNext(cq);
2313 if (whichCell == 0) break;
2314 if (tq == &CellLRU) tcell = 0;
2319 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2320 for(i=0;i<MAXCELLHOSTS;i++) {
2321 if (tcell->cellHosts[i] == 0) break;
2322 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2323 cp += sizeof(afs_int32);
2325 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2326 strcpy(cp, tcell->cellName);
2327 cp += strlen(tcell->cellName)+1;
2328 *aoutSize = cp - aout;
2330 ReleaseReadLock(&afs_xcell);
2331 if (tcell) return 0;
2335 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2338 struct vrequest *areq;
2342 afs_int32 *aoutSize; /* set this */ {
2343 register afs_int32 code;
2345 afs_int32 offset, len, hasatsys = 0;
2346 register struct conn *tc;
2347 register struct dcache *tdc;
2348 register struct vcache *tvc;
2349 struct AFSFetchStatus OutDirStatus;
2350 struct VenusFid tfid;
2351 struct AFSVolSync tsync;
2355 /* "ain" is the name of the file in this dir to remove */
2357 AFS_STATCNT(PRemoveMount);
2358 if (!avc) return EINVAL;
2359 code = afs_VerifyVCache(avc, areq);
2360 if (code) return code;
2361 if (vType(avc) != VDIR) return ENOTDIR;
2363 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2364 if (!tdc) return ENOENT;
2365 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2366 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2371 tfid.Cell = avc->fid.Cell;
2372 tfid.Fid.Volume = avc->fid.Fid.Volume;
2373 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2374 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2376 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2377 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2384 if (vType(tvc) != VLNK) {
2386 afs_PutVCache(tvc, WRITE_LOCK);
2390 ObtainWriteLock(&tvc->lock,230);
2391 code = afs_HandleLink(tvc, areq);
2393 if (tvc->linkData) {
2394 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2399 ReleaseWriteLock(&tvc->lock);
2400 osi_dnlc_purgedp(tvc);
2401 afs_PutVCache(tvc, WRITE_LOCK);
2406 ObtainWriteLock(&avc->lock,231);
2407 osi_dnlc_remove(avc, bufp, tvc);
2409 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2411 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2412 #ifdef RX_ENABLE_LOCKS
2414 #endif /* RX_ENABLE_LOCKS */
2415 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2416 bufp, &OutDirStatus, &tsync);
2417 #ifdef RX_ENABLE_LOCKS
2419 #endif /* RX_ENABLE_LOCKS */
2424 (afs_Analyze(tc, code, &avc->fid, areq,
2425 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2426 SHARED_LOCK, (struct cell *)0));
2429 if (tdc) afs_PutDCache(tdc);
2430 ReleaseWriteLock(&avc->lock);
2434 /* we have the thing in the cache */
2435 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2436 /* we can do it locally */
2437 code = afs_dir_Delete(&tdc->f.inode, bufp);
2439 ZapDCE(tdc); /* surprise error -- invalid value */
2440 DZap(&tdc->f.inode);
2443 afs_PutDCache(tdc); /* drop ref count */
2445 avc->states &= ~CUnique; /* For the dfs xlator */
2446 ReleaseWriteLock(&avc->lock);
2449 if (hasatsys) osi_FreeLargeSpace(bufp);
2453 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2456 struct vrequest *areq;
2460 struct AFS_UCRED *acred;
2461 afs_int32 *aoutSize; /* set this */ {
2462 return EINVAL; /* OBSOLETE */
2465 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2468 struct vrequest *areq;
2471 afs_int32 *aoutSize; /* set this */ {
2472 register struct cell *tcell;
2475 AFS_STATCNT(PGetCellStatus);
2476 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2477 return EIO; /* Inappropriate ioctl for device */
2479 tcell = afs_GetCellByName(ain, READ_LOCK);
2480 if (!tcell) return ENOENT;
2481 temp = tcell->states;
2482 afs_PutCell(tcell, READ_LOCK);
2483 bcopy((char *)&temp, aout, sizeof(afs_int32));
2484 *aoutSize = sizeof(afs_int32);
2488 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2491 struct vrequest *areq;
2494 struct AFS_UCRED *acred;
2495 afs_int32 *aoutSize; /* set this */ {
2496 register struct cell *tcell;
2499 if (!afs_osi_suser(acred))
2501 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2502 return EIO; /* Inappropriate ioctl for device */
2504 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2505 if (!tcell) return ENOENT;
2506 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2508 tcell->states |= CNoSUID;
2510 tcell->states &= ~CNoSUID;
2511 afs_PutCell(tcell, WRITE_LOCK);
2515 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2518 struct vrequest *areq;
2521 afs_int32 *aoutSize; /* set this */
2522 struct AFS_UCRED *acred;
2524 extern struct volume *afs_volumes[NVOLS];
2525 register afs_int32 i;
2526 register struct dcache *tdc;
2527 register struct vcache *tvc;
2528 register struct volume *tv;
2529 afs_int32 cell, volume;
2531 AFS_STATCNT(PFlushVolumeData);
2534 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2535 return EIO; /* Inappropriate ioctl for device */
2537 volume = avc->fid.Fid.Volume; /* who to zap */
2538 cell = avc->fid.Cell;
2541 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2542 * the vcaches associated with the volume.
2544 ObtainReadLock(&afs_xvcache);
2545 for(i = 0; i < VCSIZE; i++) {
2546 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2547 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2548 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2549 VN_HOLD((struct vnode *)tvc);
2551 #if defined(AFS_DARWIN_ENV)
2557 ReleaseReadLock(&afs_xvcache);
2558 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2559 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2561 ObtainWriteLock(&tvc->lock,232);
2563 ObtainWriteLock(&afs_xcbhash, 458);
2564 afs_DequeueCallback(tvc);
2565 tvc->states &= ~(CStatd | CDirty);
2566 ReleaseWriteLock(&afs_xcbhash);
2567 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2568 osi_dnlc_purgedp(tvc);
2569 afs_TryToSmush(tvc, acred, 1);
2570 ReleaseWriteLock(&tvc->lock);
2571 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2572 afs_BozonUnlock(&tvc->pvnLock, tvc);
2574 ObtainReadLock(&afs_xvcache);
2575 /* our tvc ptr is still good until now */
2580 ReleaseReadLock(&afs_xvcache);
2583 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2584 for(i=0;i<afs_cacheFiles;i++) {
2585 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2586 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2587 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2588 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2589 if (! (afs_indexFlags[i] & IFDataMod)) {
2590 /* if the file is modified, but has a ref cnt of only 1, then
2591 someone probably has the file open and is writing into it.
2592 Better to skip flushing such a file, it will be brought back
2593 immediately on the next write anyway.
2595 If we *must* flush, then this code has to be rearranged to call
2596 afs_storeAllSegments() first */
2597 afs_FlushDCache(tdc);
2601 tdc->refCount--; /* bumped by getdslot */
2603 MReleaseWriteLock(&afs_xdcache);
2605 ObtainReadLock(&afs_xvolume);
2606 for (i=0;i<NVOLS;i++) {
2607 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2608 if (tv->volume == volume) {
2609 afs_ResetVolumeInfo(tv);
2614 ReleaseReadLock(&afs_xvolume);
2616 /* probably, a user is doing this, probably, because things are screwed up.
2617 * maybe it's the dnlc's fault? */
2624 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2627 struct vrequest *areq;
2630 afs_int32 *aoutSize; /* set this */ {
2631 register afs_int32 code;
2632 struct vcxstat stat;
2635 /* AFS_STATCNT(PGetVnodeXStatus); */
2636 if (!avc) return EINVAL;
2637 code = afs_VerifyVCache(avc, areq);
2638 if (code) return code;
2639 if (vType(avc) == VDIR)
2640 mode = PRSFS_LOOKUP;
2643 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2645 stat.fid = avc->fid;
2646 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2647 stat.lock = avc->lock;
2648 stat.parentVnode = avc->parentVnode;
2649 stat.parentUnique = avc->parentUnique;
2650 hset(stat.flushDV, avc->flushDV);
2651 hset(stat.mapDV, avc->mapDV);
2652 stat.truncPos = avc->truncPos;
2653 { /* just grab the first two - won't break anything... */
2654 struct axscache *ac;
2656 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2657 stat.randomUid[i] = ac->uid;
2658 stat.randomAccess[i] = ac->axess;
2661 stat.callback = afs_data_pointer_to_int32(avc->callback);
2662 stat.cbExpires = avc->cbExpires;
2663 stat.anyAccess = avc->anyAccess;
2664 stat.opens = avc->opens;
2665 stat.execsOrWriters = avc->execsOrWriters;
2666 stat.flockCount = avc->flockCount;
2667 stat.mvstat = avc->mvstat;
2668 stat.states = avc->states;
2669 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2670 *aoutSize = sizeof(struct vcxstat);
2675 /* We require root for local sysname changes, but not for remote */
2676 /* (since we don't really believe remote uids anyway) */
2677 /* outname[] shouldn't really be needed- this is left as an excercise */
2678 /* for the reader. */
2680 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2683 struct vrequest *areq;
2686 afs_int32 *aoutSize; /* set this */
2687 register struct AFS_UCRED *acred;
2689 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2690 int setsysname, foundname=0;
2691 register struct afs_exporter *exporter;
2692 extern struct unixuser *afs_FindUser();
2693 extern char *afs_sysname;
2694 register struct unixuser *au;
2695 register afs_int32 pag, error;
2699 AFS_STATCNT(PSetSysName);
2700 if (!afs_globalVFS) {
2701 /* Afsd is NOT running; disable it */
2702 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
2705 return (setuerror(EINVAL), EINVAL);
2708 bzero(inname, MAXSYSNAME);
2709 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2710 ain += sizeof(afs_int32);
2715 bcopy(ain, inname, t+1); /* include terminating null */
2718 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2719 pag = PagInCred(acred);
2721 return EINVAL; /* Better than panicing */
2723 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2724 return EINVAL; /* Better than panicing */
2726 if (!(exporter = au->exporter)) {
2727 afs_PutUser(au, READ_LOCK);
2728 return EINVAL; /* Better than panicing */
2730 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2732 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2734 afs_PutUser(au, READ_LOCK);
2739 afs_PutUser(au, READ_LOCK);
2741 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2743 strcpy(outname, afs_sysname);
2746 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2748 strcpy(afs_sysname, inname);
2753 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2754 cp += sizeof(afs_int32);
2756 strcpy(cp, outname);
2757 cp += strlen(outname)+1;
2759 *aoutSize = cp - aout;
2764 /* sequential search through the list of touched cells is not a good
2765 * long-term solution here. For small n, though, it should be just
2766 * fine. Should consider special-casing the local cell for large n.
2767 * Likewise for PSetSPrefs.
2769 static void ReSortCells(s,l, vlonly)
2770 int s; /* number of ids in array l[] -- NOT index of last id */
2771 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2772 int vlonly; /* sort vl servers or file servers?*/
2774 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2783 tcell = afs_GetCell(l[k], WRITE_LOCK);
2784 if (!tcell) continue;
2785 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2786 afs_PutCell(tcell, WRITE_LOCK);
2791 ObtainReadLock(&afs_xvolume);
2792 for (i= 0; i< NVOLS; i++) {
2793 for (j=afs_volumes[i];j;j=j->next) {
2795 if (j->cell == l[k]) {
2796 ObtainWriteLock(&j->lock,233);
2797 afs_SortServers(j->serverHost, MAXHOSTS);
2798 ReleaseWriteLock(&j->lock);
2803 ReleaseReadLock(&afs_xvolume);
2808 static int afs_setsprefs(sp, num, vlonly)
2811 unsigned int vlonly;
2814 int i,j,k,matches,touchedSize;
2815 struct server *srvr = NULL;
2816 afs_int32 touched[34];
2820 for (k=0; k < num; sp++, k++) {
2822 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2825 ObtainReadLock(&afs_xserver);
2827 i = SHash(sp->host.s_addr);
2828 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2829 if (sa->sa_ip == sp->host.s_addr) {
2831 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2832 || (sa->sa_portal == AFS_FSPORT);
2833 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2840 if (sa && matches) { /* found one! */
2842 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2844 sa->sa_iprank = sp->rank + afs_randomMod15();
2845 afs_SortOneServer(sa->server);
2848 /* if we don't know yet what cell it's in, this is moot */
2849 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2850 /* is it in our list of touched cells ? */ ;
2851 if (j < 0) { /* no, it's not */
2852 touched[touchedSize++] = srvr->cell->cell;
2853 if (touchedSize >= 32) { /* watch for ovrflow */
2854 ReleaseReadLock(&afs_xserver);
2855 ReSortCells(touchedSize, touched, vlonly);
2857 ObtainReadLock(&afs_xserver);
2863 ReleaseReadLock(&afs_xserver);
2864 /* if we didn't find one, start to create one. */
2865 /* Note that it doesn't have a cell yet... */
2867 afs_uint32 temp = sp->host.s_addr;
2868 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2869 WRITE_LOCK, (afsUUID *)0,0);
2870 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2871 afs_PutServer(srvr, WRITE_LOCK);
2873 } /* for all cited preferences */
2875 ReSortCells(touchedSize, touched, vlonly);
2879 /* Note that this may only be performed by the local root user.
2882 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2885 struct vrequest *areq;
2888 struct AFS_UCRED *acred;
2889 afs_int32 *aoutSize;
2891 struct setspref *ssp;
2892 AFS_STATCNT(PSetSPrefs);
2894 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2895 return EIO; /* Inappropriate ioctl for device */
2897 if (!afs_osi_suser(acred))
2900 if (ainSize < sizeof(struct setspref))
2903 ssp = (struct setspref *)ain;
2904 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2907 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2908 (ssp->flags & DBservers));
2913 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2916 struct vrequest *areq;
2919 struct AFS_UCRED *acred;
2920 afs_int32 *aoutSize;
2923 AFS_STATCNT(PSetSPrefs);
2924 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2925 return EIO; /* Inappropriate ioctl for device */
2928 if (!afs_osi_suser(acred))
2931 sp = (struct spref *)ain;
2932 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2936 /* some notes on the following code...
2937 * in the hash table of server structs, all servers with the same IP address
2938 * will be on the same overflow chain.
2939 * This could be sped slightly in some circumstances by having it cache the
2940 * immediately previous slot in the hash table and some supporting information
2941 * Only reports file servers now.
2944 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2947 struct vrequest *areq;
2950 afs_int32 *aoutSize;
2952 struct sprefrequest *spin; /* input */
2953 struct sprefinfo *spout; /* output */
2954 struct spref *srvout; /* one output component */
2955 int i,j; /* counters for hash table traversal */
2956 struct server *srvr; /* one of CM's server structs */
2959 int vlonly; /* just return vlservers ? */
2962 AFS_STATCNT(PGetSPrefs);
2963 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2964 return EIO; /* Inappropriate ioctl for device */
2967 if (ainSize < sizeof (struct sprefrequest_33)) {
2971 spin = ((struct sprefrequest *) ain);
2974 if (ainSize > sizeof (struct sprefrequest_33)) {
2975 vlonly = (spin->flags & DBservers);
2979 /* struct sprefinfo includes 1 server struct... that size gets added
2980 * in during the loop that follows.
2982 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2983 spout = (struct sprefinfo *) aout;
2984 spout->next_offset = spin->offset;
2985 spout->num_servers = 0;
2986 srvout = spout->servers;
2988 ObtainReadLock(&afs_xserver);
2989 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2990 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2991 if (spin->offset > (unsigned short)i) {
2992 continue; /* catch up to where we left off */
2994 spout->next_offset++;
2997 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2998 || (sa->sa_portal == AFS_FSPORT);
3000 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3001 /* only report ranks for vl servers */
3005 srvout->host.s_addr = sa->sa_ip;
3006 srvout->rank = sa->sa_iprank;
3007 *aoutSize += sizeof(struct spref);
3008 spout->num_servers++;
3011 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3012 ReleaseReadLock(&afs_xserver); /* no more room! */
3017 ReleaseReadLock(&afs_xserver);
3019 spout->next_offset = 0; /* start over from the beginning next time */
3023 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3024 int afs_NFSRootOnly = 1;
3025 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3028 struct vrequest *areq;
3031 afs_int32 *aoutSize; /* set this */
3032 struct AFS_UCRED *acred;
3034 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
3035 extern struct afs_exporter *exporter_find();
3036 register struct afs_exporter *exporter;
3038 AFS_STATCNT(PExportAfs);
3039 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
3040 type = handleValue >> 24;
3045 exporter = exporter_find(type);
3047 export = handleValue & 3;
3048 changestate = handleValue & 0xff;
3049 smounts = (handleValue >> 2) & 3;
3050 pwsync = (handleValue >> 4) & 3;
3051 convmode = (handleValue >> 6) & 3;
3053 changestate = (handleValue >> 16) & 0x1;
3054 convmode = (handleValue >> 16) & 0x2;
3055 pwsync = (handleValue >> 16) & 0x4;
3056 smounts = (handleValue >> 16) & 0x8;
3057 export = handleValue & 0xff;
3060 /* Failed finding desired exporter; */
3064 handleValue = exporter->exp_states;
3065 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3066 *aoutSize = sizeof(afs_int32);
3068 if (!afs_osi_suser(acred))
3069 return EACCES; /* Only superuser can do this */
3073 exporter->exp_states |= EXP_EXPORTED;
3075 exporter->exp_states &= ~EXP_EXPORTED;
3079 exporter->exp_states |= EXP_UNIXMODE;
3081 exporter->exp_states &= ~EXP_UNIXMODE;
3085 exporter->exp_states |= EXP_PWSYNC;
3087 exporter->exp_states &= ~EXP_PWSYNC;
3091 afs_NFSRootOnly = 0;
3092 exporter->exp_states |= EXP_SUBMOUNTS;
3094 afs_NFSRootOnly = 1;
3095 exporter->exp_states &= ~EXP_SUBMOUNTS;
3098 handleValue = exporter->exp_states;
3099 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3100 *aoutSize = sizeof(afs_int32);
3103 exporter->exp_states |= EXP_EXPORTED;
3105 exporter->exp_states &= ~EXP_EXPORTED;
3107 exporter->exp_states |= EXP_UNIXMODE;
3109 exporter->exp_states &= ~EXP_UNIXMODE;
3111 exporter->exp_states |= EXP_PWSYNC;
3113 exporter->exp_states &= ~EXP_PWSYNC;
3115 afs_NFSRootOnly = 0;
3116 exporter->exp_states |= EXP_SUBMOUNTS;
3118 afs_NFSRootOnly = 1;
3119 exporter->exp_states &= ~EXP_SUBMOUNTS;
3128 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3131 struct vrequest *areq;
3134 struct AFS_UCRED *acred;
3135 afs_int32 *aoutSize; /* set this */
3137 struct gaginfo *gagflags;
3139 if (!afs_osi_suser(acred))
3142 gagflags = (struct gaginfo *) ain;
3143 afs_showflags = gagflags->showflags;
3150 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3153 struct vrequest *areq;
3156 struct AFS_UCRED *acred;
3157 afs_int32 *aoutSize;
3159 struct rxparams *rxp;
3161 if (!afs_osi_suser(acred))
3164 rxp = (struct rxparams *) ain;
3166 if (rxp->rx_initReceiveWindow)
3167 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3168 if (rxp->rx_maxReceiveWindow)
3169 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3170 if (rxp->rx_initSendWindow)
3171 rx_initSendWindow = rxp->rx_initSendWindow;
3172 if (rxp->rx_maxSendWindow)
3173 rx_maxSendWindow = rxp->rx_maxSendWindow;
3174 if (rxp->rxi_nSendFrags)
3175 rxi_nSendFrags = rxp->rxi_nSendFrags;
3176 if (rxp->rxi_nRecvFrags)
3177 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3178 if (rxp->rxi_OrphanFragSize)
3179 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3180 if (rxp->rx_maxReceiveSize)
3182 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3183 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3185 if (rxp->rx_MyMaxSendSize)
3186 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3191 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3194 struct vrequest *areq;
3198 afs_int32 *aoutSize; /* set this */
3200 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3203 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3204 *aoutSize = sizeof(struct cm_initparams);
3208 #ifdef AFS_SGI65_ENV
3209 /* They took crget() from us, so fake it. */
3210 static cred_t *crget(void)
3213 cr = crdup(get_current_cred());
3214 bzero((char*)cr, sizeof(cred_t));
3215 #if CELL || CELL_PREPARE
3223 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3226 struct vrequest *areq;
3229 afs_int32 *aoutSize;
3230 struct AFS_UCRED *acred;
3232 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3233 *aoutSize=sizeof(afs_int32);
3238 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3241 struct vrequest *areq;
3244 afs_int32 *aoutSize;
3245 struct AFS_UCRED *acred;
3249 if (!afs_osi_suser(acred))
3251 if (ainSize != sizeof(afs_int32) || ain == NULL)
3253 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3254 /* if new mappings added later this will need to be changed */
3255 if (tmpval != 0 && tmpval != 1)
3262 * Create new credentials to correspond to a remote user with given
3263 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3264 * provide pioctl (and other) services to foreign clients (i.e. nfs
3265 * clients) by using this call to `become' the client.
3268 #define PIOCTL_HEADER 6
3269 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3272 afs_uint32 hostaddr;
3273 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3274 extern struct afs_exporter *exporter_find();
3275 struct afs_exporter *exporter, *outexporter;
3276 struct AFS_UCRED *newcred;
3277 struct unixuser *au;
3279 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3280 return EINVAL; /* NFS trans not supported for Ultrix */
3282 #if defined(AFS_SGIMP_ENV)
3283 osi_Assert(ISAFS_GLOCK());
3285 AFS_STATCNT(HandleClientContext);
3286 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3287 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3288 return EINVAL; /* Too small to be good */
3290 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3291 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3293 osi_FreeLargeSpace(inData);
3297 /* Extract information for remote user */
3298 hostaddr = *((afs_uint32 *)ain);
3299 ain += sizeof(hostaddr);
3300 uid = *((afs_uint32 *)ain);
3302 g0 = *((afs_uint32 *)ain);
3304 g1 = *((afs_uint32 *)ain);
3306 *com = *((afs_uint32 *)ain);
3307 ain += sizeof(afs_int32);
3308 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3311 * Of course, one must be root for most of these functions, but
3312 * we'll allow (for knfs) you to set things if the pag is 0 and
3313 * you're setting tokens or unlogging.
3316 if (!afs_osi_suser(credp)) {
3318 #ifndef AFS_SGI64_ENV
3319 /* Since SGI's suser() returns explicit failure after the call.. */
3323 /* check for acceptable opcodes for normal folks, which are, so far,
3324 * set tokens and unlog.
3326 if (i != 9 && i != 3 && i != 38 && i != 8) {
3327 osi_FreeLargeSpace(inData);
3332 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3333 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3334 osi_FreeLargeSpace(inData);
3337 * We map uid 0 to nobody to match the mapping that the nfs
3338 * server does and to ensure that the suser() calls in the afs
3339 * code fails for remote client roots.
3341 uid = afs_nobody; /* NFS_NOBODY == -2 */
3344 #ifdef AFS_AIX41_ENV
3347 newcred->cr_gid = RMTUSER_REQ;
3348 newcred->cr_groups[0] = g0;
3349 newcred->cr_groups[1] = g1;
3351 newcred->cr_ngrps = 2;
3353 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3354 newcred->cr_ngroups = 2;
3356 for (i=2; i<NGROUPS; i++)
3357 newcred->cr_groups[i] = NOGROUP;
3360 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3361 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3363 if (!(exporter = exporter_find(exporter_type))) {
3364 /* Exporter wasn't initialized or an invalid exporter type */
3368 if (exporter->exp_states & EXP_PWSYNC) {
3369 if (uid != credp->cr_uid) {
3371 return ENOEXEC; /* XXX Find a better errno XXX */
3374 newcred->cr_uid = uid; /* Only temporary */
3375 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3376 /* The client's pag is the only unique identifier for it */
3377 newcred->cr_uid = pag;
3379 if (!code && *com == PSETPAG) {
3380 /* Special case for 'setpag' */
3381 afs_uint32 pagvalue = genpag();
3383 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3385 * Note that we leave the 'outexporter' struct held so it won't
3388 au->exporter = outexporter;
3389 if (ablob->out_size >= 4) {
3390 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3392 afs_PutUser(au, WRITE_LOCK);
3393 if (code) return code;
3394 return PSETPAG; /* Special return for setpag */
3396 EXP_RELE(outexporter);
3399 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3402 /* get all interface addresses of this client */
3405 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3408 struct vrequest *areq;
3411 afs_int32 *aoutSize;
3413 struct sprefrequest *spin; /* input */
3414 struct sprefinfo *spout; /* output */
3415 struct spref *srvout; /* one output component */
3419 AFS_STATCNT(PGetCPrefs);
3420 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3421 return EIO; /* Inappropriate ioctl for device */
3423 if ( ainSize < sizeof (struct sprefrequest ))
3426 spin = (struct sprefrequest *) ain;
3427 spout = (struct sprefinfo *) aout;
3429 maxNumber = spin->num_servers; /* max addrs this time */
3430 srvout = spout->servers;
3432 ObtainReadLock(&afs_xinterface);
3434 /* copy out the client interface information from the
3435 ** kernel data structure "interface" to the output buffer
3437 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3438 && ( j< maxNumber) ; i++, j++, srvout++)
3439 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3441 spout->num_servers = j;
3442 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3444 if ( i >= afs_cb_interface.numberOfInterfaces )
3445 spout->next_offset = 0; /* start from beginning again */
3447 spout->next_offset = spin->offset + j;
3449 ReleaseReadLock(&afs_xinterface);
3454 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3457 struct vrequest *areq;
3460 afs_int32 *aoutSize;
3462 struct setspref *sin;
3465 AFS_STATCNT(PSetCPrefs);
3466 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3467 return EIO; /* Inappropriate ioctl for device */
3469 sin = (struct setspref *)ain;
3471 if ( ainSize < sizeof(struct setspref) )
3473 #if 0 /* num_servers is unsigned */
3474 if ( sin->num_servers < 0 )
3477 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3480 ObtainWriteLock(&afs_xinterface, 412);
3481 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3482 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3483 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3485 ReleaseWriteLock(&afs_xinterface);
3489 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3492 struct vrequest *areq;
3495 afs_int32 *aoutSize;
3496 struct AFS_UCRED *acred; {
3497 register afs_int32 code;
3498 register struct vcache *tvc;
3499 register struct dcache *tdc;
3500 struct VenusFid tfid;
3502 afs_int32 offset, len, hasatsys=0;
3504 AFS_STATCNT(PFlushMount);
3505 if (!avc) return EINVAL;
3506 code = afs_VerifyVCache(avc, areq);
3507 if (code) return code;
3508 if (vType(avc) != VDIR) {
3511 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3512 if (!tdc) return ENOENT;
3513 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3514 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3519 tfid.Cell = avc->fid.Cell;
3520 tfid.Fid.Volume = avc->fid.Fid.Volume;
3521 afs_PutDCache(tdc); /* we're done with the data */
3522 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3523 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3525 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3532 if (vType(tvc) != VLNK) {
3533 afs_PutVCache(tvc, WRITE_LOCK);
3537 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3538 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3540 ObtainWriteLock(&tvc->lock,645);
3541 ObtainWriteLock(&afs_xcbhash, 646);
3542 afs_DequeueCallback(tvc);
3543 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3544 ReleaseWriteLock(&afs_xcbhash);
3545 /* now find the disk cache entries */
3546 afs_TryToSmush(tvc, acred, 1);
3547 osi_dnlc_purgedp(tvc);
3548 afs_symhint_inval(tvc);
3549 if (tvc->linkData && !(tvc->states & CCore)) {
3550 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3551 tvc->linkData = (char *) 0;
3553 ReleaseWriteLock(&tvc->lock);
3554 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3555 afs_BozonUnlock(&tvc->pvnLock, tvc);
3557 afs_PutVCache(tvc, WRITE_LOCK);
3559 if (hasatsys) osi_FreeLargeSpace(bufp);
3563 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3566 struct vrequest *areq;
3569 afs_int32 *aoutSize;
3570 struct AFS_UCRED *acred;
3575 if (!afs_osi_suser(acred)) {
3579 if (ainSize != sizeof(afs_int32)) {
3583 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3584 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3588 if (flags & AFSCALL_RXSTATS_ENABLE) {
3589 rx_enableProcessRPCStats();
3591 if (flags & AFSCALL_RXSTATS_DISABLE) {
3592 rx_disableProcessRPCStats();
3594 if (flags & AFSCALL_RXSTATS_CLEAR) {
3595 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3603 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3606 struct vrequest *areq;
3609 afs_int32 *aoutSize;
3610 struct AFS_UCRED *acred;
3615 if (!afs_osi_suser(acred)) {
3619 if (ainSize != sizeof(afs_int32)) {
3623 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3624 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3628 if (flags & AFSCALL_RXSTATS_ENABLE) {
3629 rx_enablePeerRPCStats();
3631 if (flags & AFSCALL_RXSTATS_DISABLE) {
3632 rx_disablePeerRPCStats();
3634 if (flags & AFSCALL_RXSTATS_CLEAR) {
3635 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3642 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3645 struct vrequest *areq;
3648 afs_int32 *aoutSize; /* set this */
3650 register afs_int32 code, code1;
3653 struct rx_call *tcall;
3654 struct AFSVolSync tsync;
3655 struct AFSFetchStatus OutStatus;
3656 struct AFSCallBack CallBack;
3657 struct VenusFid tfid;
3662 AFS_STATCNT(PSetAcl);
3666 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3667 Fid = (struct AFSFid *) ain;
3669 Fid = &avc->fid.Fid;
3670 tfid.Cell = avc->fid.Cell;
3671 tfid.Fid.Volume = Fid->Volume;
3672 tfid.Fid.Vnode = Fid->Vnode;
3673 tfid.Fid.Unique = Fid->Unique;
3675 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3678 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3679 ICL_TYPE_POINTER, tvc,
3680 ICL_TYPE_FID, &tfid,
3681 ICL_TYPE_FID, &avc->fid);
3684 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3685 ICL_TYPE_POINTER, tvc,
3686 ICL_TYPE_FID, &tfid,
3687 ICL_TYPE_FID, &tvc->fid);
3690 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3693 #ifdef RX_ENABLE_LOCKS
3695 #endif /* RX_ENABLE_LOCKS */
3696 tcall = rx_NewCall(tc->id);
3697 code = StartRXAFS_FetchData(tcall,
3698 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3700 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3701 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3703 code1 = rx_EndCall(tcall, code);
3704 #ifdef RX_ENABLE_LOCKS
3706 #endif /* RX_ENABLE_LOCKS */
3710 (afs_Analyze(tc, code, &tvc->fid, areq,
3711 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3713 /* This call is done only to have the callback things handled correctly */
3714 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3715 afs_PutVCache(tvc, WRITE_LOCK);
3718 *aoutSize = sizeof(afs_int32);
3723 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3726 struct vrequest *areq;
3729 afs_int32 *aoutSize; /* set this */
3731 register afs_int32 code;
3734 struct ResidencyCmdInputs *Inputs;
3735 struct ResidencyCmdOutputs *Outputs;
3736 struct VenusFid tfid;
3739 Inputs = (struct ResidencyCmdInputs *) ain;
3740 Outputs = (struct ResidencyCmdOutputs *) aout;
3741 if (!avc) return EINVAL;
3742 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3746 Fid = &avc->fid.Fid;
3748 tfid.Cell = avc->fid.Cell;
3749 tfid.Fid.Volume = Fid->Volume;
3750 tfid.Fid.Vnode = Fid->Vnode;
3751 tfid.Fid.Unique = Fid->Unique;
3753 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3755 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3756 ICL_TYPE_POINTER, tvc,
3757 ICL_TYPE_INT32, Inputs->command,
3758 ICL_TYPE_FID, &tfid);
3762 if (Inputs->command) {
3764 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3766 #ifdef RX_ENABLE_LOCKS
3768 #endif /* RX_ENABLE_LOCKS */
3769 code = RXAFS_ResidencyCmd(tc->id, Fid,
3771 (struct ResidencyCmdOutputs *) aout);
3772 #ifdef RX_ENABLE_LOCKS
3774 #endif /* RX_ENABLE_LOCKS */
3778 (afs_Analyze(tc, code, &tvc->fid, areq,
3779 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3781 /* This call is done to have the callback things handled correctly */
3782 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3783 } else { /* just a status request, return also link data */
3785 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3786 Outputs->chars[0] = 0;
3787 if (vType(tvc) == VLNK) {
3788 ObtainWriteLock(&tvc->lock,555);
3789 if (afs_HandleLink(tvc, areq) == 0)
3790 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3791 ReleaseWriteLock(&tvc->lock);
3795 afs_PutVCache(tvc, WRITE_LOCK);
3798 *aoutSize = sizeof(struct ResidencyCmdOutputs);