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 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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 || AFS_FBSD_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) || defined(AFS_FBSD_ENV)
422 register struct file *fd;
425 register struct vcache *tvc;
426 register int ioctlDone = 0, code = 0;
428 AFS_STATCNT(afs_xioctl);
429 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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) || defined(AFS_FBSD_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) && !defined(AFS_FBSD_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) || defined(AFS_FBSD_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 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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) || defined(AFS_FBSD_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) || defined(AFS_FBSD_ENV)
762 if ((com & 0xff) == PSetClientContext) {
763 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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) || defined(AFS_FBSD_ENV)
788 return (setuerror(code), code);
792 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_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) || defined(AFS_FBSD_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) && !defined(AFS_FBSD_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) || defined(AFS_FBSD_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) && !defined(AFS_FBSD_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) || defined(AFS_FBSD_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) || defined(AFS_FBSD_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) || defined(AFS_FBSD_ENV)
973 code = EINVAL; /* not in /afs */
980 vp = (struct vnode *) 0;
985 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_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) || defined(AFS_FBSD_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 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_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 struct sysname_info sysState;
1669 afs_int32 offset, len;
1671 AFS_STATCNT(PNewStatMount);
1672 if (!avc) return EINVAL;
1673 code = afs_VerifyVCache(avc, areq);
1674 if (code) return code;
1675 if (vType(avc) != VDIR) {
1678 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1679 if (!tdc) return ENOENT;
1680 Check_AtSys(avc, ain, &sysState, areq);
1682 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1683 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1684 bufp = sysState.name;
1689 tfid.Cell = avc->fid.Cell;
1690 tfid.Fid.Volume = avc->fid.Fid.Volume;
1691 afs_PutDCache(tdc); /* we're done with the data */
1692 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1693 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1695 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1702 if (vType(tvc) != VLNK) {
1703 afs_PutVCache(tvc, WRITE_LOCK);
1707 ObtainWriteLock(&tvc->lock,226);
1708 code = afs_HandleLink(tvc, areq);
1710 if (tvc->linkData) {
1711 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1714 /* we have the data */
1715 strcpy(aout, tvc->linkData);
1716 *aoutSize = strlen(tvc->linkData)+1;
1721 ReleaseWriteLock(&tvc->lock);
1722 afs_PutVCache(tvc, WRITE_LOCK);
1724 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1728 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1731 struct vrequest *areq;
1734 afs_int32 *aoutSize; /* set this */ {
1735 register struct cell *tcell;
1736 register afs_int32 i;
1737 register struct unixuser *tu;
1742 AFS_STATCNT(PGetTokens);
1743 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1744 return EIO; /* Inappropriate ioctl for device */
1746 /* weird interface. If input parameter is present, it is an integer and
1747 we're supposed to return the parm'th tokens for this unix uid.
1748 If not present, we just return tokens for cell 1.
1749 If counter out of bounds, return EDOM.
1750 If no tokens for the particular cell, return ENOTCONN.
1751 Also, if this mysterious parm is present, we return, along with the
1752 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1753 at the end, in that order.
1755 if (newStyle = (ainSize > 0)) {
1756 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1758 i = UHash(areq->uid);
1759 ObtainReadLock(&afs_xuser);
1760 for(tu = afs_users[i]; tu; tu=tu->next) {
1762 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1763 if (iterator-- == 0) break; /* are we done yet? */
1767 if (tu->uid == areq->uid && tu->cell == 1) break;
1772 * No need to hold a read lock on each user entry
1776 ReleaseReadLock(&afs_xuser);
1781 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1782 tu->states |= (UTokensBad | UNeedsReset);
1783 afs_PutUser(tu, READ_LOCK);
1786 /* use iterator for temp */
1788 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1789 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1790 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1791 cp += sizeof(afs_int32);
1792 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1794 iterator = sizeof(struct ClearToken);
1795 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1796 cp += sizeof(afs_int32);
1797 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1798 cp += sizeof(struct ClearToken);
1800 /* put out primary id and cell name, too */
1801 iterator = (tu->states & UPrimary ? 1 : 0);
1802 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1803 cp += sizeof(afs_int32);
1804 tcell = afs_GetCell(tu->cell, READ_LOCK);
1806 strcpy(cp, tcell->cellName);
1807 cp += strlen(tcell->cellName)+1;
1808 afs_PutCell(tcell, READ_LOCK);
1812 *aoutSize = cp - aout;
1813 afs_PutUser(tu, READ_LOCK);
1817 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1820 struct vrequest *areq;
1823 afs_int32 *aoutSize; /* set this */ {
1824 register afs_int32 i;
1825 register struct unixuser *tu;
1827 AFS_STATCNT(PUnlog);
1828 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1829 return EIO; /* Inappropriate ioctl for device */
1831 i = UHash(areq->uid);
1832 ObtainWriteLock(&afs_xuser,227);
1833 for(tu=afs_users[i]; tu; tu=tu->next) {
1834 if (tu->uid == areq->uid) {
1836 tu->states &= ~UHasTokens;
1837 /* security is not having to say you're sorry */
1838 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1840 ReleaseWriteLock(&afs_xuser);
1841 /* We have to drop the lock over the call to afs_ResetUserConns, since
1842 * it obtains the afs_xvcache lock. We could also keep the lock, and
1843 * modify ResetUserConns to take parm saying we obtained the lock
1844 * already, but that is overkill. By keeping the "tu" pointer
1845 * held over the released lock, we guarantee that we won't lose our
1846 * place, and that we'll pass over every user conn that existed when
1847 * we began this call.
1849 afs_ResetUserConns(tu);
1851 ObtainWriteLock(&afs_xuser,228);
1853 /* set the expire times to 0, causes
1854 * afs_GCUserData to remove this entry
1856 tu->ct.EndTimestamp = 0;
1858 #endif /* UKERNEL */
1861 ReleaseWriteLock(&afs_xuser);
1865 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1868 struct vrequest *areq;
1871 afs_int32 *aoutSize; /* set this */ {
1872 afs_int32 newHostAddr;
1873 afs_int32 oldHostAddr;
1875 AFS_STATCNT(PMariner);
1877 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1879 oldHostAddr = 0xffffffff; /* disabled */
1881 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1882 if (newHostAddr == 0xffffffff) {
1883 /* disable mariner operations */
1886 else if (newHostAddr) {
1888 afs_marinerHost = newHostAddr;
1890 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1891 *aoutSize = sizeof(afs_int32);
1895 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1898 struct vrequest *areq;
1901 afs_int32 *aoutSize; /* set this */
1902 struct AFS_UCRED *acred;
1904 register char *cp = 0;
1906 register struct server *ts;
1907 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1909 struct chservinfo *pcheck;
1911 AFS_STATCNT(PCheckServers);
1913 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1914 return EIO; /* Inappropriate ioctl for device */
1916 if (*lp == 0x12345678) { /* For afs3.3 version */
1917 pcheck=(struct chservinfo *)ain;
1918 if (pcheck->tinterval >= 0) {
1920 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1921 *aoutSize = sizeof(afs_int32);
1922 if (pcheck->tinterval > 0) {
1923 if (!afs_osi_suser(acred))
1925 PROBE_INTERVAL=pcheck->tinterval;
1931 temp=pcheck->tflags;
1932 cp = pcheck->tbuffer;
1933 } else { /* For pre afs3.3 versions */
1934 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1935 cp = ain+sizeof(afs_int32);
1936 if (ainSize > sizeof(afs_int32))
1941 * 1: fast check, don't contact servers.
1942 * 2: local cell only.
1945 /* have cell name, too */
1946 cellp = afs_GetCellByName(cp, READ_LOCK);
1947 if (!cellp) return ENOENT;
1949 else cellp = (struct cell *) 0;
1950 if (!cellp && (temp & 2)) {
1951 /* use local cell */
1952 cellp = afs_GetCell(1, READ_LOCK);
1954 if (!(temp & 1)) { /* if not fast, call server checker routine */
1955 afs_CheckServers(1, cellp); /* check down servers */
1956 afs_CheckServers(0, cellp); /* check up servers */
1958 /* now return the current down server list */
1960 ObtainReadLock(&afs_xserver);
1961 for(i=0;i<NSERVERS;i++) {
1962 for(ts = afs_servers[i]; ts; ts=ts->next) {
1963 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1964 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1965 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1966 cp += sizeof(afs_int32);
1970 ReleaseReadLock(&afs_xserver);
1971 if (cellp) afs_PutCell(cellp, READ_LOCK);
1972 *aoutSize = cp - aout;
1976 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1979 struct vrequest *areq;
1982 afs_int32 *aoutSize; /* set this */ {
1983 AFS_STATCNT(PCheckVolNames);
1984 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1985 return EIO; /* Inappropriate ioctl for device */
1987 afs_CheckRootVolume();
1988 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1989 AFS_VOLCHECK_EXPIRED |
1991 AFS_VOLCHECK_MTPTS);
1995 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1998 struct vrequest *areq;
2001 afs_int32 *aoutSize; /* set this */ {
2005 struct unixuser *tu;
2007 extern afs_rwlock_t afs_xsrvAddr;
2009 AFS_STATCNT(PCheckAuth);
2010 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2011 return EIO; /* Inappropriate ioctl for device */
2014 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2015 if (!tu) retValue = EACCES;
2017 /* we have a user */
2018 ObtainReadLock(&afs_xsrvAddr);
2019 ObtainReadLock(&afs_xconn);
2021 /* any tokens set? */
2022 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
2023 /* all connections in cell 1 working? */
2024 for(i=0;i<NSERVERS;i++) {
2025 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
2026 for (tc = sa->conns; tc; tc=tc->next) {
2027 if (tc->user == tu && (tu->states & UTokensBad))
2032 ReleaseReadLock(&afs_xsrvAddr);
2033 ReleaseReadLock(&afs_xconn);
2034 afs_PutUser(tu, READ_LOCK);
2036 bcopy((char *)&retValue, aout, sizeof(afs_int32));
2037 *aoutSize = sizeof(afs_int32);
2041 static Prefetch(apath, adata, afollow, acred)
2043 struct afs_ioctl *adata;
2045 struct AFS_UCRED *acred;
2048 register afs_int32 code;
2049 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2055 AFS_STATCNT(Prefetch);
2056 if (!apath) return EINVAL;
2057 tp = osi_AllocLargeSpace(1024);
2058 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2060 osi_FreeLargeSpace(tp);
2063 if (afs_BBusy()) { /* do this as late as possible */
2064 osi_FreeLargeSpace(tp);
2065 return EWOULDBLOCK; /* pretty close */
2067 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
2071 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
2074 struct vrequest *areq;
2077 afs_int32 *aoutSize; /* set this */ {
2078 register struct volume *tvp;
2079 register struct server *ts;
2080 register afs_int32 i;
2083 AFS_STATCNT(PFindVolume);
2084 if (!avc) return EINVAL;
2085 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2088 for(i=0;i<MAXHOSTS;i++) {
2089 ts = tvp->serverHost[i];
2091 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2092 cp += sizeof(afs_int32);
2095 /* still room for terminating NULL, add it on */
2096 ainSize = 0; /* reuse vbl */
2097 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2098 cp += sizeof(afs_int32);
2100 *aoutSize = cp - aout;
2101 afs_PutVolume(tvp, READ_LOCK);
2107 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2110 struct vrequest *areq;
2113 afs_int32 *aoutSize; /* set this */ {
2114 register afs_int32 code;
2117 AFS_STATCNT(PViceAccess);
2118 if (!avc) return EINVAL;
2119 code = afs_VerifyVCache(avc, areq);
2120 if (code) return code;
2121 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2122 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2127 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2130 struct vrequest *areq;
2133 afs_int32 *aoutSize; /* set this */
2134 struct AFS_UCRED *acred;
2139 AFS_STATCNT(PSetCacheSize);
2140 if (!afs_osi_suser(acred))
2142 /* too many things are setup initially in mem cache version */
2143 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2144 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2145 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2147 extern u_int afs_min_cache;
2148 if (newValue < afs_min_cache)
2149 afs_cacheBlocks = afs_min_cache;
2151 afs_cacheBlocks = newValue;
2153 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2154 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2155 afs_MaybeWakeupTruncateDaemon();
2156 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2157 afs_osi_Wait(1000, 0, 0);
2158 afs_MaybeWakeupTruncateDaemon();
2163 #define MAXGCSTATS 16
2164 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2167 struct vrequest *areq;
2170 afs_int32 *aoutSize; /* set this */ {
2171 afs_int32 results[MAXGCSTATS];
2173 AFS_STATCNT(PGetCacheSize);
2174 bzero((char *)results, sizeof(results));
2175 results[0] = afs_cacheBlocks;
2176 results[1] = afs_blocksUsed;
2177 bcopy((char *)results, aout, sizeof(results));
2178 *aoutSize = sizeof(results);
2182 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2185 struct vrequest *areq;
2188 afs_int32 *aoutSize; /* set this */ {
2189 register struct conn *tc;
2190 register afs_int32 code;
2191 struct AFSCallBack CallBacks_Array[1];
2192 struct AFSCBFids theFids;
2193 struct AFSCBs theCBs;
2196 AFS_STATCNT(PRemoveCallBack);
2197 if (!avc) return EINVAL;
2198 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2199 ObtainWriteLock(&avc->lock,229);
2200 theFids.AFSCBFids_len = 1;
2201 theCBs.AFSCBs_len = 1;
2202 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2203 theCBs.AFSCBs_val = CallBacks_Array;
2204 CallBacks_Array[0].CallBackType = CB_DROPPED;
2205 if (avc->callback) {
2207 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2209 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2210 #ifdef RX_ENABLE_LOCKS
2212 #endif /* RX_ENABLE_LOCKS */
2213 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2214 #ifdef RX_ENABLE_LOCKS
2216 #endif /* RX_ENABLE_LOCKS */
2219 /* don't set code on failure since we wouldn't use it */
2221 (afs_Analyze(tc, code, &avc->fid, areq,
2222 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2223 SHARED_LOCK, (struct cell *)0));
2225 ObtainWriteLock(&afs_xcbhash, 457);
2226 afs_DequeueCallback(avc);
2228 avc->states &= ~(CStatd | CUnique);
2229 ReleaseWriteLock(&afs_xcbhash);
2230 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2231 osi_dnlc_purgedp(avc);
2233 ReleaseWriteLock(&avc->lock);
2237 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2240 struct vrequest *areq;
2244 struct AFS_UCRED *acred;
2245 afs_int32 *aoutSize; /* set this */ {
2246 /* create a new cell */
2247 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2248 register struct cell *tcell;
2249 char *newcell=0, *linkedcell=0, *tp= ain;
2250 register afs_int32 code, linkedstate=0, ls;
2251 u_short fsport = 0, vlport = 0;
2254 AFS_STATCNT(PNewCell);
2255 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2256 return EIO; /* Inappropriate ioctl for device */
2258 if (!afs_osi_suser(acred))
2261 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2262 tp += sizeof(afs_int32);
2263 if (magic != 0x12345678)
2266 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2267 * server addresses while the 3.5 fs newcell command passes
2268 * MAXHOSTS. To figure out which is which, check if the cellname
2271 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2272 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2274 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2275 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2276 tp += (scount * sizeof(afs_int32));
2278 lp = (afs_int32 *)tp;
2281 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2282 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2283 tp += (3 * sizeof(afs_int32));
2285 if ((ls = *lp) & 1) {
2286 linkedcell = tp + strlen(newcell)+1;
2287 linkedstate |= CLinkedCell;
2290 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2291 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
2295 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2298 struct vrequest *areq;
2301 afs_int32 *aoutSize; /* set this */ {
2302 afs_int32 whichCell;
2303 register struct cell *tcell=0;
2304 register afs_int32 i;
2305 register char *cp, *tp = ain;
2306 register struct afs_q *cq, *tq;
2308 AFS_STATCNT(PListCells);
2309 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2310 return EIO; /* Inappropriate ioctl for device */
2312 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2313 tp += sizeof(afs_int32);
2314 ObtainReadLock(&afs_xcell);
2315 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2316 tcell = QTOC(cq); tq = QNext(cq);
2317 if (whichCell == 0) break;
2318 if (tq == &CellLRU) tcell = 0;
2323 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2324 for(i=0;i<MAXCELLHOSTS;i++) {
2325 if (tcell->cellHosts[i] == 0) break;
2326 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2327 cp += sizeof(afs_int32);
2329 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2330 strcpy(cp, tcell->cellName);
2331 cp += strlen(tcell->cellName)+1;
2332 *aoutSize = cp - aout;
2334 ReleaseReadLock(&afs_xcell);
2335 if (tcell) return 0;
2339 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2342 struct vrequest *areq;
2346 afs_int32 *aoutSize; /* set this */ {
2347 register afs_int32 code;
2349 struct sysname_info sysState;
2350 afs_int32 offset, len;
2351 register struct conn *tc;
2352 register struct dcache *tdc;
2353 register struct vcache *tvc;
2354 struct AFSFetchStatus OutDirStatus;
2355 struct VenusFid tfid;
2356 struct AFSVolSync tsync;
2360 /* "ain" is the name of the file in this dir to remove */
2362 AFS_STATCNT(PRemoveMount);
2363 if (!avc) return EINVAL;
2364 code = afs_VerifyVCache(avc, areq);
2365 if (code) return code;
2366 if (vType(avc) != VDIR) return ENOTDIR;
2368 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2369 if (!tdc) return ENOENT;
2370 Check_AtSys(avc, ain, &sysState, areq);
2372 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2373 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2374 bufp = sysState.name;
2379 tfid.Cell = avc->fid.Cell;
2380 tfid.Fid.Volume = avc->fid.Fid.Volume;
2381 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2382 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2384 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2385 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2392 if (vType(tvc) != VLNK) {
2394 afs_PutVCache(tvc, WRITE_LOCK);
2398 ObtainWriteLock(&tvc->lock,230);
2399 code = afs_HandleLink(tvc, areq);
2401 if (tvc->linkData) {
2402 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2407 ReleaseWriteLock(&tvc->lock);
2408 osi_dnlc_purgedp(tvc);
2409 afs_PutVCache(tvc, WRITE_LOCK);
2414 ObtainWriteLock(&avc->lock,231);
2415 osi_dnlc_remove(avc, bufp, tvc);
2417 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2419 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2420 #ifdef RX_ENABLE_LOCKS
2422 #endif /* RX_ENABLE_LOCKS */
2423 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2424 bufp, &OutDirStatus, &tsync);
2425 #ifdef RX_ENABLE_LOCKS
2427 #endif /* RX_ENABLE_LOCKS */
2432 (afs_Analyze(tc, code, &avc->fid, areq,
2433 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2434 SHARED_LOCK, (struct cell *)0));
2437 if (tdc) afs_PutDCache(tdc);
2438 ReleaseWriteLock(&avc->lock);
2442 /* we have the thing in the cache */
2443 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2444 /* we can do it locally */
2445 code = afs_dir_Delete(&tdc->f.inode, bufp);
2447 ZapDCE(tdc); /* surprise error -- invalid value */
2448 DZap(&tdc->f.inode);
2451 afs_PutDCache(tdc); /* drop ref count */
2453 avc->states &= ~CUnique; /* For the dfs xlator */
2454 ReleaseWriteLock(&avc->lock);
2457 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2461 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2464 struct vrequest *areq;
2468 struct AFS_UCRED *acred;
2469 afs_int32 *aoutSize; /* set this */ {
2470 return EINVAL; /* OBSOLETE */
2473 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2476 struct vrequest *areq;
2479 afs_int32 *aoutSize; /* set this */ {
2480 register struct cell *tcell;
2483 AFS_STATCNT(PGetCellStatus);
2484 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2485 return EIO; /* Inappropriate ioctl for device */
2487 tcell = afs_GetCellByName(ain, READ_LOCK);
2488 if (!tcell) return ENOENT;
2489 temp = tcell->states;
2490 afs_PutCell(tcell, READ_LOCK);
2491 bcopy((char *)&temp, aout, sizeof(afs_int32));
2492 *aoutSize = sizeof(afs_int32);
2496 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2499 struct vrequest *areq;
2502 struct AFS_UCRED *acred;
2503 afs_int32 *aoutSize; /* set this */ {
2504 register struct cell *tcell;
2507 if (!afs_osi_suser(acred))
2509 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2510 return EIO; /* Inappropriate ioctl for device */
2512 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2513 if (!tcell) return ENOENT;
2514 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2516 tcell->states |= CNoSUID;
2518 tcell->states &= ~CNoSUID;
2519 afs_PutCell(tcell, WRITE_LOCK);
2523 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2526 struct vrequest *areq;
2529 afs_int32 *aoutSize; /* set this */
2530 struct AFS_UCRED *acred;
2532 extern struct volume *afs_volumes[NVOLS];
2533 register afs_int32 i;
2534 register struct dcache *tdc;
2535 register struct vcache *tvc;
2536 register struct volume *tv;
2537 afs_int32 cell, volume;
2539 AFS_STATCNT(PFlushVolumeData);
2542 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2543 return EIO; /* Inappropriate ioctl for device */
2545 volume = avc->fid.Fid.Volume; /* who to zap */
2546 cell = avc->fid.Cell;
2549 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2550 * the vcaches associated with the volume.
2552 ObtainReadLock(&afs_xvcache);
2553 for(i = 0; i < VCSIZE; i++) {
2554 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2555 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2556 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2557 VN_HOLD((struct vnode *)tvc);
2559 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2565 ReleaseReadLock(&afs_xvcache);
2566 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2567 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2569 ObtainWriteLock(&tvc->lock,232);
2571 ObtainWriteLock(&afs_xcbhash, 458);
2572 afs_DequeueCallback(tvc);
2573 tvc->states &= ~(CStatd | CDirty);
2574 ReleaseWriteLock(&afs_xcbhash);
2575 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2576 osi_dnlc_purgedp(tvc);
2577 afs_TryToSmush(tvc, acred, 1);
2578 ReleaseWriteLock(&tvc->lock);
2579 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2580 afs_BozonUnlock(&tvc->pvnLock, tvc);
2582 ObtainReadLock(&afs_xvcache);
2583 /* our tvc ptr is still good until now */
2588 ReleaseReadLock(&afs_xvcache);
2591 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2592 for(i=0;i<afs_cacheFiles;i++) {
2593 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2594 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2595 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2596 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2597 if (! (afs_indexFlags[i] & IFDataMod)) {
2598 /* if the file is modified, but has a ref cnt of only 1, then
2599 someone probably has the file open and is writing into it.
2600 Better to skip flushing such a file, it will be brought back
2601 immediately on the next write anyway.
2603 If we *must* flush, then this code has to be rearranged to call
2604 afs_storeAllSegments() first */
2605 afs_FlushDCache(tdc);
2609 tdc->refCount--; /* bumped by getdslot */
2611 MReleaseWriteLock(&afs_xdcache);
2613 ObtainReadLock(&afs_xvolume);
2614 for (i=0;i<NVOLS;i++) {
2615 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2616 if (tv->volume == volume) {
2617 afs_ResetVolumeInfo(tv);
2622 ReleaseReadLock(&afs_xvolume);
2624 /* probably, a user is doing this, probably, because things are screwed up.
2625 * maybe it's the dnlc's fault? */
2632 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2635 struct vrequest *areq;
2638 afs_int32 *aoutSize; /* set this */ {
2639 register afs_int32 code;
2640 struct vcxstat stat;
2643 /* AFS_STATCNT(PGetVnodeXStatus); */
2644 if (!avc) return EINVAL;
2645 code = afs_VerifyVCache(avc, areq);
2646 if (code) return code;
2647 if (vType(avc) == VDIR)
2648 mode = PRSFS_LOOKUP;
2651 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2653 stat.fid = avc->fid;
2654 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2655 stat.lock = avc->lock;
2656 stat.parentVnode = avc->parentVnode;
2657 stat.parentUnique = avc->parentUnique;
2658 hset(stat.flushDV, avc->flushDV);
2659 hset(stat.mapDV, avc->mapDV);
2660 stat.truncPos = avc->truncPos;
2661 { /* just grab the first two - won't break anything... */
2662 struct axscache *ac;
2664 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2665 stat.randomUid[i] = ac->uid;
2666 stat.randomAccess[i] = ac->axess;
2669 stat.callback = afs_data_pointer_to_int32(avc->callback);
2670 stat.cbExpires = avc->cbExpires;
2671 stat.anyAccess = avc->anyAccess;
2672 stat.opens = avc->opens;
2673 stat.execsOrWriters = avc->execsOrWriters;
2674 stat.flockCount = avc->flockCount;
2675 stat.mvstat = avc->mvstat;
2676 stat.states = avc->states;
2677 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2678 *aoutSize = sizeof(struct vcxstat);
2683 /* We require root for local sysname changes, but not for remote */
2684 /* (since we don't really believe remote uids anyway) */
2685 /* outname[] shouldn't really be needed- this is left as an excercise */
2686 /* for the reader. */
2687 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2690 struct vrequest *areq;
2693 afs_int32 *aoutSize; /* set this */
2694 register struct AFS_UCRED *acred;
2696 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2697 int setsysname, foundname=0;
2698 register struct afs_exporter *exporter;
2699 extern struct unixuser *afs_FindUser();
2700 extern char *afs_sysname;
2701 extern char *afs_sysnamelist[];
2702 extern int afs_sysnamecount;
2703 register struct unixuser *au;
2704 register afs_int32 pag, error;
2708 AFS_STATCNT(PSetSysName);
2709 if (!afs_globalVFS) {
2710 /* Afsd is NOT running; disable it */
2711 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2714 return (setuerror(EINVAL), EINVAL);
2717 bzero(inname, MAXSYSNAME);
2718 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2719 ain += sizeof(afs_int32);
2723 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2725 for(cp = ain,count = 0;count < setsysname;count++) {
2726 /* won't go past end of ain since maxsysname*num < ain length */
2728 if (t >= MAXSYSNAME || t <= 0)
2730 /* check for names that can shoot us in the foot */
2731 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2737 /* inname gets first entry in case we're being a translater */
2739 bcopy(ain, inname, t+1); /* include terminating null */
2742 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2743 pag = PagInCred(acred);
2745 return EINVAL; /* Better than panicing */
2747 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2748 return EINVAL; /* Better than panicing */
2750 if (!(exporter = au->exporter)) {
2751 afs_PutUser(au, READ_LOCK);
2752 return EINVAL; /* Better than panicing */
2754 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2756 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2758 afs_PutUser(au, READ_LOCK);
2763 afs_PutUser(au, READ_LOCK);
2766 /* Not xlating, so local case */
2767 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2768 if (!setsysname) { /* user just wants the info */
2769 strcpy(outname, afs_sysname);
2770 foundname = afs_sysnamecount;
2771 } else { /* Local guy; only root can change sysname */
2772 if (!afs_osi_suser(acred))
2775 /* clear @sys entries from the dnlc, once afs_lookup can
2776 do lookups of @sys entries and thinks it can trust them */
2777 /* privs ok, store the entry, ... */
2778 strcpy(afs_sysname, inname);
2779 if (setsysname > 1) { /* ... or list */
2781 for(count=1; count < setsysname;++count) {
2782 if (!afs_sysnamelist[count])
2783 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2785 bcopy(cp, afs_sysnamelist[count], t+1); /* include null */
2789 afs_sysnamecount = setsysname;
2793 cp = aout; /* not changing so report back the count and ... */
2794 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2795 cp += sizeof(afs_int32);
2797 strcpy(cp, outname); /* ... the entry, ... */
2798 cp += strlen(outname)+1;
2799 for(count=1; count < foundname; ++count) { /* ... or list. */
2800 /* Note: we don't support @sys lists for exporters */
2801 if (!afs_sysnamelist[count])
2802 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2803 t = strlen(afs_sysnamelist[count]);
2804 if (t >= MAXSYSNAME)
2805 osi_Panic("PSetSysName: sysname entry garbled\n");
2806 strcpy(cp, afs_sysnamelist[count]);
2810 *aoutSize = cp - aout;
2815 /* sequential search through the list of touched cells is not a good
2816 * long-term solution here. For small n, though, it should be just
2817 * fine. Should consider special-casing the local cell for large n.
2818 * Likewise for PSetSPrefs.
2820 static void ReSortCells(s,l, vlonly)
2821 int s; /* number of ids in array l[] -- NOT index of last id */
2822 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2823 int vlonly; /* sort vl servers or file servers?*/
2825 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2834 tcell = afs_GetCell(l[k], WRITE_LOCK);
2835 if (!tcell) continue;
2836 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2837 afs_PutCell(tcell, WRITE_LOCK);
2842 ObtainReadLock(&afs_xvolume);
2843 for (i= 0; i< NVOLS; i++) {
2844 for (j=afs_volumes[i];j;j=j->next) {
2846 if (j->cell == l[k]) {
2847 ObtainWriteLock(&j->lock,233);
2848 afs_SortServers(j->serverHost, MAXHOSTS);
2849 ReleaseWriteLock(&j->lock);
2854 ReleaseReadLock(&afs_xvolume);
2859 static int afs_setsprefs(sp, num, vlonly)
2862 unsigned int vlonly;
2865 int i,j,k,matches,touchedSize;
2866 struct server *srvr = NULL;
2867 afs_int32 touched[34];
2871 for (k=0; k < num; sp++, k++) {
2873 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2876 ObtainReadLock(&afs_xserver);
2878 i = SHash(sp->host.s_addr);
2879 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2880 if (sa->sa_ip == sp->host.s_addr) {
2882 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2883 || (sa->sa_portal == AFS_FSPORT);
2884 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2891 if (sa && matches) { /* found one! */
2893 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2895 sa->sa_iprank = sp->rank + afs_randomMod15();
2896 afs_SortOneServer(sa->server);
2899 /* if we don't know yet what cell it's in, this is moot */
2900 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2901 /* is it in our list of touched cells ? */ ;
2902 if (j < 0) { /* no, it's not */
2903 touched[touchedSize++] = srvr->cell->cell;
2904 if (touchedSize >= 32) { /* watch for ovrflow */
2905 ReleaseReadLock(&afs_xserver);
2906 ReSortCells(touchedSize, touched, vlonly);
2908 ObtainReadLock(&afs_xserver);
2914 ReleaseReadLock(&afs_xserver);
2915 /* if we didn't find one, start to create one. */
2916 /* Note that it doesn't have a cell yet... */
2918 afs_uint32 temp = sp->host.s_addr;
2919 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2920 WRITE_LOCK, (afsUUID *)0,0);
2921 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2922 afs_PutServer(srvr, WRITE_LOCK);
2924 } /* for all cited preferences */
2926 ReSortCells(touchedSize, touched, vlonly);
2930 /* Note that this may only be performed by the local root user.
2933 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2936 struct vrequest *areq;
2939 struct AFS_UCRED *acred;
2940 afs_int32 *aoutSize;
2942 struct setspref *ssp;
2943 AFS_STATCNT(PSetSPrefs);
2945 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2946 return EIO; /* Inappropriate ioctl for device */
2948 if (!afs_osi_suser(acred))
2951 if (ainSize < sizeof(struct setspref))
2954 ssp = (struct setspref *)ain;
2955 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2958 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2959 (ssp->flags & DBservers));
2964 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2967 struct vrequest *areq;
2970 struct AFS_UCRED *acred;
2971 afs_int32 *aoutSize;
2974 AFS_STATCNT(PSetSPrefs);
2975 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2976 return EIO; /* Inappropriate ioctl for device */
2979 if (!afs_osi_suser(acred))
2982 sp = (struct spref *)ain;
2983 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2987 /* some notes on the following code...
2988 * in the hash table of server structs, all servers with the same IP address
2989 * will be on the same overflow chain.
2990 * This could be sped slightly in some circumstances by having it cache the
2991 * immediately previous slot in the hash table and some supporting information
2992 * Only reports file servers now.
2995 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2998 struct vrequest *areq;
3001 afs_int32 *aoutSize;
3003 struct sprefrequest *spin; /* input */
3004 struct sprefinfo *spout; /* output */
3005 struct spref *srvout; /* one output component */
3006 int i,j; /* counters for hash table traversal */
3007 struct server *srvr; /* one of CM's server structs */
3010 int vlonly; /* just return vlservers ? */
3013 AFS_STATCNT(PGetSPrefs);
3014 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3015 return EIO; /* Inappropriate ioctl for device */
3018 if (ainSize < sizeof (struct sprefrequest_33)) {
3022 spin = ((struct sprefrequest *) ain);
3025 if (ainSize > sizeof (struct sprefrequest_33)) {
3026 vlonly = (spin->flags & DBservers);
3030 /* struct sprefinfo includes 1 server struct... that size gets added
3031 * in during the loop that follows.
3033 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
3034 spout = (struct sprefinfo *) aout;
3035 spout->next_offset = spin->offset;
3036 spout->num_servers = 0;
3037 srvout = spout->servers;
3039 ObtainReadLock(&afs_xserver);
3040 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
3041 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
3042 if (spin->offset > (unsigned short)i) {
3043 continue; /* catch up to where we left off */
3045 spout->next_offset++;
3048 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3049 || (sa->sa_portal == AFS_FSPORT);
3051 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3052 /* only report ranks for vl servers */
3056 srvout->host.s_addr = sa->sa_ip;
3057 srvout->rank = sa->sa_iprank;
3058 *aoutSize += sizeof(struct spref);
3059 spout->num_servers++;
3062 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3063 ReleaseReadLock(&afs_xserver); /* no more room! */
3068 ReleaseReadLock(&afs_xserver);
3070 spout->next_offset = 0; /* start over from the beginning next time */
3074 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3075 int afs_NFSRootOnly = 1;
3076 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3079 struct vrequest *areq;
3082 afs_int32 *aoutSize; /* set this */
3083 struct AFS_UCRED *acred;
3085 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
3086 extern struct afs_exporter *exporter_find();
3087 register struct afs_exporter *exporter;
3089 AFS_STATCNT(PExportAfs);
3090 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
3091 type = handleValue >> 24;
3096 exporter = exporter_find(type);
3098 export = handleValue & 3;
3099 changestate = handleValue & 0xff;
3100 smounts = (handleValue >> 2) & 3;
3101 pwsync = (handleValue >> 4) & 3;
3102 convmode = (handleValue >> 6) & 3;
3104 changestate = (handleValue >> 16) & 0x1;
3105 convmode = (handleValue >> 16) & 0x2;
3106 pwsync = (handleValue >> 16) & 0x4;
3107 smounts = (handleValue >> 16) & 0x8;
3108 export = handleValue & 0xff;
3111 /* Failed finding desired exporter; */
3115 handleValue = exporter->exp_states;
3116 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3117 *aoutSize = sizeof(afs_int32);
3119 if (!afs_osi_suser(acred))
3120 return EACCES; /* Only superuser can do this */
3124 exporter->exp_states |= EXP_EXPORTED;
3126 exporter->exp_states &= ~EXP_EXPORTED;
3130 exporter->exp_states |= EXP_UNIXMODE;
3132 exporter->exp_states &= ~EXP_UNIXMODE;
3136 exporter->exp_states |= EXP_PWSYNC;
3138 exporter->exp_states &= ~EXP_PWSYNC;
3142 afs_NFSRootOnly = 0;
3143 exporter->exp_states |= EXP_SUBMOUNTS;
3145 afs_NFSRootOnly = 1;
3146 exporter->exp_states &= ~EXP_SUBMOUNTS;
3149 handleValue = exporter->exp_states;
3150 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3151 *aoutSize = sizeof(afs_int32);
3154 exporter->exp_states |= EXP_EXPORTED;
3156 exporter->exp_states &= ~EXP_EXPORTED;
3158 exporter->exp_states |= EXP_UNIXMODE;
3160 exporter->exp_states &= ~EXP_UNIXMODE;
3162 exporter->exp_states |= EXP_PWSYNC;
3164 exporter->exp_states &= ~EXP_PWSYNC;
3166 afs_NFSRootOnly = 0;
3167 exporter->exp_states |= EXP_SUBMOUNTS;
3169 afs_NFSRootOnly = 1;
3170 exporter->exp_states &= ~EXP_SUBMOUNTS;
3179 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3182 struct vrequest *areq;
3185 struct AFS_UCRED *acred;
3186 afs_int32 *aoutSize; /* set this */
3188 struct gaginfo *gagflags;
3190 if (!afs_osi_suser(acred))
3193 gagflags = (struct gaginfo *) ain;
3194 afs_showflags = gagflags->showflags;
3201 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3204 struct vrequest *areq;
3207 struct AFS_UCRED *acred;
3208 afs_int32 *aoutSize;
3210 struct rxparams *rxp;
3212 if (!afs_osi_suser(acred))
3215 rxp = (struct rxparams *) ain;
3217 if (rxp->rx_initReceiveWindow)
3218 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3219 if (rxp->rx_maxReceiveWindow)
3220 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3221 if (rxp->rx_initSendWindow)
3222 rx_initSendWindow = rxp->rx_initSendWindow;
3223 if (rxp->rx_maxSendWindow)
3224 rx_maxSendWindow = rxp->rx_maxSendWindow;
3225 if (rxp->rxi_nSendFrags)
3226 rxi_nSendFrags = rxp->rxi_nSendFrags;
3227 if (rxp->rxi_nRecvFrags)
3228 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3229 if (rxp->rxi_OrphanFragSize)
3230 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3231 if (rxp->rx_maxReceiveSize)
3233 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3234 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3236 if (rxp->rx_MyMaxSendSize)
3237 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3242 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3245 struct vrequest *areq;
3249 afs_int32 *aoutSize; /* set this */
3251 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3254 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3255 *aoutSize = sizeof(struct cm_initparams);
3259 #ifdef AFS_SGI65_ENV
3260 /* They took crget() from us, so fake it. */
3261 static cred_t *crget(void)
3264 cr = crdup(get_current_cred());
3265 bzero((char*)cr, sizeof(cred_t));
3266 #if CELL || CELL_PREPARE
3274 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3277 struct vrequest *areq;
3280 afs_int32 *aoutSize;
3281 struct AFS_UCRED *acred;
3283 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3284 *aoutSize=sizeof(afs_int32);
3289 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3292 struct vrequest *areq;
3295 afs_int32 *aoutSize;
3296 struct AFS_UCRED *acred;
3300 if (!afs_osi_suser(acred))
3302 if (ainSize != sizeof(afs_int32) || ain == NULL)
3304 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3305 /* if new mappings added later this will need to be changed */
3306 if (tmpval != 0 && tmpval != 1)
3313 * Create new credentials to correspond to a remote user with given
3314 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3315 * provide pioctl (and other) services to foreign clients (i.e. nfs
3316 * clients) by using this call to `become' the client.
3319 #define PIOCTL_HEADER 6
3320 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3323 afs_uint32 hostaddr;
3324 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3325 extern struct afs_exporter *exporter_find();
3326 struct afs_exporter *exporter, *outexporter;
3327 struct AFS_UCRED *newcred;
3328 struct unixuser *au;
3330 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3331 return EINVAL; /* NFS trans not supported for Ultrix */
3333 #if defined(AFS_SGIMP_ENV)
3334 osi_Assert(ISAFS_GLOCK());
3336 AFS_STATCNT(HandleClientContext);
3337 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3338 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3339 return EINVAL; /* Too small to be good */
3341 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3342 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3344 osi_FreeLargeSpace(inData);
3348 /* Extract information for remote user */
3349 hostaddr = *((afs_uint32 *)ain);
3350 ain += sizeof(hostaddr);
3351 uid = *((afs_uint32 *)ain);
3353 g0 = *((afs_uint32 *)ain);
3355 g1 = *((afs_uint32 *)ain);
3357 *com = *((afs_uint32 *)ain);
3358 ain += sizeof(afs_int32);
3359 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3362 * Of course, one must be root for most of these functions, but
3363 * we'll allow (for knfs) you to set things if the pag is 0 and
3364 * you're setting tokens or unlogging.
3367 if (!afs_osi_suser(credp)) {
3369 #ifndef AFS_SGI64_ENV
3370 /* Since SGI's suser() returns explicit failure after the call.. */
3374 /* check for acceptable opcodes for normal folks, which are, so far,
3375 * set tokens and unlog.
3377 if (i != 9 && i != 3 && i != 38 && i != 8) {
3378 osi_FreeLargeSpace(inData);
3383 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3384 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3385 osi_FreeLargeSpace(inData);
3388 * We map uid 0 to nobody to match the mapping that the nfs
3389 * server does and to ensure that the suser() calls in the afs
3390 * code fails for remote client roots.
3392 uid = afs_nobody; /* NFS_NOBODY == -2 */
3395 #ifdef AFS_AIX41_ENV
3398 newcred->cr_gid = RMTUSER_REQ;
3399 newcred->cr_groups[0] = g0;
3400 newcred->cr_groups[1] = g1;
3402 newcred->cr_ngrps = 2;
3404 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3405 newcred->cr_ngroups = 2;
3407 for (i=2; i<NGROUPS; i++)
3408 newcred->cr_groups[i] = NOGROUP;
3411 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3412 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3414 if (!(exporter = exporter_find(exporter_type))) {
3415 /* Exporter wasn't initialized or an invalid exporter type */
3419 if (exporter->exp_states & EXP_PWSYNC) {
3420 if (uid != credp->cr_uid) {
3422 return ENOEXEC; /* XXX Find a better errno XXX */
3425 newcred->cr_uid = uid; /* Only temporary */
3426 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3427 /* The client's pag is the only unique identifier for it */
3428 newcred->cr_uid = pag;
3430 if (!code && *com == PSETPAG) {
3431 /* Special case for 'setpag' */
3432 afs_uint32 pagvalue = genpag();
3434 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3436 * Note that we leave the 'outexporter' struct held so it won't
3439 au->exporter = outexporter;
3440 if (ablob->out_size >= 4) {
3441 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3443 afs_PutUser(au, WRITE_LOCK);
3444 if (code) return code;
3445 return PSETPAG; /* Special return for setpag */
3447 EXP_RELE(outexporter);
3450 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3453 /* get all interface addresses of this client */
3456 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3459 struct vrequest *areq;
3462 afs_int32 *aoutSize;
3464 struct sprefrequest *spin; /* input */
3465 struct sprefinfo *spout; /* output */
3466 struct spref *srvout; /* one output component */
3470 AFS_STATCNT(PGetCPrefs);
3471 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3472 return EIO; /* Inappropriate ioctl for device */
3474 if ( ainSize < sizeof (struct sprefrequest ))
3477 spin = (struct sprefrequest *) ain;
3478 spout = (struct sprefinfo *) aout;
3480 maxNumber = spin->num_servers; /* max addrs this time */
3481 srvout = spout->servers;
3483 ObtainReadLock(&afs_xinterface);
3485 /* copy out the client interface information from the
3486 ** kernel data structure "interface" to the output buffer
3488 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3489 && ( j< maxNumber) ; i++, j++, srvout++)
3490 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3492 spout->num_servers = j;
3493 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3495 if ( i >= afs_cb_interface.numberOfInterfaces )
3496 spout->next_offset = 0; /* start from beginning again */
3498 spout->next_offset = spin->offset + j;
3500 ReleaseReadLock(&afs_xinterface);
3505 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3508 struct vrequest *areq;
3511 afs_int32 *aoutSize;
3513 struct setspref *sin;
3516 AFS_STATCNT(PSetCPrefs);
3517 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3518 return EIO; /* Inappropriate ioctl for device */
3520 sin = (struct setspref *)ain;
3522 if ( ainSize < sizeof(struct setspref) )
3524 #if 0 /* num_servers is unsigned */
3525 if ( sin->num_servers < 0 )
3528 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3531 ObtainWriteLock(&afs_xinterface, 412);
3532 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3533 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3534 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3536 ReleaseWriteLock(&afs_xinterface);
3540 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3543 struct vrequest *areq;
3546 afs_int32 *aoutSize;
3547 struct AFS_UCRED *acred; {
3548 register afs_int32 code;
3549 register struct vcache *tvc;
3550 register struct dcache *tdc;
3551 struct VenusFid tfid;
3553 struct sysname_info sysState;
3554 afs_int32 offset, len;
3556 AFS_STATCNT(PFlushMount);
3557 if (!avc) return EINVAL;
3558 code = afs_VerifyVCache(avc, areq);
3559 if (code) return code;
3560 if (vType(avc) != VDIR) {
3563 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3564 if (!tdc) return ENOENT;
3565 Check_AtSys(avc, ain, &sysState, areq);
3567 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3568 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3569 bufp = sysState.name;
3574 tfid.Cell = avc->fid.Cell;
3575 tfid.Fid.Volume = avc->fid.Fid.Volume;
3576 afs_PutDCache(tdc); /* we're done with the data */
3577 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3578 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3580 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3587 if (vType(tvc) != VLNK) {
3588 afs_PutVCache(tvc, WRITE_LOCK);
3592 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3593 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3595 ObtainWriteLock(&tvc->lock,645);
3596 ObtainWriteLock(&afs_xcbhash, 646);
3597 afs_DequeueCallback(tvc);
3598 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3599 ReleaseWriteLock(&afs_xcbhash);
3600 /* now find the disk cache entries */
3601 afs_TryToSmush(tvc, acred, 1);
3602 osi_dnlc_purgedp(tvc);
3603 afs_symhint_inval(tvc);
3604 if (tvc->linkData && !(tvc->states & CCore)) {
3605 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3606 tvc->linkData = (char *) 0;
3608 ReleaseWriteLock(&tvc->lock);
3609 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3610 afs_BozonUnlock(&tvc->pvnLock, tvc);
3612 afs_PutVCache(tvc, WRITE_LOCK);
3614 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3618 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3621 struct vrequest *areq;
3624 afs_int32 *aoutSize;
3625 struct AFS_UCRED *acred;
3630 if (!afs_osi_suser(acred)) {
3634 if (ainSize != sizeof(afs_int32)) {
3638 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3639 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3643 if (flags & AFSCALL_RXSTATS_ENABLE) {
3644 rx_enableProcessRPCStats();
3646 if (flags & AFSCALL_RXSTATS_DISABLE) {
3647 rx_disableProcessRPCStats();
3649 if (flags & AFSCALL_RXSTATS_CLEAR) {
3650 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3658 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3661 struct vrequest *areq;
3664 afs_int32 *aoutSize;
3665 struct AFS_UCRED *acred;
3670 if (!afs_osi_suser(acred)) {
3674 if (ainSize != sizeof(afs_int32)) {
3678 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3679 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3683 if (flags & AFSCALL_RXSTATS_ENABLE) {
3684 rx_enablePeerRPCStats();
3686 if (flags & AFSCALL_RXSTATS_DISABLE) {
3687 rx_disablePeerRPCStats();
3689 if (flags & AFSCALL_RXSTATS_CLEAR) {
3690 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3697 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3700 struct vrequest *areq;
3703 afs_int32 *aoutSize; /* set this */
3705 register afs_int32 code, code1;
3708 struct rx_call *tcall;
3709 struct AFSVolSync tsync;
3710 struct AFSFetchStatus OutStatus;
3711 struct AFSCallBack CallBack;
3712 struct VenusFid tfid;
3717 AFS_STATCNT(PSetAcl);
3721 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3722 Fid = (struct AFSFid *) ain;
3724 Fid = &avc->fid.Fid;
3725 tfid.Cell = avc->fid.Cell;
3726 tfid.Fid.Volume = Fid->Volume;
3727 tfid.Fid.Vnode = Fid->Vnode;
3728 tfid.Fid.Unique = Fid->Unique;
3730 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3733 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3734 ICL_TYPE_POINTER, tvc,
3735 ICL_TYPE_FID, &tfid,
3736 ICL_TYPE_FID, &avc->fid);
3739 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3740 ICL_TYPE_POINTER, tvc,
3741 ICL_TYPE_FID, &tfid,
3742 ICL_TYPE_FID, &tvc->fid);
3745 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3748 #ifdef RX_ENABLE_LOCKS
3750 #endif /* RX_ENABLE_LOCKS */
3751 tcall = rx_NewCall(tc->id);
3752 code = StartRXAFS_FetchData(tcall,
3753 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3755 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3756 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3758 code1 = rx_EndCall(tcall, code);
3759 #ifdef RX_ENABLE_LOCKS
3761 #endif /* RX_ENABLE_LOCKS */
3765 (afs_Analyze(tc, code, &tvc->fid, areq,
3766 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3768 /* This call is done only to have the callback things handled correctly */
3769 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3770 afs_PutVCache(tvc, WRITE_LOCK);
3773 *aoutSize = sizeof(afs_int32);
3778 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3781 struct vrequest *areq;
3784 afs_int32 *aoutSize; /* set this */
3786 register afs_int32 code;
3789 struct ResidencyCmdInputs *Inputs;
3790 struct ResidencyCmdOutputs *Outputs;
3791 struct VenusFid tfid;
3794 Inputs = (struct ResidencyCmdInputs *) ain;
3795 Outputs = (struct ResidencyCmdOutputs *) aout;
3796 if (!avc) return EINVAL;
3797 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3801 Fid = &avc->fid.Fid;
3803 tfid.Cell = avc->fid.Cell;
3804 tfid.Fid.Volume = Fid->Volume;
3805 tfid.Fid.Vnode = Fid->Vnode;
3806 tfid.Fid.Unique = Fid->Unique;
3808 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3810 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3811 ICL_TYPE_POINTER, tvc,
3812 ICL_TYPE_INT32, Inputs->command,
3813 ICL_TYPE_FID, &tfid);
3817 if (Inputs->command) {
3819 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3821 #ifdef RX_ENABLE_LOCKS
3823 #endif /* RX_ENABLE_LOCKS */
3824 code = RXAFS_ResidencyCmd(tc->id, Fid,
3826 (struct ResidencyCmdOutputs *) aout);
3827 #ifdef RX_ENABLE_LOCKS
3829 #endif /* RX_ENABLE_LOCKS */
3833 (afs_Analyze(tc, code, &tvc->fid, areq,
3834 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3836 /* This call is done to have the callback things handled correctly */
3837 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3838 } else { /* just a status request, return also link data */
3840 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3841 Outputs->chars[0] = 0;
3842 if (vType(tvc) == VLNK) {
3843 ObtainWriteLock(&tvc->lock,555);
3844 if (afs_HandleLink(tvc, areq) == 0)
3845 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3846 ReleaseWriteLock(&tvc->lock);
3850 afs_PutVCache(tvc, WRITE_LOCK);
3853 *aoutSize = sizeof(struct ResidencyCmdOutputs);