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);
1850 ReleaseWriteLock(&afs_xuser);
1854 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1857 struct vrequest *areq;
1860 afs_int32 *aoutSize; /* set this */ {
1861 afs_int32 newHostAddr;
1862 afs_int32 oldHostAddr;
1864 AFS_STATCNT(PMariner);
1866 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1868 oldHostAddr = 0xffffffff; /* disabled */
1870 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1871 if (newHostAddr == 0xffffffff) {
1872 /* disable mariner operations */
1875 else if (newHostAddr) {
1877 afs_marinerHost = newHostAddr;
1879 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1880 *aoutSize = sizeof(afs_int32);
1884 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1887 struct vrequest *areq;
1890 afs_int32 *aoutSize; /* set this */
1891 struct AFS_UCRED *acred;
1893 register char *cp = 0;
1895 register struct server *ts;
1896 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1898 struct chservinfo *pcheck;
1900 AFS_STATCNT(PCheckServers);
1902 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1903 return EIO; /* Inappropriate ioctl for device */
1905 if (*lp == 0x12345678) { /* For afs3.3 version */
1906 pcheck=(struct chservinfo *)ain;
1907 if (pcheck->tinterval >= 0) {
1909 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1910 *aoutSize = sizeof(afs_int32);
1911 if (pcheck->tinterval > 0) {
1912 if (!afs_osi_suser(acred))
1914 PROBE_INTERVAL=pcheck->tinterval;
1920 temp=pcheck->tflags;
1921 cp = pcheck->tbuffer;
1922 } else { /* For pre afs3.3 versions */
1923 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1924 cp = ain+sizeof(afs_int32);
1925 if (ainSize > sizeof(afs_int32))
1930 * 1: fast check, don't contact servers.
1931 * 2: local cell only.
1934 /* have cell name, too */
1935 cellp = afs_GetCellByName(cp, READ_LOCK);
1936 if (!cellp) return ENOENT;
1938 else cellp = (struct cell *) 0;
1939 if (!cellp && (temp & 2)) {
1940 /* use local cell */
1941 cellp = afs_GetCell(1, READ_LOCK);
1943 if (!(temp & 1)) { /* if not fast, call server checker routine */
1944 afs_CheckServers(1, cellp); /* check down servers */
1945 afs_CheckServers(0, cellp); /* check up servers */
1947 /* now return the current down server list */
1949 ObtainReadLock(&afs_xserver);
1950 for(i=0;i<NSERVERS;i++) {
1951 for(ts = afs_servers[i]; ts; ts=ts->next) {
1952 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1953 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1954 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1955 cp += sizeof(afs_int32);
1959 ReleaseReadLock(&afs_xserver);
1960 if (cellp) afs_PutCell(cellp, READ_LOCK);
1961 *aoutSize = cp - aout;
1965 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1968 struct vrequest *areq;
1971 afs_int32 *aoutSize; /* set this */ {
1972 AFS_STATCNT(PCheckVolNames);
1973 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1974 return EIO; /* Inappropriate ioctl for device */
1976 afs_CheckRootVolume();
1977 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1978 AFS_VOLCHECK_EXPIRED |
1980 AFS_VOLCHECK_MTPTS);
1984 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1987 struct vrequest *areq;
1990 afs_int32 *aoutSize; /* set this */ {
1994 struct unixuser *tu;
1996 extern afs_rwlock_t afs_xsrvAddr;
1998 AFS_STATCNT(PCheckAuth);
1999 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2000 return EIO; /* Inappropriate ioctl for device */
2003 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2004 if (!tu) retValue = EACCES;
2006 /* we have a user */
2007 ObtainReadLock(&afs_xsrvAddr);
2008 ObtainReadLock(&afs_xconn);
2010 /* any tokens set? */
2011 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
2012 /* all connections in cell 1 working? */
2013 for(i=0;i<NSERVERS;i++) {
2014 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
2015 for (tc = sa->conns; tc; tc=tc->next) {
2016 if (tc->user == tu && (tu->states & UTokensBad))
2021 ReleaseReadLock(&afs_xsrvAddr);
2022 ReleaseReadLock(&afs_xconn);
2023 afs_PutUser(tu, READ_LOCK);
2025 bcopy((char *)&retValue, aout, sizeof(afs_int32));
2026 *aoutSize = sizeof(afs_int32);
2030 static Prefetch(apath, adata, afollow, acred)
2032 struct afs_ioctl *adata;
2034 struct AFS_UCRED *acred;
2037 register afs_int32 code;
2038 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV)
2044 AFS_STATCNT(Prefetch);
2045 if (!apath) return EINVAL;
2046 tp = osi_AllocLargeSpace(1024);
2047 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2049 osi_FreeLargeSpace(tp);
2052 if (afs_BBusy()) { /* do this as late as possible */
2053 osi_FreeLargeSpace(tp);
2054 return EWOULDBLOCK; /* pretty close */
2056 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
2060 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
2063 struct vrequest *areq;
2066 afs_int32 *aoutSize; /* set this */ {
2067 register struct volume *tvp;
2068 register struct server *ts;
2069 register afs_int32 i;
2072 AFS_STATCNT(PFindVolume);
2073 if (!avc) return EINVAL;
2074 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2077 for(i=0;i<MAXHOSTS;i++) {
2078 ts = tvp->serverHost[i];
2080 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2081 cp += sizeof(afs_int32);
2084 /* still room for terminating NULL, add it on */
2085 ainSize = 0; /* reuse vbl */
2086 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2087 cp += sizeof(afs_int32);
2089 *aoutSize = cp - aout;
2090 afs_PutVolume(tvp, READ_LOCK);
2096 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2099 struct vrequest *areq;
2102 afs_int32 *aoutSize; /* set this */ {
2103 register afs_int32 code;
2106 AFS_STATCNT(PViceAccess);
2107 if (!avc) return EINVAL;
2108 code = afs_VerifyVCache(avc, areq);
2109 if (code) return code;
2110 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2111 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2116 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2119 struct vrequest *areq;
2122 afs_int32 *aoutSize; /* set this */
2123 struct AFS_UCRED *acred;
2128 AFS_STATCNT(PSetCacheSize);
2129 if (!afs_osi_suser(acred))
2131 /* too many things are setup initially in mem cache version */
2132 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2133 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2134 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2136 extern u_int afs_min_cache;
2137 if (newValue < afs_min_cache)
2138 afs_cacheBlocks = afs_min_cache;
2140 afs_cacheBlocks = newValue;
2142 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2143 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2144 afs_MaybeWakeupTruncateDaemon();
2145 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2146 afs_osi_Wait(1000, 0, 0);
2147 afs_MaybeWakeupTruncateDaemon();
2152 #define MAXGCSTATS 16
2153 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2156 struct vrequest *areq;
2159 afs_int32 *aoutSize; /* set this */ {
2160 afs_int32 results[MAXGCSTATS];
2162 AFS_STATCNT(PGetCacheSize);
2163 bzero((char *)results, sizeof(results));
2164 results[0] = afs_cacheBlocks;
2165 results[1] = afs_blocksUsed;
2166 bcopy((char *)results, aout, sizeof(results));
2167 *aoutSize = sizeof(results);
2171 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2174 struct vrequest *areq;
2177 afs_int32 *aoutSize; /* set this */ {
2178 register struct conn *tc;
2179 register afs_int32 code;
2180 struct AFSCallBack CallBacks_Array[1];
2181 struct AFSCBFids theFids;
2182 struct AFSCBs theCBs;
2185 AFS_STATCNT(PRemoveCallBack);
2186 if (!avc) return EINVAL;
2187 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2188 ObtainWriteLock(&avc->lock,229);
2189 theFids.AFSCBFids_len = 1;
2190 theCBs.AFSCBs_len = 1;
2191 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2192 theCBs.AFSCBs_val = CallBacks_Array;
2193 CallBacks_Array[0].CallBackType = CB_DROPPED;
2194 if (avc->callback) {
2196 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2198 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2199 #ifdef RX_ENABLE_LOCKS
2201 #endif /* RX_ENABLE_LOCKS */
2202 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2203 #ifdef RX_ENABLE_LOCKS
2205 #endif /* RX_ENABLE_LOCKS */
2208 /* don't set code on failure since we wouldn't use it */
2210 (afs_Analyze(tc, code, &avc->fid, areq,
2211 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2212 SHARED_LOCK, (struct cell *)0));
2214 ObtainWriteLock(&afs_xcbhash, 457);
2215 afs_DequeueCallback(avc);
2217 avc->states &= ~(CStatd | CUnique);
2218 ReleaseWriteLock(&afs_xcbhash);
2219 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2220 osi_dnlc_purgedp(avc);
2222 ReleaseWriteLock(&avc->lock);
2226 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2229 struct vrequest *areq;
2233 struct AFS_UCRED *acred;
2234 afs_int32 *aoutSize; /* set this */ {
2235 /* create a new cell */
2236 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2237 register struct cell *tcell;
2238 char *newcell=0, *linkedcell=0, *tp= ain;
2239 register afs_int32 code, linkedstate=0, ls;
2240 u_short fsport = 0, vlport = 0;
2243 AFS_STATCNT(PNewCell);
2244 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2245 return EIO; /* Inappropriate ioctl for device */
2247 if (!afs_osi_suser(acred))
2250 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2251 tp += sizeof(afs_int32);
2252 if (magic != 0x12345678)
2255 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2256 * server addresses while the 3.5 fs newcell command passes
2257 * MAXHOSTS. To figure out which is which, check if the cellname
2260 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2261 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2263 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2264 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2265 tp += (scount * sizeof(afs_int32));
2267 lp = (afs_int32 *)tp;
2270 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2271 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2272 tp += (3 * sizeof(afs_int32));
2274 if ((ls = *lp) & 1) {
2275 linkedcell = tp + strlen(newcell)+1;
2276 linkedstate |= CLinkedCell;
2279 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2280 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
2284 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2287 struct vrequest *areq;
2290 afs_int32 *aoutSize; /* set this */ {
2291 afs_int32 whichCell;
2292 register struct cell *tcell=0;
2293 register afs_int32 i;
2294 register char *cp, *tp = ain;
2295 register struct afs_q *cq, *tq;
2297 AFS_STATCNT(PListCells);
2298 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2299 return EIO; /* Inappropriate ioctl for device */
2301 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2302 tp += sizeof(afs_int32);
2303 ObtainReadLock(&afs_xcell);
2304 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2305 tcell = QTOC(cq); tq = QNext(cq);
2306 if (whichCell == 0) break;
2307 if (tq == &CellLRU) tcell = 0;
2312 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2313 for(i=0;i<MAXCELLHOSTS;i++) {
2314 if (tcell->cellHosts[i] == 0) break;
2315 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2316 cp += sizeof(afs_int32);
2318 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2319 strcpy(cp, tcell->cellName);
2320 cp += strlen(tcell->cellName)+1;
2321 *aoutSize = cp - aout;
2323 ReleaseReadLock(&afs_xcell);
2324 if (tcell) return 0;
2328 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2331 struct vrequest *areq;
2335 afs_int32 *aoutSize; /* set this */ {
2336 register afs_int32 code;
2338 afs_int32 offset, len, hasatsys = 0;
2339 register struct conn *tc;
2340 register struct dcache *tdc;
2341 register struct vcache *tvc;
2342 struct AFSFetchStatus OutDirStatus;
2343 struct VenusFid tfid;
2344 struct AFSVolSync tsync;
2348 /* "ain" is the name of the file in this dir to remove */
2350 AFS_STATCNT(PRemoveMount);
2351 if (!avc) return EINVAL;
2352 code = afs_VerifyVCache(avc, areq);
2353 if (code) return code;
2354 if (vType(avc) != VDIR) return ENOTDIR;
2356 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2357 if (!tdc) return ENOENT;
2358 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2359 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2364 tfid.Cell = avc->fid.Cell;
2365 tfid.Fid.Volume = avc->fid.Fid.Volume;
2366 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2367 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2369 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2370 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2377 if (vType(tvc) != VLNK) {
2379 afs_PutVCache(tvc, WRITE_LOCK);
2383 ObtainWriteLock(&tvc->lock,230);
2384 code = afs_HandleLink(tvc, areq);
2386 if (tvc->linkData) {
2387 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2392 ReleaseWriteLock(&tvc->lock);
2393 osi_dnlc_purgedp(tvc);
2394 afs_PutVCache(tvc, WRITE_LOCK);
2399 ObtainWriteLock(&avc->lock,231);
2400 osi_dnlc_remove(avc, bufp, tvc);
2402 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2404 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2405 #ifdef RX_ENABLE_LOCKS
2407 #endif /* RX_ENABLE_LOCKS */
2408 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2409 bufp, &OutDirStatus, &tsync);
2410 #ifdef RX_ENABLE_LOCKS
2412 #endif /* RX_ENABLE_LOCKS */
2417 (afs_Analyze(tc, code, &avc->fid, areq,
2418 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2419 SHARED_LOCK, (struct cell *)0));
2422 if (tdc) afs_PutDCache(tdc);
2423 ReleaseWriteLock(&avc->lock);
2427 /* we have the thing in the cache */
2428 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2429 /* we can do it locally */
2430 code = afs_dir_Delete(&tdc->f.inode, bufp);
2432 ZapDCE(tdc); /* surprise error -- invalid value */
2433 DZap(&tdc->f.inode);
2436 afs_PutDCache(tdc); /* drop ref count */
2438 avc->states &= ~CUnique; /* For the dfs xlator */
2439 ReleaseWriteLock(&avc->lock);
2442 if (hasatsys) osi_FreeLargeSpace(bufp);
2446 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2449 struct vrequest *areq;
2453 struct AFS_UCRED *acred;
2454 afs_int32 *aoutSize; /* set this */ {
2455 return EINVAL; /* OBSOLETE */
2458 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2461 struct vrequest *areq;
2464 afs_int32 *aoutSize; /* set this */ {
2465 register struct cell *tcell;
2468 AFS_STATCNT(PGetCellStatus);
2469 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2470 return EIO; /* Inappropriate ioctl for device */
2472 tcell = afs_GetCellByName(ain, READ_LOCK);
2473 if (!tcell) return ENOENT;
2474 temp = tcell->states;
2475 afs_PutCell(tcell, READ_LOCK);
2476 bcopy((char *)&temp, aout, sizeof(afs_int32));
2477 *aoutSize = sizeof(afs_int32);
2481 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2484 struct vrequest *areq;
2487 struct AFS_UCRED *acred;
2488 afs_int32 *aoutSize; /* set this */ {
2489 register struct cell *tcell;
2492 if (!afs_osi_suser(acred))
2494 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2495 return EIO; /* Inappropriate ioctl for device */
2497 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2498 if (!tcell) return ENOENT;
2499 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2501 tcell->states |= CNoSUID;
2503 tcell->states &= ~CNoSUID;
2504 afs_PutCell(tcell, WRITE_LOCK);
2508 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2511 struct vrequest *areq;
2514 afs_int32 *aoutSize; /* set this */
2515 struct AFS_UCRED *acred;
2517 extern struct volume *afs_volumes[NVOLS];
2518 register afs_int32 i;
2519 register struct dcache *tdc;
2520 register struct vcache *tvc;
2521 register struct volume *tv;
2522 afs_int32 cell, volume;
2524 AFS_STATCNT(PFlushVolumeData);
2527 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2528 return EIO; /* Inappropriate ioctl for device */
2530 volume = avc->fid.Fid.Volume; /* who to zap */
2531 cell = avc->fid.Cell;
2534 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2535 * the vcaches associated with the volume.
2537 ObtainReadLock(&afs_xvcache);
2538 for(i = 0; i < VCSIZE; i++) {
2539 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2540 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2541 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2542 VN_HOLD((struct vnode *)tvc);
2544 #if defined(AFS_DARWIN_ENV)
2550 ReleaseReadLock(&afs_xvcache);
2551 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2552 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2554 ObtainWriteLock(&tvc->lock,232);
2556 ObtainWriteLock(&afs_xcbhash, 458);
2557 afs_DequeueCallback(tvc);
2558 tvc->states &= ~(CStatd | CDirty);
2559 ReleaseWriteLock(&afs_xcbhash);
2560 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2561 osi_dnlc_purgedp(tvc);
2562 afs_TryToSmush(tvc, acred, 1);
2563 ReleaseWriteLock(&tvc->lock);
2564 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2565 afs_BozonUnlock(&tvc->pvnLock, tvc);
2567 ObtainReadLock(&afs_xvcache);
2568 /* our tvc ptr is still good until now */
2573 ReleaseReadLock(&afs_xvcache);
2576 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2577 for(i=0;i<afs_cacheFiles;i++) {
2578 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2579 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2580 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2581 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2582 if (! (afs_indexFlags[i] & IFDataMod)) {
2583 /* if the file is modified, but has a ref cnt of only 1, then
2584 someone probably has the file open and is writing into it.
2585 Better to skip flushing such a file, it will be brought back
2586 immediately on the next write anyway.
2588 If we *must* flush, then this code has to be rearranged to call
2589 afs_storeAllSegments() first */
2590 afs_FlushDCache(tdc);
2594 tdc->refCount--; /* bumped by getdslot */
2596 MReleaseWriteLock(&afs_xdcache);
2598 ObtainReadLock(&afs_xvolume);
2599 for (i=0;i<NVOLS;i++) {
2600 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2601 if (tv->volume == volume) {
2602 afs_ResetVolumeInfo(tv);
2607 ReleaseReadLock(&afs_xvolume);
2609 /* probably, a user is doing this, probably, because things are screwed up.
2610 * maybe it's the dnlc's fault? */
2617 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2620 struct vrequest *areq;
2623 afs_int32 *aoutSize; /* set this */ {
2624 register afs_int32 code;
2625 struct vcxstat stat;
2628 /* AFS_STATCNT(PGetVnodeXStatus); */
2629 if (!avc) return EINVAL;
2630 code = afs_VerifyVCache(avc, areq);
2631 if (code) return code;
2632 if (vType(avc) == VDIR)
2633 mode = PRSFS_LOOKUP;
2636 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2638 stat.fid = avc->fid;
2639 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2640 stat.lock = avc->lock;
2641 stat.parentVnode = avc->parentVnode;
2642 stat.parentUnique = avc->parentUnique;
2643 hset(stat.flushDV, avc->flushDV);
2644 hset(stat.mapDV, avc->mapDV);
2645 stat.truncPos = avc->truncPos;
2646 { /* just grab the first two - won't break anything... */
2647 struct axscache *ac;
2649 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2650 stat.randomUid[i] = ac->uid;
2651 stat.randomAccess[i] = ac->axess;
2654 stat.callback = afs_data_pointer_to_int32(avc->callback);
2655 stat.cbExpires = avc->cbExpires;
2656 stat.anyAccess = avc->anyAccess;
2657 stat.opens = avc->opens;
2658 stat.execsOrWriters = avc->execsOrWriters;
2659 stat.flockCount = avc->flockCount;
2660 stat.mvstat = avc->mvstat;
2661 stat.states = avc->states;
2662 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2663 *aoutSize = sizeof(struct vcxstat);
2668 /* We require root for local sysname changes, but not for remote */
2669 /* (since we don't really believe remote uids anyway) */
2670 /* outname[] shouldn't really be needed- this is left as an excercise */
2671 /* for the reader. */
2673 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2676 struct vrequest *areq;
2679 afs_int32 *aoutSize; /* set this */
2680 register struct AFS_UCRED *acred;
2682 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2683 int setsysname, foundname=0;
2684 register struct afs_exporter *exporter;
2685 extern struct unixuser *afs_FindUser();
2686 extern char *afs_sysname;
2687 register struct unixuser *au;
2688 register afs_int32 pag, error;
2692 AFS_STATCNT(PSetSysName);
2693 if (!afs_globalVFS) {
2694 /* Afsd is NOT running; disable it */
2695 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV)
2698 return (setuerror(EINVAL), EINVAL);
2701 bzero(inname, MAXSYSNAME);
2702 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2703 ain += sizeof(afs_int32);
2708 bcopy(ain, inname, t+1); /* include terminating null */
2711 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2712 pag = PagInCred(acred);
2714 return EINVAL; /* Better than panicing */
2716 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2717 return EINVAL; /* Better than panicing */
2719 if (!(exporter = au->exporter)) {
2720 afs_PutUser(au, READ_LOCK);
2721 return EINVAL; /* Better than panicing */
2723 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2725 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2727 afs_PutUser(au, READ_LOCK);
2732 afs_PutUser(au, READ_LOCK);
2734 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2736 strcpy(outname, afs_sysname);
2739 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2741 strcpy(afs_sysname, inname);
2746 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2747 cp += sizeof(afs_int32);
2749 strcpy(cp, outname);
2750 cp += strlen(outname)+1;
2752 *aoutSize = cp - aout;
2757 /* sequential search through the list of touched cells is not a good
2758 * long-term solution here. For small n, though, it should be just
2759 * fine. Should consider special-casing the local cell for large n.
2760 * Likewise for PSetSPrefs.
2762 static void ReSortCells(s,l, vlonly)
2763 int s; /* number of ids in array l[] -- NOT index of last id */
2764 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2765 int vlonly; /* sort vl servers or file servers?*/
2767 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2776 tcell = afs_GetCell(l[k], WRITE_LOCK);
2777 if (!tcell) continue;
2778 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2779 afs_PutCell(tcell, WRITE_LOCK);
2784 ObtainReadLock(&afs_xvolume);
2785 for (i= 0; i< NVOLS; i++) {
2786 for (j=afs_volumes[i];j;j=j->next) {
2788 if (j->cell == l[k]) {
2789 ObtainWriteLock(&j->lock,233);
2790 afs_SortServers(j->serverHost, MAXHOSTS);
2791 ReleaseWriteLock(&j->lock);
2796 ReleaseReadLock(&afs_xvolume);
2801 static int afs_setsprefs(sp, num, vlonly)
2804 unsigned int vlonly;
2807 int i,j,k,matches,touchedSize;
2808 struct server *srvr = NULL;
2809 afs_int32 touched[34];
2813 for (k=0; k < num; sp++, k++) {
2815 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2818 ObtainReadLock(&afs_xserver);
2820 i = SHash(sp->host.s_addr);
2821 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2822 if (sa->sa_ip == sp->host.s_addr) {
2824 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2825 || (sa->sa_portal == AFS_FSPORT);
2826 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2833 if (sa && matches) { /* found one! */
2835 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2837 sa->sa_iprank = sp->rank + afs_randomMod15();
2838 afs_SortOneServer(sa->server);
2841 /* if we don't know yet what cell it's in, this is moot */
2842 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2843 /* is it in our list of touched cells ? */ ;
2844 if (j < 0) { /* no, it's not */
2845 touched[touchedSize++] = srvr->cell->cell;
2846 if (touchedSize >= 32) { /* watch for ovrflow */
2847 ReleaseReadLock(&afs_xserver);
2848 ReSortCells(touchedSize, touched, vlonly);
2850 ObtainReadLock(&afs_xserver);
2856 ReleaseReadLock(&afs_xserver);
2857 /* if we didn't find one, start to create one. */
2858 /* Note that it doesn't have a cell yet... */
2860 afs_uint32 temp = sp->host.s_addr;
2861 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2862 WRITE_LOCK, (afsUUID *)0,0);
2863 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2864 afs_PutServer(srvr, WRITE_LOCK);
2866 } /* for all cited preferences */
2868 ReSortCells(touchedSize, touched, vlonly);
2872 /* Note that this may only be performed by the local root user.
2875 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2878 struct vrequest *areq;
2881 struct AFS_UCRED *acred;
2882 afs_int32 *aoutSize;
2884 struct setspref *ssp;
2885 AFS_STATCNT(PSetSPrefs);
2887 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2888 return EIO; /* Inappropriate ioctl for device */
2890 if (!afs_osi_suser(acred))
2893 if (ainSize < sizeof(struct setspref))
2896 ssp = (struct setspref *)ain;
2897 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2900 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2901 (ssp->flags & DBservers));
2906 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2909 struct vrequest *areq;
2912 struct AFS_UCRED *acred;
2913 afs_int32 *aoutSize;
2916 AFS_STATCNT(PSetSPrefs);
2917 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2918 return EIO; /* Inappropriate ioctl for device */
2921 if (!afs_osi_suser(acred))
2924 sp = (struct spref *)ain;
2925 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2929 /* some notes on the following code...
2930 * in the hash table of server structs, all servers with the same IP address
2931 * will be on the same overflow chain.
2932 * This could be sped slightly in some circumstances by having it cache the
2933 * immediately previous slot in the hash table and some supporting information
2934 * Only reports file servers now.
2937 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2940 struct vrequest *areq;
2943 afs_int32 *aoutSize;
2945 struct sprefrequest *spin; /* input */
2946 struct sprefinfo *spout; /* output */
2947 struct spref *srvout; /* one output component */
2948 int i,j; /* counters for hash table traversal */
2949 struct server *srvr; /* one of CM's server structs */
2952 int vlonly; /* just return vlservers ? */
2955 AFS_STATCNT(PGetSPrefs);
2956 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2957 return EIO; /* Inappropriate ioctl for device */
2960 if (ainSize < sizeof (struct sprefrequest_33)) {
2964 spin = ((struct sprefrequest *) ain);
2967 if (ainSize > sizeof (struct sprefrequest_33)) {
2968 vlonly = (spin->flags & DBservers);
2972 /* struct sprefinfo includes 1 server struct... that size gets added
2973 * in during the loop that follows.
2975 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2976 spout = (struct sprefinfo *) aout;
2977 spout->next_offset = spin->offset;
2978 spout->num_servers = 0;
2979 srvout = spout->servers;
2981 ObtainReadLock(&afs_xserver);
2982 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2983 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2984 if (spin->offset > (unsigned short)i) {
2985 continue; /* catch up to where we left off */
2987 spout->next_offset++;
2990 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2991 || (sa->sa_portal == AFS_FSPORT);
2993 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2994 /* only report ranks for vl servers */
2998 srvout->host.s_addr = sa->sa_ip;
2999 srvout->rank = sa->sa_iprank;
3000 *aoutSize += sizeof(struct spref);
3001 spout->num_servers++;
3004 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3005 ReleaseReadLock(&afs_xserver); /* no more room! */
3010 ReleaseReadLock(&afs_xserver);
3012 spout->next_offset = 0; /* start over from the beginning next time */
3016 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3017 int afs_NFSRootOnly = 1;
3018 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3021 struct vrequest *areq;
3024 afs_int32 *aoutSize; /* set this */
3025 struct AFS_UCRED *acred;
3027 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
3028 extern struct afs_exporter *exporter_find();
3029 register struct afs_exporter *exporter;
3031 AFS_STATCNT(PExportAfs);
3032 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
3033 type = handleValue >> 24;
3038 exporter = exporter_find(type);
3040 export = handleValue & 3;
3041 changestate = handleValue & 0xff;
3042 smounts = (handleValue >> 2) & 3;
3043 pwsync = (handleValue >> 4) & 3;
3044 convmode = (handleValue >> 6) & 3;
3046 changestate = (handleValue >> 16) & 0x1;
3047 convmode = (handleValue >> 16) & 0x2;
3048 pwsync = (handleValue >> 16) & 0x4;
3049 smounts = (handleValue >> 16) & 0x8;
3050 export = handleValue & 0xff;
3053 /* Failed finding desired exporter; */
3057 handleValue = exporter->exp_states;
3058 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3059 *aoutSize = sizeof(afs_int32);
3061 if (!afs_osi_suser(acred))
3062 return EACCES; /* Only superuser can do this */
3066 exporter->exp_states |= EXP_EXPORTED;
3068 exporter->exp_states &= ~EXP_EXPORTED;
3072 exporter->exp_states |= EXP_UNIXMODE;
3074 exporter->exp_states &= ~EXP_UNIXMODE;
3078 exporter->exp_states |= EXP_PWSYNC;
3080 exporter->exp_states &= ~EXP_PWSYNC;
3084 afs_NFSRootOnly = 0;
3085 exporter->exp_states |= EXP_SUBMOUNTS;
3087 afs_NFSRootOnly = 1;
3088 exporter->exp_states &= ~EXP_SUBMOUNTS;
3091 handleValue = exporter->exp_states;
3092 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3093 *aoutSize = sizeof(afs_int32);
3096 exporter->exp_states |= EXP_EXPORTED;
3098 exporter->exp_states &= ~EXP_EXPORTED;
3100 exporter->exp_states |= EXP_UNIXMODE;
3102 exporter->exp_states &= ~EXP_UNIXMODE;
3104 exporter->exp_states |= EXP_PWSYNC;
3106 exporter->exp_states &= ~EXP_PWSYNC;
3108 afs_NFSRootOnly = 0;
3109 exporter->exp_states |= EXP_SUBMOUNTS;
3111 afs_NFSRootOnly = 1;
3112 exporter->exp_states &= ~EXP_SUBMOUNTS;
3121 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3124 struct vrequest *areq;
3127 struct AFS_UCRED *acred;
3128 afs_int32 *aoutSize; /* set this */
3130 struct gaginfo *gagflags;
3132 if (!afs_osi_suser(acred))
3135 gagflags = (struct gaginfo *) ain;
3136 afs_showflags = gagflags->showflags;
3143 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3146 struct vrequest *areq;
3149 struct AFS_UCRED *acred;
3150 afs_int32 *aoutSize;
3152 struct rxparams *rxp;
3154 if (!afs_osi_suser(acred))
3157 rxp = (struct rxparams *) ain;
3159 if (rxp->rx_initReceiveWindow)
3160 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3161 if (rxp->rx_maxReceiveWindow)
3162 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3163 if (rxp->rx_initSendWindow)
3164 rx_initSendWindow = rxp->rx_initSendWindow;
3165 if (rxp->rx_maxSendWindow)
3166 rx_maxSendWindow = rxp->rx_maxSendWindow;
3167 if (rxp->rxi_nSendFrags)
3168 rxi_nSendFrags = rxp->rxi_nSendFrags;
3169 if (rxp->rxi_nRecvFrags)
3170 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3171 if (rxp->rxi_OrphanFragSize)
3172 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3173 if (rxp->rx_maxReceiveSize)
3175 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3176 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3178 if (rxp->rx_MyMaxSendSize)
3179 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3184 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3187 struct vrequest *areq;
3191 afs_int32 *aoutSize; /* set this */
3193 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3196 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3197 *aoutSize = sizeof(struct cm_initparams);
3201 #ifdef AFS_SGI65_ENV
3202 /* They took crget() from us, so fake it. */
3203 static cred_t *crget(void)
3206 cr = crdup(get_current_cred());
3207 bzero((char*)cr, sizeof(cred_t));
3208 #if CELL || CELL_PREPARE
3216 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3219 struct vrequest *areq;
3222 afs_int32 *aoutSize;
3223 struct AFS_UCRED *acred;
3225 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3226 *aoutSize=sizeof(afs_int32);
3231 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3234 struct vrequest *areq;
3237 afs_int32 *aoutSize;
3238 struct AFS_UCRED *acred;
3242 if (!afs_osi_suser(acred))
3244 if (ainSize != sizeof(afs_int32) || ain == NULL)
3246 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3247 /* if new mappings added later this will need to be changed */
3248 if (tmpval != 0 && tmpval != 1)
3255 * Create new credentials to correspond to a remote user with given
3256 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3257 * provide pioctl (and other) services to foreign clients (i.e. nfs
3258 * clients) by using this call to `become' the client.
3261 #define PIOCTL_HEADER 6
3262 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3265 afs_uint32 hostaddr;
3266 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3267 extern struct afs_exporter *exporter_find();
3268 struct afs_exporter *exporter, *outexporter;
3269 struct AFS_UCRED *newcred;
3270 struct unixuser *au;
3272 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3273 return EINVAL; /* NFS trans not supported for Ultrix */
3275 #if defined(AFS_SGIMP_ENV)
3276 osi_Assert(ISAFS_GLOCK());
3278 AFS_STATCNT(HandleClientContext);
3279 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3280 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3281 return EINVAL; /* Too small to be good */
3283 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3284 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3286 osi_FreeLargeSpace(inData);
3290 /* Extract information for remote user */
3291 hostaddr = *((afs_uint32 *)ain);
3292 ain += sizeof(hostaddr);
3293 uid = *((afs_uint32 *)ain);
3295 g0 = *((afs_uint32 *)ain);
3297 g1 = *((afs_uint32 *)ain);
3299 *com = *((afs_uint32 *)ain);
3300 ain += sizeof(afs_int32);
3301 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3304 * Of course, one must be root for most of these functions, but
3305 * we'll allow (for knfs) you to set things if the pag is 0 and
3306 * you're setting tokens or unlogging.
3309 if (!afs_osi_suser(credp)) {
3311 #ifndef AFS_SGI64_ENV
3312 /* Since SGI's suser() returns explicit failure after the call.. */
3316 /* check for acceptable opcodes for normal folks, which are, so far,
3317 * set tokens and unlog.
3319 if (i != 9 && i != 3 && i != 38 && i != 8) {
3320 osi_FreeLargeSpace(inData);
3325 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3326 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3327 osi_FreeLargeSpace(inData);
3330 * We map uid 0 to nobody to match the mapping that the nfs
3331 * server does and to ensure that the suser() calls in the afs
3332 * code fails for remote client roots.
3334 uid = afs_nobody; /* NFS_NOBODY == -2 */
3337 #ifdef AFS_AIX41_ENV
3340 newcred->cr_gid = RMTUSER_REQ;
3341 newcred->cr_groups[0] = g0;
3342 newcred->cr_groups[1] = g1;
3344 newcred->cr_ngrps = 2;
3346 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3347 newcred->cr_ngroups = 2;
3349 for (i=2; i<NGROUPS; i++)
3350 newcred->cr_groups[i] = NOGROUP;
3353 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3354 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3356 if (!(exporter = exporter_find(exporter_type))) {
3357 /* Exporter wasn't initialized or an invalid exporter type */
3361 if (exporter->exp_states & EXP_PWSYNC) {
3362 if (uid != credp->cr_uid) {
3364 return ENOEXEC; /* XXX Find a better errno XXX */
3367 newcred->cr_uid = uid; /* Only temporary */
3368 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3369 /* The client's pag is the only unique identifier for it */
3370 newcred->cr_uid = pag;
3372 if (!code && *com == PSETPAG) {
3373 /* Special case for 'setpag' */
3374 afs_uint32 pagvalue = genpag();
3376 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3378 * Note that we leave the 'outexporter' struct held so it won't
3381 au->exporter = outexporter;
3382 if (ablob->out_size >= 4) {
3383 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3385 afs_PutUser(au, WRITE_LOCK);
3386 if (code) return code;
3387 return PSETPAG; /* Special return for setpag */
3389 EXP_RELE(outexporter);
3392 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3395 /* get all interface addresses of this client */
3398 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3401 struct vrequest *areq;
3404 afs_int32 *aoutSize;
3406 struct sprefrequest *spin; /* input */
3407 struct sprefinfo *spout; /* output */
3408 struct spref *srvout; /* one output component */
3412 AFS_STATCNT(PGetCPrefs);
3413 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3414 return EIO; /* Inappropriate ioctl for device */
3416 if ( ainSize < sizeof (struct sprefrequest ))
3419 spin = (struct sprefrequest *) ain;
3420 spout = (struct sprefinfo *) aout;
3422 maxNumber = spin->num_servers; /* max addrs this time */
3423 srvout = spout->servers;
3425 ObtainReadLock(&afs_xinterface);
3427 /* copy out the client interface information from the
3428 ** kernel data structure "interface" to the output buffer
3430 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3431 && ( j< maxNumber) ; i++, j++, srvout++)
3432 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3434 spout->num_servers = j;
3435 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3437 if ( i >= afs_cb_interface.numberOfInterfaces )
3438 spout->next_offset = 0; /* start from beginning again */
3440 spout->next_offset = spin->offset + j;
3442 ReleaseReadLock(&afs_xinterface);
3447 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3450 struct vrequest *areq;
3453 afs_int32 *aoutSize;
3455 struct setspref *sin;
3458 AFS_STATCNT(PSetCPrefs);
3459 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3460 return EIO; /* Inappropriate ioctl for device */
3462 sin = (struct setspref *)ain;
3464 if ( ainSize < sizeof(struct setspref) )
3466 #if 0 /* num_servers is unsigned */
3467 if ( sin->num_servers < 0 )
3470 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3473 ObtainWriteLock(&afs_xinterface, 412);
3474 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3475 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3476 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3478 ReleaseWriteLock(&afs_xinterface);
3482 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3485 struct vrequest *areq;
3488 afs_int32 *aoutSize;
3489 struct AFS_UCRED *acred; {
3490 register afs_int32 code;
3491 register struct vcache *tvc;
3492 register struct dcache *tdc;
3493 struct VenusFid tfid;
3495 afs_int32 offset, len, hasatsys=0;
3497 AFS_STATCNT(PFlushMount);
3498 if (!avc) return EINVAL;
3499 code = afs_VerifyVCache(avc, areq);
3500 if (code) return code;
3501 if (vType(avc) != VDIR) {
3504 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3505 if (!tdc) return ENOENT;
3506 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3507 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3512 tfid.Cell = avc->fid.Cell;
3513 tfid.Fid.Volume = avc->fid.Fid.Volume;
3514 afs_PutDCache(tdc); /* we're done with the data */
3515 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3516 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3518 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3525 if (vType(tvc) != VLNK) {
3526 afs_PutVCache(tvc, WRITE_LOCK);
3530 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3531 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3533 ObtainWriteLock(&tvc->lock,645);
3534 ObtainWriteLock(&afs_xcbhash, 646);
3535 afs_DequeueCallback(tvc);
3536 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3537 ReleaseWriteLock(&afs_xcbhash);
3538 /* now find the disk cache entries */
3539 afs_TryToSmush(tvc, acred, 1);
3540 osi_dnlc_purgedp(tvc);
3541 afs_symhint_inval(tvc);
3542 if (tvc->linkData && !(tvc->states & CCore)) {
3543 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3544 tvc->linkData = (char *) 0;
3546 ReleaseWriteLock(&tvc->lock);
3547 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3548 afs_BozonUnlock(&tvc->pvnLock, tvc);
3550 afs_PutVCache(tvc, WRITE_LOCK);
3552 if (hasatsys) osi_FreeLargeSpace(bufp);
3556 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3559 struct vrequest *areq;
3562 afs_int32 *aoutSize;
3563 struct AFS_UCRED *acred;
3568 if (!afs_osi_suser(acred)) {
3572 if (ainSize != sizeof(afs_int32)) {
3576 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3577 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3581 if (flags & AFSCALL_RXSTATS_ENABLE) {
3582 rx_enableProcessRPCStats();
3584 if (flags & AFSCALL_RXSTATS_DISABLE) {
3585 rx_disableProcessRPCStats();
3587 if (flags & AFSCALL_RXSTATS_CLEAR) {
3588 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3596 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3599 struct vrequest *areq;
3602 afs_int32 *aoutSize;
3603 struct AFS_UCRED *acred;
3608 if (!afs_osi_suser(acred)) {
3612 if (ainSize != sizeof(afs_int32)) {
3616 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3617 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3621 if (flags & AFSCALL_RXSTATS_ENABLE) {
3622 rx_enablePeerRPCStats();
3624 if (flags & AFSCALL_RXSTATS_DISABLE) {
3625 rx_disablePeerRPCStats();
3627 if (flags & AFSCALL_RXSTATS_CLEAR) {
3628 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3635 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3638 struct vrequest *areq;
3641 afs_int32 *aoutSize; /* set this */
3643 register afs_int32 code, code1;
3646 struct rx_call *tcall;
3647 struct AFSVolSync tsync;
3648 struct AFSFetchStatus OutStatus;
3649 struct AFSCallBack CallBack;
3650 struct VenusFid tfid;
3655 AFS_STATCNT(PSetAcl);
3659 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3660 Fid = (struct AFSFid *) ain;
3662 Fid = &avc->fid.Fid;
3663 tfid.Cell = avc->fid.Cell;
3664 tfid.Fid.Volume = Fid->Volume;
3665 tfid.Fid.Vnode = Fid->Vnode;
3666 tfid.Fid.Unique = Fid->Unique;
3668 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3671 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3672 ICL_TYPE_POINTER, tvc,
3673 ICL_TYPE_FID, &tfid,
3674 ICL_TYPE_FID, &avc->fid);
3677 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3678 ICL_TYPE_POINTER, tvc,
3679 ICL_TYPE_FID, &tfid,
3680 ICL_TYPE_FID, &tvc->fid);
3683 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3686 #ifdef RX_ENABLE_LOCKS
3688 #endif /* RX_ENABLE_LOCKS */
3689 tcall = rx_NewCall(tc->id);
3690 code = StartRXAFS_FetchData(tcall,
3691 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3693 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3694 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3696 code1 = rx_EndCall(tcall, code);
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 only to have the callback things handled correctly */
3707 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3708 afs_PutVCache(tvc, WRITE_LOCK);
3711 *aoutSize = sizeof(afs_int32);
3716 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3719 struct vrequest *areq;
3722 afs_int32 *aoutSize; /* set this */
3724 register afs_int32 code;
3727 struct ResidencyCmdInputs *Inputs;
3728 struct ResidencyCmdOutputs *Outputs;
3729 struct VenusFid tfid;
3732 Inputs = (struct ResidencyCmdInputs *) ain;
3733 Outputs = (struct ResidencyCmdOutputs *) aout;
3734 if (!avc) return EINVAL;
3735 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3739 Fid = &avc->fid.Fid;
3741 tfid.Cell = avc->fid.Cell;
3742 tfid.Fid.Volume = Fid->Volume;
3743 tfid.Fid.Vnode = Fid->Vnode;
3744 tfid.Fid.Unique = Fid->Unique;
3746 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3748 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3749 ICL_TYPE_POINTER, tvc,
3750 ICL_TYPE_INT32, Inputs->command,
3751 ICL_TYPE_FID, &tfid);
3755 if (Inputs->command) {
3757 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3759 #ifdef RX_ENABLE_LOCKS
3761 #endif /* RX_ENABLE_LOCKS */
3762 code = RXAFS_ResidencyCmd(tc->id, Fid,
3764 (struct ResidencyCmdOutputs *) aout);
3765 #ifdef RX_ENABLE_LOCKS
3767 #endif /* RX_ENABLE_LOCKS */
3771 (afs_Analyze(tc, code, &tvc->fid, areq,
3772 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3774 /* This call is done to have the callback things handled correctly */
3775 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3776 } else { /* just a status request, return also link data */
3778 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3779 Outputs->chars[0] = 0;
3780 if (vType(tvc) == VLNK) {
3781 ObtainWriteLock(&tvc->lock,555);
3782 if (afs_HandleLink(tvc, areq) == 0)
3783 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3784 ReleaseWriteLock(&tvc->lock);
3788 afs_PutVCache(tvc, WRITE_LOCK);
3791 *aoutSize = sizeof(struct ResidencyCmdOutputs);