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 <afsconfig.h>
11 #include "../afs/param.h"
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* afs statistics */
18 #include "../afs/vice.h"
19 #include "../rx/rx_globals.h"
21 extern void afs_ComputePAGStats();
22 extern struct vcache *afs_LookupVCache();
23 struct VenusFid afs_rootFid;
24 afs_int32 afs_waitForever=0;
25 short afs_waitForeverCount = 0;
26 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
27 extern afs_int32 PROBE_INTERVAL;
29 extern int cacheDiskType;
30 extern afs_int32 afs_cacheBlocks;
31 extern struct afs_q CellLRU;
32 extern char *afs_indexFlags; /* only one: is there data there? */
33 extern afs_int32 afs_blocksUsed;
34 extern struct unixuser *afs_users[NUSERS];
35 extern struct server *afs_servers[NSERVERS];
36 extern struct interfaceAddr afs_cb_interface; /* client interface addresses */
37 extern afs_rwlock_t afs_xserver;
38 extern afs_rwlock_t afs_xinterface;
39 extern afs_rwlock_t afs_xcell;
40 extern afs_rwlock_t afs_xuser;
41 #ifndef AFS_FINEG_SUNLOCK
42 extern afs_rwlock_t afs_xconn;
44 extern afs_rwlock_t afs_xvolume;
45 extern afs_lock_t afs_xdcache; /* lock: alloc new disk cache entries */
46 extern afs_rwlock_t afs_xvcache;
47 extern afs_rwlock_t afs_xcbhash;
48 extern afs_int32 afs_mariner, afs_marinerHost;
49 extern struct srvAddr *afs_srvAddrs[NSERVERS];
50 extern int afs_resourceinit_flag;
51 extern afs_int32 cryptall;
53 static int PBogus(), PSetAcl(), PGetAcl(), PSetTokens(), PGetVolumeStatus();
54 static int PSetVolumeStatus(), PFlush(), PNewStatMount(), PGetTokens(), PUnlog();
55 static int PCheckServers(), PCheckVolNames(), PCheckAuth(), PFindVolume();
56 static int PViceAccess(), PSetCacheSize(), Prefetch();
57 static int PRemoveCallBack(), PNewCell(), PListCells(), PRemoveMount();
58 static int PMariner(), PGetUserCell(), PGetWSCell(), PGetFileCell();
59 static int PVenusLogging(), PNoop(), PSetCellStatus(), PGetCellStatus();
60 static int PFlushVolumeData(), PGetCacheSize();
61 static int PSetSysName(),PGetFID();
62 static int PGetVnodeXStatus();
63 static int PSetSPrefs(), PGetSPrefs(), PGag(), PTwiddleRx();
64 static int PSetSPrefs33(), PStoreBehind(), PGCPAGs();
65 static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */
66 static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer();
67 static int PGetRxkcrypt(), PSetRxkcrypt();
68 static int PPrefetchFromTape(), PResidencyCmd();
71 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
73 extern struct cm_initparams cm_initParams;
75 static int (*(pioctlSw[]))() = {
80 PGetVolumeStatus, /* 4 */
81 PSetVolumeStatus, /* 5 */
86 PCheckServers, /* 10 */
87 PCheckVolNames, /* 11 */
89 PBogus, /* 13 -- used to be quick check time */
91 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
92 PBogus, /* 16 -- used to be testing code */
93 PNoop, /* 17 -- used to be enable group */
94 PNoop, /* 18 -- used to be disable group */
95 PBogus, /* 19 -- used to be list group */
97 PUnlog, /* 21 -- unlog *is* unpag in this system */
98 PGetFID, /* 22 -- get file ID */
99 PBogus, /* 23 -- used to be waitforever */
100 PSetCacheSize, /* 24 */
101 PRemoveCallBack, /* 25 -- flush only the callback */
104 PRemoveMount, /* 28 -- delete mount point */
105 PNewStatMount, /* 29 -- new style mount point stat */
106 PGetFileCell, /* 30 -- get cell name for input file */
107 PGetWSCell, /* 31 -- get cell name for workstation */
108 PMariner, /* 32 - set/get mariner host */
109 PGetUserCell, /* 33 -- get cell name for user */
110 PVenusLogging, /* 34 -- Enable/Disable logging */
111 PGetCellStatus, /* 35 */
112 PSetCellStatus, /* 36 */
113 PFlushVolumeData, /* 37 -- flush all data from a volume */
114 PSetSysName, /* 38 - Set system name */
115 PExportAfs, /* 39 - Export Afs to remote nfs clients */
116 PGetCacheSize, /* 40 - get cache size and usage */
117 PGetVnodeXStatus, /* 41 - get vcache's special status */
118 PSetSPrefs33, /* 42 - Set CM Server preferences... */
119 PGetSPrefs, /* 43 - Get CM Server preferences... */
120 PGag, /* 44 - turn off/on all CM messages */
121 PTwiddleRx, /* 45 - adjust some RX params */
122 PSetSPrefs, /* 46 - Set CM Server preferences... */
123 PStoreBehind, /* 47 - set degree of store behind to be done */
124 PGCPAGs, /* 48 - disable automatic pag gc-ing */
125 PGetInitParams, /* 49 - get initial cm params */
126 PGetCPrefs, /* 50 - get client interface addresses */
127 PSetCPrefs, /* 51 - set client interface addresses */
128 PFlushMount, /* 52 - flush mount symlink data */
129 PRxStatProc, /* 53 - control process RX statistics */
130 PRxStatPeer, /* 54 - control peer RX statistics */
131 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
132 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
133 PNoop, /* 57 -- arla: set file prio */
134 PNoop, /* 58 -- arla: fallback getfh */
135 PNoop, /* 59 -- arla: fallback fhopen */
136 PNoop, /* 60 -- arla: controls xfsdebug */
137 PNoop, /* 61 -- arla: controls arla debug */
138 PNoop, /* 62 -- arla: debug interface */
139 PNoop, /* 63 -- arla: print xfs status */
140 PNoop, /* 64 -- arla: force cache check */
141 PNoop, /* 65 -- arla: break callback */
142 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
143 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
146 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
147 int afs_nobody = NFS_NOBODY;
150 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
152 dst->in = (char *)(unsigned long)src->in;
153 dst->out = (char *)(unsigned long)src->out;
154 dst->in_size = src->in_size;
155 dst->out_size = src->out_size;
159 * If you need to change copyin_afs_ioctl(), you may also need to change
164 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
168 #if defined(AFS_HPUX_64BIT_ENV)
169 struct afs_ioctl32 dst32;
171 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
173 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
175 afs_ioctl32_to_afs_ioctl(&dst32, dst);
178 #endif /* defined(AFS_HPUX_64BIT_ENV) */
180 #if defined(AFS_SUN57_64BIT_ENV)
181 struct afs_ioctl32 dst32;
183 if (get_udatamodel() == DATAMODEL_ILP32) {
184 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
186 afs_ioctl32_to_afs_ioctl(&dst32, dst);
189 #endif /* defined(AFS_SUN57_64BIT_ENV) */
191 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
192 struct afs_ioctl32 dst32;
194 if (!ABI_IS_64BIT(get_current_abi()))
196 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
198 afs_ioctl32_to_afs_ioctl(&dst32, dst);
201 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
203 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
204 struct afs_ioctl32 dst32;
206 #ifdef AFS_SPARC64_LINUX24_ENV
207 if (current->thread.flags & SPARC_FLAG_32BIT)
208 #elif AFS_SPARC64_LINUX20_ENV
209 if (current->tss.flags & SPARC_FLAG_32BIT)
211 #error Not done for this linux type
212 #endif /* AFS_SPARC64_LINUX20_ENV */
214 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
216 afs_ioctl32_to_afs_ioctl(&dst32, dst);
219 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
221 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
225 HandleIoctl(avc, acom, adata)
226 register struct vcache *avc;
227 register afs_int32 acom;
228 struct afs_ioctl *adata; {
229 register afs_int32 code;
232 AFS_STATCNT(HandleIoctl);
234 switch(acom & 0xff) {
236 avc->states |= CSafeStore;
240 /* case 2 used to be abort store, but this is no longer provided,
241 since it is impossible to implement under normal Unix.
245 /* return the name of the cell this file is open on */
246 register struct cell *tcell;
247 register afs_int32 i;
249 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
251 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
253 if (i > adata->out_size) {
254 /* 0 means we're not interested in the output */
255 if (adata->out_size != 0) code = EFAULT;
259 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
261 afs_PutCell(tcell, READ_LOCK);
267 case 49: /* VIOC_GETINITPARAMS */
268 if (adata->out_size < sizeof(struct cm_initparams)) {
272 AFS_COPYOUT(&cm_initParams, adata->out,
273 sizeof(struct cm_initparams), code);
282 return code; /* so far, none implemented */
287 /* For aix we don't temporarily bypass ioctl(2) but rather do our
288 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
289 * is now called from afs_gn_ioctl.
291 afs_ioctl(tvc, cmd, arg)
296 struct afs_ioctl data;
299 AFS_STATCNT(afs_ioctl);
300 if (((cmd >> 8) & 0xff) == 'V') {
301 /* This is a VICEIOCTL call */
302 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
305 error = HandleIoctl(tvc, cmd, &data);
308 /* No-op call; just return. */
312 #endif /* AFS_AIX_ENV */
314 #if defined(AFS_SGI_ENV)
315 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
321 struct afs_ioctl data;
327 AFS_STATCNT(afs_ioctl);
328 if (((cmd >> 8) & 0xff) == 'V') {
329 /* This is a VICEIOCTL call */
330 error = copyin_afs_ioctl(arg, &data);
333 locked = ISAFS_GLOCK();
336 error = HandleIoctl(tvc, cmd, &data);
341 /* No-op call; just return. */
345 #endif /* AFS_SGI_ENV */
348 /* unlike most calls here, this one uses u.u_error to return error conditions,
349 since this is really an intercepted chapter 2 call, rather than a vnode
352 /* AFS_HPUX102 and up uses VNODE ioctl instead */
353 #ifndef AFS_HPUX102_ENV
354 #if !defined(AFS_SGI_ENV)
356 kioctl(fdes, com, arg, ext)
363 } u_uap, *uap = &u_uap;
367 struct afs_ioctl_sys {
373 afs_xioctl (uap, rvp)
374 struct afs_ioctl_sys *uap;
379 afs_xioctl (p, args, retval)
388 } *uap = (struct a *)args;
389 #else /* AFS_OSF_ENV */
390 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
396 afs_xioctl(p, uap, retval)
398 register struct ioctl_args *uap;
402 #ifdef AFS_LINUX22_ENV
403 struct afs_ioctl_sys {
407 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
408 unsigned int com, unsigned long arg)
410 struct afs_ioctl_sys ua, *uap = &ua;
418 } *uap = (struct a *)u.u_ap;
419 #endif /* AFS_LINUX22_ENV */
420 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
421 #endif /* AFS_OSF_ENV */
422 #endif /* AFS_SUN5_ENV */
424 #ifndef AFS_LINUX22_ENV
425 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
428 register struct file *fd;
431 register struct vcache *tvc;
432 register int ioctlDone = 0, code = 0;
434 AFS_STATCNT(afs_xioctl);
435 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
436 if ((code=fdgetf(p, uap->fd, &fd)))
439 #ifdef AFS_LINUX22_ENV
447 if (setuerror(getf(uap->fd, &fd))) {
453 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
455 #else /* AFS_OSF_ENV */
457 #if defined(AFS_SUN57_ENV)
459 if (!fd) return(EBADF);
460 #elif defined(AFS_SUN54_ENV)
462 if (!fd) return(EBADF);
464 if (code = getf(uap->fd, &fd)) {
477 /* first determine whether this is any sort of vnode */
478 #ifdef AFS_LINUX22_ENV
479 tvc = (struct vcache *)ip;
483 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
485 if (fd->f_type == DTYPE_VNODE) {
487 /* good, this is a vnode; next see if it is an AFS vnode */
488 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
489 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
491 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
493 #endif /* AFS_LINUX22_ENV */
494 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
496 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
497 if (!tvc) { /* shouldn't happen with held gnodes */
502 /* This is an AFS vnode */
503 if (((uap->com >> 8) & 0xff) == 'V') {
504 register struct afs_ioctl *datap;
506 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
507 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
509 osi_FreeSmallSpace(datap);
511 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
514 #if defined(AFS_SUN5_ENV)
529 #else /* AFS_OSF_ENV */
533 #ifdef AFS_LINUX22_ENV
543 code = HandleIoctl(tvc, uap->com, datap);
544 osi_FreeSmallSpace(datap);
558 #if defined(AFS_LINUX22_ENV)
568 code = okioctl(fdes, com, arg, ext);
572 okioctl(fdes, com, arg, ext);
574 #if defined(AFS_SUN5_ENV)
575 #if defined(AFS_SUN57_ENV)
577 #elif defined(AFS_SUN54_ENV)
582 code = ioctl(uap, rvp);
584 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
585 return ioctl(p, uap, retval);
588 code = ioctl(p, args, retval);
595 #else /* AFS_OSF_ENV */
596 #ifndef AFS_LINUX22_ENV
614 #ifdef AFS_LINUX22_ENV
617 #if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
620 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
621 return (getuerror() ? -1 : u.u_ioctlrv);
623 return getuerror() ? -1 : 0;
626 #endif /* AFS_LINUX22_ENV */
627 #endif /* AFS_SUN5_ENV */
628 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
632 #endif /* AFS_SGI_ENV */
633 #endif /* AFS_HPUX102_ENV */
635 #if defined(AFS_SGI_ENV)
636 /* "pioctl" system call entry point; just pass argument to the parameterized
645 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
649 AFS_STATCNT(afs_pioctl);
651 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
659 #endif /* AFS_SGI_ENV */
662 afs_pioctl(p, args, retval)
672 } *uap = (struct a *) args;
674 AFS_STATCNT(afs_pioctl);
675 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
678 extern struct mount *afs_globalVFS;
679 #else /* AFS_OSF_ENV */
680 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
681 afs_pioctl(p, args, retval)
691 } *uap = (struct a *) args;
693 AFS_STATCNT(afs_pioctl);
694 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
697 extern struct mount *afs_globalVFS;
698 #else /* AFS_OSF_ENV */
699 extern struct vfs *afs_globalVFS;
703 /* macro to avoid adding any more #ifdef's to pioctl code. */
704 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
705 #define PIOCTL_FREE_CRED() crfree(credp)
707 #define PIOCTL_FREE_CRED()
711 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
713 struct AFS_UCRED *credp;
715 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
716 afs_syscall_pioctl(path, com, cmarg, follow, credp)
717 struct AFS_UCRED *credp;
719 afs_syscall_pioctl(path, com, cmarg, follow)
727 struct afs_ioctl data;
728 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
729 register afs_int32 code = 0;
735 struct ucred *credp = crref(); /* don't free until done! */
737 #ifdef AFS_LINUX22_ENV
738 cred_t *credp = crref(); /* don't free until done! */
742 AFS_STATCNT(afs_syscall_pioctl);
743 if (follow) follow = 1; /* compat. with old venus */
745 if (! _VALIDVICEIOCTL(com)) {
747 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
749 #else /* AFS_OSF_ENV */
750 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
759 code = copyin_afs_ioctl(cmarg, &data);
762 #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)
769 if ((com & 0xff) == PSetClientContext) {
770 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
771 return EINVAL; /* Not handling these yet. */
773 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
774 code = HandleClientContext(&data, &com, &foreigncreds, credp);
776 #if defined(AFS_HPUX101_ENV)
777 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
780 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
782 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
783 #endif /* AFS_SGI_ENV */
789 crfree(foreigncreds);
792 #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)
795 return (setuerror(code), code);
799 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
802 * We could have done without temporary setting the u.u_cred below
803 * (foreigncreds could be passed as param the pioctl modules)
804 * but calls such as afs_osi_suser() doesn't allow that since it
805 * references u.u_cred directly. We could, of course, do something
806 * like afs_osi_suser(cred) which, I think, is better since it
807 * generalizes and supports multi cred environments...
811 credp = foreigncreds;
814 tmpcred = crref(); /* XXX */
817 #if defined(AFS_HPUX101_ENV)
818 tmpcred = p_cred(u.u_procp);
819 set_p_cred(u.u_procp, foreigncreds);
822 tmpcred = OSI_GET_CURRENT_CRED();
823 OSI_SET_CURRENT_CRED(foreigncreds);
826 u.u_cred = foreigncreds;
827 #endif /* AFS_SGI64_ENV */
828 #endif /* AFS_HPUX101_ENV */
833 if ((com & 0xff) == 15) {
834 /* special case prefetch so entire pathname eval occurs in helper process.
835 otherwise, the pioctl call is essentially useless */
836 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
837 code = Prefetch(path, &data, follow,
838 foreigncreds ? foreigncreds : credp);
840 #if defined(AFS_HPUX101_ENV)
841 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
844 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
846 code = Prefetch(path, &data, follow, u.u_cred);
847 #endif /* AFS_SGI64_ENV */
848 #endif /* AFS_HPUX101_ENV */
850 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
853 crset(tmpcred); /* restore original credentials */
855 #if defined(AFS_HPUX101_ENV)
856 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
860 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
862 u.u_cred = tmpcred; /* restore original credentials */
865 #endif /* AFS_HPUX101_ENV */
866 crfree(foreigncreds);
869 #endif /* AFS_LINUX22_ENV */
871 #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)
874 return (setuerror(code), code);
880 code = lookupname(path, USR, follow, NULL, &vp,
881 foreigncreds ? foreigncreds : credp);
883 #ifdef AFS_LINUX22_ENV
884 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
886 vp = (struct vnode *)dp->d_inode;
888 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
889 #endif /* AFS_LINUX22_ENV */
890 #endif /* AFS_AIX41_ENV */
893 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
896 crset(tmpcred); /* restore original credentials */
898 #if defined(AFS_HPUX101_ENV)
899 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
901 #if !defined(AFS_SUN5_ENV)
903 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
905 u.u_cred = tmpcred; /* restore original credentials */
906 #endif /* AFS_SGI64_ENV */
908 #endif /* AFS_HPUX101_ENV */
909 crfree(foreigncreds);
912 #endif /* AFS_LINUX22_ENV */
914 #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)
917 return(setuerror(code), code);
921 else vp = (struct vnode *) 0;
923 /* now make the call if we were passed no file, or were passed an AFS file */
924 if (!vp || IsAfsVnode(vp)) {
926 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
927 * So, we must test in this part of the code. Also, must arrange to
928 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
929 * we hold gnodes, whose references hold our vcache entries.
932 gp = vp; /* remember for "put" */
933 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
935 else gp = (struct vnode *) 0;
938 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
942 struct ucred *cred1, *cred2;
945 cred1 = cred2 = foreigncreds;
947 cred1 = cred2 = credp;
949 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
950 if (cred1 != cred2) {
951 /* something changed the creds */
956 #if defined(AFS_HPUX101_ENV)
958 struct ucred *cred = p_cred(u.u_procp);
959 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
965 credp = OSI_GET_CURRENT_CRED();
966 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
969 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
970 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
972 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
974 #endif /* AFS_SGI_ENV */
975 #endif /* AFS_HPUX101_ENV */
976 #endif /* AFS_AIX41_ENV */
977 #endif /* AFS_SUN5_ENV */
979 #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)
980 code = EINVAL; /* not in /afs */
987 vp = (struct vnode *) 0;
992 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
997 #if defined(AFS_HPUX101_ENV)
998 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1000 #ifndef AFS_SUN5_ENV
1002 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1004 u.u_cred = tmpcred; /* restore original credentials */
1005 #endif /* ASF_SGI64_ENV */
1007 #endif /* AFS_HPUX101_ENV */
1008 crfree(foreigncreds);
1011 #endif /* AFS_LINUX22_ENV */
1013 #ifdef AFS_LINUX22_ENV
1016 AFS_RELE(vp); /* put vnode back */
1020 #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)
1025 return (getuerror());
1030 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
1031 register struct vcache *avc;
1033 struct AFS_UCRED **acred;
1034 register struct afs_ioctl *ablob;
1037 struct vrequest treq;
1038 register afs_int32 code;
1039 register afs_int32 function;
1040 afs_int32 inSize, outSize;
1041 char *inData, *outData;
1043 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1044 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1045 AFS_STATCNT(HandlePioctl);
1046 if (code = afs_InitReq(&treq, *acred)) return code;
1047 function = acom & 0xff;
1048 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
1049 return EINVAL; /* out of range */
1051 inSize = ablob->in_size;
1052 if (inSize >= PIGGYSIZE) return E2BIG;
1053 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1055 AFS_COPYIN(ablob->in, inData, inSize, code);
1059 osi_FreeLargeSpace(inData);
1062 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1064 if (function == 3) /* PSetTokens */
1065 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1067 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1068 osi_FreeLargeSpace(inData);
1069 if (code == 0 && ablob->out_size > 0) {
1070 if (outSize > ablob->out_size) outSize = ablob->out_size;
1071 if (outSize >= PIGGYSIZE) code = E2BIG;
1073 AFS_COPYOUT(outData, ablob->out, outSize, code);
1075 osi_FreeLargeSpace(outData);
1076 return afs_CheckCode(code, &treq, 41);
1079 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1082 struct vrequest *areq;
1085 afs_int32 *aoutSize; /* set this */ {
1086 register afs_int32 code;
1088 AFS_STATCNT(PGetFID);
1089 if (!avc) return EINVAL;
1090 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1091 *aoutSize = sizeof(struct VenusFid);
1095 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1098 struct vrequest *areq;
1101 afs_int32 *aoutSize; /* set this */ {
1102 register afs_int32 code;
1104 struct AFSOpaque acl;
1105 struct AFSVolSync tsync;
1106 struct AFSFetchStatus OutStatus;
1109 AFS_STATCNT(PSetAcl);
1112 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1115 acl.AFSOpaque_val = ain;
1117 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1119 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1120 #ifdef RX_ENABLE_LOCKS
1122 #endif /* RX_ENABLE_LOCKS */
1123 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1124 &acl, &OutStatus, &tsync);
1125 #ifdef RX_ENABLE_LOCKS
1127 #endif /* RX_ENABLE_LOCKS */
1132 (afs_Analyze(tconn, code, &avc->fid, areq,
1133 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1135 /* now we've forgotten all of the access info */
1136 ObtainWriteLock(&afs_xcbhash, 455);
1138 afs_DequeueCallback(avc);
1139 avc->states &= ~(CStatd | CUnique);
1140 ReleaseWriteLock(&afs_xcbhash);
1141 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1142 osi_dnlc_purgedp(avc);
1146 int afs_defaultAsynchrony = 0;
1148 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1151 struct vrequest *areq;
1154 afs_int32 *aoutSize; /* set this */
1155 struct AFS_UCRED *acred;
1158 struct sbstruct *sbr;
1160 sbr = (struct sbstruct *)ain;
1161 if (sbr->sb_default != -1) {
1162 if (afs_osi_suser(acred))
1163 afs_defaultAsynchrony = sbr->sb_default;
1167 if (avc && (sbr->sb_thisfile != -1))
1168 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1169 areq, DONT_CHECK_MODE_BITS))
1170 avc->asynchrony = sbr->sb_thisfile;
1173 *aoutSize = sizeof(struct sbstruct);
1174 sbr = (struct sbstruct *)aout;
1175 sbr->sb_default = afs_defaultAsynchrony;
1177 sbr->sb_thisfile = avc->asynchrony;
1183 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1186 struct vrequest *areq;
1189 afs_int32 *aoutSize; /* set this */
1190 struct AFS_UCRED *acred;
1192 if (!afs_osi_suser(acred)) {
1195 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1199 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1202 struct vrequest *areq;
1205 afs_int32 *aoutSize; /* set this */ {
1206 struct AFSOpaque acl;
1207 struct AFSVolSync tsync;
1208 struct AFSFetchStatus OutStatus;
1214 AFS_STATCNT(PGetAcl);
1215 if (!avc) return EINVAL;
1216 Fid.Volume = avc->fid.Fid.Volume;
1217 Fid.Vnode = avc->fid.Fid.Vnode;
1218 Fid.Unique = avc->fid.Fid.Unique;
1219 if (avc->states & CForeign) {
1221 * For a dfs xlator acl we have a special hack so that the
1222 * xlator will distinguish which type of acl will return. So
1223 * we currently use the top 2-bytes (vals 0-4) to tell which
1224 * type of acl to bring back. Horrible hack but this will
1225 * cause the least number of changes to code size and interfaces.
1227 if (Fid.Vnode & 0xc0000000)
1229 Fid.Vnode |= (ainSize << 30);
1231 acl.AFSOpaque_val = aout;
1233 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1236 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1237 #ifdef RX_ENABLE_LOCKS
1239 #endif /* RX_ENABLE_LOCKS */
1240 code = RXAFS_FetchACL(tconn->id, &Fid,
1241 &acl, &OutStatus, &tsync);
1242 #ifdef RX_ENABLE_LOCKS
1244 #endif /* RX_ENABLE_LOCKS */
1249 (afs_Analyze(tconn, code, &avc->fid, areq,
1250 AFS_STATS_FS_RPCIDX_FETCHACL,
1251 SHARED_LOCK, (struct cell *)0));
1254 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1265 AFS_STATCNT(PBogus);
1269 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1272 struct vrequest *areq;
1276 afs_int32 *aoutSize; /* set this */ {
1277 register struct cell *tcell;
1279 AFS_STATCNT(PGetFileCell);
1280 if (!avc) return EINVAL;
1281 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1282 if (!tcell) return ESRCH;
1283 strcpy(aout, tcell->cellName);
1284 afs_PutCell(tcell, READ_LOCK);
1285 *aoutSize = strlen(aout) + 1;
1289 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1292 struct vrequest *areq;
1296 afs_int32 *aoutSize; /* set this */ {
1297 register struct cell *tcell=0, *cellOne=0;
1298 register struct afs_q *cq, *tq;
1300 AFS_STATCNT(PGetWSCell);
1301 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1302 return EIO; /* Inappropriate ioctl for device */
1304 ObtainReadLock(&afs_xcell);
1305 cellOne = (struct cell *) 0;
1307 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1308 tcell = QTOC(cq); tq = QNext(cq);
1309 if (tcell->states & CPrimary) break;
1310 if (tcell->cell == 1) cellOne = tcell;
1313 ReleaseReadLock(&afs_xcell);
1314 if (!tcell) { /* no primary cell, use cell #1 */
1315 if (!cellOne) return ESRCH;
1318 strcpy(aout, tcell->cellName);
1319 *aoutSize = strlen(aout) + 1;
1323 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1326 struct vrequest *areq;
1330 afs_int32 *aoutSize; /* set this */ {
1331 register afs_int32 i;
1332 register struct unixuser *tu;
1333 register struct cell *tcell;
1335 AFS_STATCNT(PGetUserCell);
1336 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1337 return EIO; /* Inappropriate ioctl for device */
1339 /* return the cell name of the primary cell for this user */
1340 i = UHash(areq->uid);
1341 ObtainWriteLock(&afs_xuser,224);
1342 for(tu = afs_users[i]; tu; tu = tu->next) {
1343 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1345 ReleaseWriteLock(&afs_xuser);
1350 tcell = afs_GetCell(tu->cell, READ_LOCK);
1351 afs_PutUser(tu, WRITE_LOCK);
1352 if (!tcell) return ESRCH;
1354 strcpy(aout, tcell->cellName);
1355 afs_PutCell(tcell, READ_LOCK);
1356 *aoutSize = strlen(aout)+1; /* 1 for the null */
1360 ReleaseWriteLock(&afs_xuser);
1367 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1370 struct vrequest *areq;
1374 afs_int32 *aoutSize; /* set this */
1375 struct AFS_UCRED **acred;
1378 register struct unixuser *tu;
1379 struct ClearToken clear;
1380 register struct cell *tcell;
1383 struct vrequest treq;
1384 afs_int32 flag, set_parent_pag = 0;
1386 AFS_STATCNT(PSetTokens);
1387 if (!afs_resourceinit_flag) {
1390 memcpy((char *)&i, ain, sizeof(afs_int32));
1391 ain += sizeof(afs_int32);
1392 stp = ain; /* remember where the ticket is */
1393 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1395 ain += i; /* skip over ticket */
1396 memcpy((char *)&i, ain, sizeof(afs_int32));
1397 ain += sizeof(afs_int32);
1398 if (i != sizeof(struct ClearToken)) {
1401 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1402 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1403 ain += sizeof(struct ClearToken);
1404 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1405 /* still stuff left? we've got primary flag and cell name. Set these */
1406 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1407 ain += sizeof(afs_int32); /* skip id field */
1408 /* rest is cell name, look it up */
1409 if (flag & 0x8000) { /* XXX Use Constant XXX */
1413 tcell = afs_GetCellByName(ain, READ_LOCK);
1422 /* default to cell 1, primary id */
1423 flag = 1; /* primary id */
1424 i = 1; /* cell number */
1425 tcell = afs_GetCell(1, READ_LOCK);
1426 if (!tcell) goto nocell;
1428 afs_PutCell(tcell, READ_LOCK);
1429 if (set_parent_pag) {
1431 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1432 struct proc *p=current_proc(); /* XXX */
1433 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1434 p->p_pid, p->p_comm);
1435 if (!setpag(p, acred, -1, &pag, 1)) {
1438 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1440 if (!setpag(acred, -1, &pag, 1)) {
1443 afs_InitReq(&treq, *acred);
1447 /* now we just set the tokens */
1448 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1449 tu->vid = clear.ViceId;
1450 if (tu->stp != (char *) 0) {
1451 afs_osi_Free(tu->stp, tu->stLen);
1453 tu->stp = (char *) afs_osi_Alloc(stLen);
1455 memcpy(tu->stp, stp, stLen);
1458 afs_stats_cmfullperf.authent.TicketUpdates++;
1459 afs_ComputePAGStats();
1460 #endif /* AFS_NOSTATS */
1461 tu->states |= UHasTokens;
1462 tu->states &= ~UTokensBad;
1463 afs_SetPrimary(tu, flag);
1464 tu->tokenTime =osi_Time();
1465 afs_ResetUserConns(tu);
1466 afs_PutUser(tu, WRITE_LOCK);
1481 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1484 struct vrequest *areq;
1487 afs_int32 *aoutSize; /* set this */ {
1489 char offLineMsg[256];
1491 register struct conn *tc;
1492 register afs_int32 code;
1493 struct VolumeStatus volstat;
1495 char *Name, *OfflineMsg, *MOTD;
1498 AFS_STATCNT(PGetVolumeStatus);
1499 if (!avc) return EINVAL;
1501 OfflineMsg = offLineMsg;
1504 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1506 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1507 #ifdef RX_ENABLE_LOCKS
1509 #endif /* RX_ENABLE_LOCKS */
1510 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1511 &Name, &OfflineMsg, &MOTD);
1512 #ifdef RX_ENABLE_LOCKS
1514 #endif /* RX_ENABLE_LOCKS */
1519 (afs_Analyze(tc, code, &avc->fid, areq,
1520 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1521 SHARED_LOCK, (struct cell *)0));
1523 if (code) return code;
1524 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1526 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1527 cp += sizeof(VolumeStatus);
1528 strcpy(cp, volName);
1529 cp += strlen(volName)+1;
1530 strcpy(cp, offLineMsg);
1531 cp += strlen(offLineMsg)+1;
1533 cp += strlen(motd)+1;
1534 *aoutSize = (cp - aout);
1538 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1541 struct vrequest *areq;
1544 afs_int32 *aoutSize; /* set this */ {
1546 char offLineMsg[256];
1548 register struct conn *tc;
1549 register afs_int32 code;
1550 struct AFSFetchVolumeStatus volstat;
1551 struct AFSStoreVolumeStatus storeStat;
1552 register struct volume *tvp;
1556 AFS_STATCNT(PSetVolumeStatus);
1557 if (!avc) return EINVAL;
1559 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1561 if (tvp->states & (VRO | VBackup)) {
1562 afs_PutVolume(tvp, READ_LOCK);
1565 afs_PutVolume(tvp, READ_LOCK);
1568 /* Copy the junk out, using cp as a roving pointer. */
1570 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1571 cp += sizeof(AFSFetchVolumeStatus);
1572 if (strlen(cp) >= sizeof(volName))
1574 strcpy(volName, cp);
1575 cp += strlen(volName)+1;
1576 if (strlen(cp) >= sizeof(offLineMsg))
1578 strcpy(offLineMsg, cp);
1579 cp += strlen(offLineMsg)+1;
1580 if (strlen(cp) >= sizeof(motd))
1584 if (volstat.MinQuota != -1) {
1585 storeStat.MinQuota = volstat.MinQuota;
1586 storeStat.Mask |= AFS_SETMINQUOTA;
1588 if (volstat.MaxQuota != -1) {
1589 storeStat.MaxQuota = volstat.MaxQuota;
1590 storeStat.Mask |= AFS_SETMAXQUOTA;
1593 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1595 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1596 #ifdef RX_ENABLE_LOCKS
1598 #endif /* RX_ENABLE_LOCKS */
1599 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1600 &storeStat, volName, offLineMsg, motd);
1601 #ifdef RX_ENABLE_LOCKS
1603 #endif /* RX_ENABLE_LOCKS */
1608 (afs_Analyze(tc, code, &avc->fid, areq,
1609 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1610 SHARED_LOCK, (struct cell *)0));
1612 if (code) return code;
1613 /* we are sending parms back to make compat. with prev system. should
1614 change interface later to not ask for current status, just set new status */
1616 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1617 cp += sizeof(VolumeStatus);
1618 strcpy(cp, volName);
1619 cp += strlen(volName)+1;
1620 strcpy(cp, offLineMsg);
1621 cp += strlen(offLineMsg)+1;
1623 cp += strlen(motd)+1;
1624 *aoutSize = cp - aout;
1628 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1629 register struct vcache *avc;
1631 struct vrequest *areq;
1634 afs_int32 *aoutSize; /* set this */
1635 struct AFS_UCRED *acred;
1638 AFS_STATCNT(PFlush);
1639 if (!avc) return EINVAL;
1640 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1641 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1643 ObtainWriteLock(&avc->lock,225);
1644 ObtainWriteLock(&afs_xcbhash, 456);
1645 afs_DequeueCallback(avc);
1646 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1647 ReleaseWriteLock(&afs_xcbhash);
1648 /* now find the disk cache entries */
1649 afs_TryToSmush(avc, acred, 1);
1650 osi_dnlc_purgedp(avc);
1651 afs_symhint_inval(avc);
1652 if (avc->linkData && !(avc->states & CCore)) {
1653 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1654 avc->linkData = (char *) 0;
1656 ReleaseWriteLock(&avc->lock);
1657 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1658 afs_BozonUnlock(&avc->pvnLock, avc);
1663 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1666 struct vrequest *areq;
1669 afs_int32 *aoutSize; /* set this */ {
1670 register afs_int32 code;
1671 register struct vcache *tvc;
1672 register struct dcache *tdc;
1673 struct VenusFid tfid;
1675 struct sysname_info sysState;
1676 afs_int32 offset, len;
1678 AFS_STATCNT(PNewStatMount);
1679 if (!avc) return EINVAL;
1680 code = afs_VerifyVCache(avc, areq);
1681 if (code) return code;
1682 if (vType(avc) != VDIR) {
1685 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1686 if (!tdc) return ENOENT;
1687 Check_AtSys(avc, ain, &sysState, areq);
1689 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1690 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1691 bufp = sysState.name;
1696 tfid.Cell = avc->fid.Cell;
1697 tfid.Fid.Volume = avc->fid.Fid.Volume;
1698 afs_PutDCache(tdc); /* we're done with the data */
1699 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1700 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1702 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1709 if (vType(tvc) != VLNK) {
1710 afs_PutVCache(tvc, WRITE_LOCK);
1714 ObtainWriteLock(&tvc->lock,226);
1715 code = afs_HandleLink(tvc, areq);
1717 if (tvc->linkData) {
1718 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1721 /* we have the data */
1722 strcpy(aout, tvc->linkData);
1723 *aoutSize = strlen(tvc->linkData)+1;
1728 ReleaseWriteLock(&tvc->lock);
1729 afs_PutVCache(tvc, WRITE_LOCK);
1731 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1735 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1738 struct vrequest *areq;
1741 afs_int32 *aoutSize; /* set this */ {
1742 register struct cell *tcell;
1743 register afs_int32 i;
1744 register struct unixuser *tu;
1749 AFS_STATCNT(PGetTokens);
1750 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1751 return EIO; /* Inappropriate ioctl for device */
1753 /* weird interface. If input parameter is present, it is an integer and
1754 we're supposed to return the parm'th tokens for this unix uid.
1755 If not present, we just return tokens for cell 1.
1756 If counter out of bounds, return EDOM.
1757 If no tokens for the particular cell, return ENOTCONN.
1758 Also, if this mysterious parm is present, we return, along with the
1759 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1760 at the end, in that order.
1762 if (newStyle = (ainSize > 0)) {
1763 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1765 i = UHash(areq->uid);
1766 ObtainReadLock(&afs_xuser);
1767 for(tu = afs_users[i]; tu; tu=tu->next) {
1769 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1770 if (iterator-- == 0) break; /* are we done yet? */
1774 if (tu->uid == areq->uid && tu->cell == 1) break;
1779 * No need to hold a read lock on each user entry
1783 ReleaseReadLock(&afs_xuser);
1788 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1789 tu->states |= (UTokensBad | UNeedsReset);
1790 afs_PutUser(tu, READ_LOCK);
1793 /* use iterator for temp */
1795 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1796 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1797 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1798 cp += sizeof(afs_int32);
1799 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1801 iterator = sizeof(struct ClearToken);
1802 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1803 cp += sizeof(afs_int32);
1804 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1805 cp += sizeof(struct ClearToken);
1807 /* put out primary id and cell name, too */
1808 iterator = (tu->states & UPrimary ? 1 : 0);
1809 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1810 cp += sizeof(afs_int32);
1811 tcell = afs_GetCell(tu->cell, READ_LOCK);
1813 strcpy(cp, tcell->cellName);
1814 cp += strlen(tcell->cellName)+1;
1815 afs_PutCell(tcell, READ_LOCK);
1819 *aoutSize = cp - aout;
1820 afs_PutUser(tu, READ_LOCK);
1824 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1827 struct vrequest *areq;
1830 afs_int32 *aoutSize; /* set this */ {
1831 register afs_int32 i;
1832 register struct unixuser *tu;
1834 AFS_STATCNT(PUnlog);
1835 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1836 return EIO; /* Inappropriate ioctl for device */
1838 i = UHash(areq->uid);
1839 ObtainWriteLock(&afs_xuser,227);
1840 for(tu=afs_users[i]; tu; tu=tu->next) {
1841 if (tu->uid == areq->uid) {
1843 tu->states &= ~UHasTokens;
1844 /* security is not having to say you're sorry */
1845 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1847 ReleaseWriteLock(&afs_xuser);
1848 /* We have to drop the lock over the call to afs_ResetUserConns, since
1849 * it obtains the afs_xvcache lock. We could also keep the lock, and
1850 * modify ResetUserConns to take parm saying we obtained the lock
1851 * already, but that is overkill. By keeping the "tu" pointer
1852 * held over the released lock, we guarantee that we won't lose our
1853 * place, and that we'll pass over every user conn that existed when
1854 * we began this call.
1856 afs_ResetUserConns(tu);
1858 ObtainWriteLock(&afs_xuser,228);
1860 /* set the expire times to 0, causes
1861 * afs_GCUserData to remove this entry
1863 tu->ct.EndTimestamp = 0;
1865 #endif /* UKERNEL */
1868 ReleaseWriteLock(&afs_xuser);
1872 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1875 struct vrequest *areq;
1878 afs_int32 *aoutSize; /* set this */ {
1879 afs_int32 newHostAddr;
1880 afs_int32 oldHostAddr;
1882 AFS_STATCNT(PMariner);
1884 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1886 oldHostAddr = 0xffffffff; /* disabled */
1888 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1889 if (newHostAddr == 0xffffffff) {
1890 /* disable mariner operations */
1893 else if (newHostAddr) {
1895 afs_marinerHost = newHostAddr;
1897 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1898 *aoutSize = sizeof(afs_int32);
1902 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1905 struct vrequest *areq;
1908 afs_int32 *aoutSize; /* set this */
1909 struct AFS_UCRED *acred;
1911 register char *cp = 0;
1913 register struct server *ts;
1914 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1916 struct chservinfo *pcheck;
1918 AFS_STATCNT(PCheckServers);
1920 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1921 return EIO; /* Inappropriate ioctl for device */
1923 if (*lp == 0x12345678) { /* For afs3.3 version */
1924 pcheck=(struct chservinfo *)ain;
1925 if (pcheck->tinterval >= 0) {
1927 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1928 *aoutSize = sizeof(afs_int32);
1929 if (pcheck->tinterval > 0) {
1930 if (!afs_osi_suser(acred))
1932 PROBE_INTERVAL=pcheck->tinterval;
1938 temp=pcheck->tflags;
1939 cp = pcheck->tbuffer;
1940 } else { /* For pre afs3.3 versions */
1941 memcpy((char *)&temp, ain, sizeof(afs_int32));
1942 cp = ain+sizeof(afs_int32);
1943 if (ainSize > sizeof(afs_int32))
1948 * 1: fast check, don't contact servers.
1949 * 2: local cell only.
1952 /* have cell name, too */
1953 cellp = afs_GetCellByName(cp, READ_LOCK);
1954 if (!cellp) return ENOENT;
1956 else cellp = (struct cell *) 0;
1957 if (!cellp && (temp & 2)) {
1958 /* use local cell */
1959 cellp = afs_GetCell(1, READ_LOCK);
1961 if (!(temp & 1)) { /* if not fast, call server checker routine */
1962 afs_CheckServers(1, cellp); /* check down servers */
1963 afs_CheckServers(0, cellp); /* check up servers */
1965 /* now return the current down server list */
1967 ObtainReadLock(&afs_xserver);
1968 for(i=0;i<NSERVERS;i++) {
1969 for(ts = afs_servers[i]; ts; ts=ts->next) {
1970 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1971 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1972 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1973 cp += sizeof(afs_int32);
1977 ReleaseReadLock(&afs_xserver);
1978 if (cellp) afs_PutCell(cellp, READ_LOCK);
1979 *aoutSize = cp - aout;
1983 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1986 struct vrequest *areq;
1989 afs_int32 *aoutSize; /* set this */ {
1990 AFS_STATCNT(PCheckVolNames);
1991 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1992 return EIO; /* Inappropriate ioctl for device */
1994 afs_CheckRootVolume();
1995 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1996 AFS_VOLCHECK_EXPIRED |
1998 AFS_VOLCHECK_MTPTS);
2002 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
2005 struct vrequest *areq;
2008 afs_int32 *aoutSize; /* set this */ {
2012 struct unixuser *tu;
2014 extern afs_rwlock_t afs_xsrvAddr;
2016 AFS_STATCNT(PCheckAuth);
2017 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2018 return EIO; /* Inappropriate ioctl for device */
2021 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2022 if (!tu) retValue = EACCES;
2024 /* we have a user */
2025 ObtainReadLock(&afs_xsrvAddr);
2026 ObtainReadLock(&afs_xconn);
2028 /* any tokens set? */
2029 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
2030 /* all connections in cell 1 working? */
2031 for(i=0;i<NSERVERS;i++) {
2032 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
2033 for (tc = sa->conns; tc; tc=tc->next) {
2034 if (tc->user == tu && (tu->states & UTokensBad))
2039 ReleaseReadLock(&afs_xsrvAddr);
2040 ReleaseReadLock(&afs_xconn);
2041 afs_PutUser(tu, READ_LOCK);
2043 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
2044 *aoutSize = sizeof(afs_int32);
2048 static Prefetch(apath, adata, afollow, acred)
2050 struct afs_ioctl *adata;
2052 struct AFS_UCRED *acred;
2055 register afs_int32 code;
2056 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2062 AFS_STATCNT(Prefetch);
2063 if (!apath) return EINVAL;
2064 tp = osi_AllocLargeSpace(1024);
2065 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2067 osi_FreeLargeSpace(tp);
2070 if (afs_BBusy()) { /* do this as late as possible */
2071 osi_FreeLargeSpace(tp);
2072 return EWOULDBLOCK; /* pretty close */
2074 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
2078 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
2081 struct vrequest *areq;
2084 afs_int32 *aoutSize; /* set this */ {
2085 register struct volume *tvp;
2086 register struct server *ts;
2087 register afs_int32 i;
2090 AFS_STATCNT(PFindVolume);
2091 if (!avc) return EINVAL;
2092 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2095 for(i=0;i<MAXHOSTS;i++) {
2096 ts = tvp->serverHost[i];
2098 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2099 cp += sizeof(afs_int32);
2102 /* still room for terminating NULL, add it on */
2103 ainSize = 0; /* reuse vbl */
2104 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2105 cp += sizeof(afs_int32);
2107 *aoutSize = cp - aout;
2108 afs_PutVolume(tvp, READ_LOCK);
2114 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2117 struct vrequest *areq;
2120 afs_int32 *aoutSize; /* set this */ {
2121 register afs_int32 code;
2124 AFS_STATCNT(PViceAccess);
2125 if (!avc) return EINVAL;
2126 code = afs_VerifyVCache(avc, areq);
2127 if (code) return code;
2128 memcpy((char *)&temp, ain, sizeof(afs_int32));
2129 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2134 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2137 struct vrequest *areq;
2140 afs_int32 *aoutSize; /* set this */
2141 struct AFS_UCRED *acred;
2146 AFS_STATCNT(PSetCacheSize);
2147 if (!afs_osi_suser(acred))
2149 /* too many things are setup initially in mem cache version */
2150 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2151 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2152 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2154 extern u_int afs_min_cache;
2155 if (newValue < afs_min_cache)
2156 afs_cacheBlocks = afs_min_cache;
2158 afs_cacheBlocks = newValue;
2160 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2161 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2162 afs_MaybeWakeupTruncateDaemon();
2163 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2164 afs_osi_Wait(1000, 0, 0);
2165 afs_MaybeWakeupTruncateDaemon();
2170 #define MAXGCSTATS 16
2171 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2174 struct vrequest *areq;
2177 afs_int32 *aoutSize; /* set this */ {
2178 afs_int32 results[MAXGCSTATS];
2180 AFS_STATCNT(PGetCacheSize);
2181 memset((char *)results, 0, sizeof(results));
2182 results[0] = afs_cacheBlocks;
2183 results[1] = afs_blocksUsed;
2184 memcpy(aout, (char *)results, sizeof(results));
2185 *aoutSize = sizeof(results);
2189 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2192 struct vrequest *areq;
2195 afs_int32 *aoutSize; /* set this */ {
2196 register struct conn *tc;
2197 register afs_int32 code;
2198 struct AFSCallBack CallBacks_Array[1];
2199 struct AFSCBFids theFids;
2200 struct AFSCBs theCBs;
2203 AFS_STATCNT(PRemoveCallBack);
2204 if (!avc) return EINVAL;
2205 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2206 ObtainWriteLock(&avc->lock,229);
2207 theFids.AFSCBFids_len = 1;
2208 theCBs.AFSCBs_len = 1;
2209 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2210 theCBs.AFSCBs_val = CallBacks_Array;
2211 CallBacks_Array[0].CallBackType = CB_DROPPED;
2212 if (avc->callback) {
2214 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2216 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2217 #ifdef RX_ENABLE_LOCKS
2219 #endif /* RX_ENABLE_LOCKS */
2220 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2221 #ifdef RX_ENABLE_LOCKS
2223 #endif /* RX_ENABLE_LOCKS */
2226 /* don't set code on failure since we wouldn't use it */
2228 (afs_Analyze(tc, code, &avc->fid, areq,
2229 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2230 SHARED_LOCK, (struct cell *)0));
2232 ObtainWriteLock(&afs_xcbhash, 457);
2233 afs_DequeueCallback(avc);
2235 avc->states &= ~(CStatd | CUnique);
2236 ReleaseWriteLock(&afs_xcbhash);
2237 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2238 osi_dnlc_purgedp(avc);
2240 ReleaseWriteLock(&avc->lock);
2244 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2247 struct vrequest *areq;
2251 struct AFS_UCRED *acred;
2252 afs_int32 *aoutSize; /* set this */ {
2253 /* create a new cell */
2254 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2255 register struct cell *tcell;
2256 char *newcell=0, *linkedcell=0, *tp= ain;
2257 register afs_int32 code, linkedstate=0, ls;
2258 u_short fsport = 0, vlport = 0;
2261 AFS_STATCNT(PNewCell);
2262 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2263 return EIO; /* Inappropriate ioctl for device */
2265 if (!afs_osi_suser(acred))
2268 memcpy((char *)&magic, tp, sizeof(afs_int32));
2269 tp += sizeof(afs_int32);
2270 if (magic != 0x12345678)
2273 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2274 * server addresses while the 3.5 fs newcell command passes
2275 * MAXHOSTS. To figure out which is which, check if the cellname
2278 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2279 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2281 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2282 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2283 tp += (scount * sizeof(afs_int32));
2285 lp = (afs_int32 *)tp;
2288 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2289 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2290 tp += (3 * sizeof(afs_int32));
2292 if ((ls = *lp) & 1) {
2293 linkedcell = tp + strlen(newcell)+1;
2294 linkedstate |= CLinkedCell;
2297 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2298 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0);
2302 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2305 struct vrequest *areq;
2308 afs_int32 *aoutSize; /* set this */ {
2309 afs_int32 whichCell;
2310 register struct cell *tcell=0;
2311 register afs_int32 i;
2312 register char *cp, *tp = ain;
2313 register struct afs_q *cq, *tq;
2315 AFS_STATCNT(PListCells);
2316 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2317 return EIO; /* Inappropriate ioctl for device */
2319 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2320 tp += sizeof(afs_int32);
2321 ObtainReadLock(&afs_xcell);
2322 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2323 tcell = QTOC(cq); tq = QNext(cq);
2324 if (whichCell == 0) break;
2325 if (tq == &CellLRU) tcell = 0;
2330 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2331 for(i=0;i<MAXCELLHOSTS;i++) {
2332 if (tcell->cellHosts[i] == 0) break;
2333 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2334 cp += sizeof(afs_int32);
2336 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2337 strcpy(cp, tcell->cellName);
2338 cp += strlen(tcell->cellName)+1;
2339 *aoutSize = cp - aout;
2341 ReleaseReadLock(&afs_xcell);
2342 if (tcell) return 0;
2346 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2349 struct vrequest *areq;
2353 afs_int32 *aoutSize; /* set this */ {
2354 register afs_int32 code;
2356 struct sysname_info sysState;
2357 afs_int32 offset, len;
2358 register struct conn *tc;
2359 register struct dcache *tdc;
2360 register struct vcache *tvc;
2361 struct AFSFetchStatus OutDirStatus;
2362 struct VenusFid tfid;
2363 struct AFSVolSync tsync;
2367 /* "ain" is the name of the file in this dir to remove */
2369 AFS_STATCNT(PRemoveMount);
2370 if (!avc) return EINVAL;
2371 code = afs_VerifyVCache(avc, areq);
2372 if (code) return code;
2373 if (vType(avc) != VDIR) return ENOTDIR;
2375 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2376 if (!tdc) return ENOENT;
2377 Check_AtSys(avc, ain, &sysState, areq);
2379 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2380 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2381 bufp = sysState.name;
2386 tfid.Cell = avc->fid.Cell;
2387 tfid.Fid.Volume = avc->fid.Fid.Volume;
2388 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2389 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2391 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2392 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2399 if (vType(tvc) != VLNK) {
2401 afs_PutVCache(tvc, WRITE_LOCK);
2405 ObtainWriteLock(&tvc->lock,230);
2406 code = afs_HandleLink(tvc, areq);
2408 if (tvc->linkData) {
2409 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2414 ReleaseWriteLock(&tvc->lock);
2415 osi_dnlc_purgedp(tvc);
2416 afs_PutVCache(tvc, WRITE_LOCK);
2421 ObtainWriteLock(&avc->lock,231);
2422 osi_dnlc_remove(avc, bufp, tvc);
2424 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2426 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2427 #ifdef RX_ENABLE_LOCKS
2429 #endif /* RX_ENABLE_LOCKS */
2430 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2431 bufp, &OutDirStatus, &tsync);
2432 #ifdef RX_ENABLE_LOCKS
2434 #endif /* RX_ENABLE_LOCKS */
2439 (afs_Analyze(tc, code, &avc->fid, areq,
2440 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2441 SHARED_LOCK, (struct cell *)0));
2444 if (tdc) afs_PutDCache(tdc);
2445 ReleaseWriteLock(&avc->lock);
2449 /* we have the thing in the cache */
2450 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2451 /* we can do it locally */
2452 code = afs_dir_Delete(&tdc->f.inode, bufp);
2454 ZapDCE(tdc); /* surprise error -- invalid value */
2455 DZap(&tdc->f.inode);
2458 afs_PutDCache(tdc); /* drop ref count */
2460 avc->states &= ~CUnique; /* For the dfs xlator */
2461 ReleaseWriteLock(&avc->lock);
2464 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2468 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2471 struct vrequest *areq;
2475 struct AFS_UCRED *acred;
2476 afs_int32 *aoutSize; /* set this */ {
2477 return EINVAL; /* OBSOLETE */
2480 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2483 struct vrequest *areq;
2486 afs_int32 *aoutSize; /* set this */ {
2487 register struct cell *tcell;
2490 AFS_STATCNT(PGetCellStatus);
2491 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2492 return EIO; /* Inappropriate ioctl for device */
2494 tcell = afs_GetCellByName(ain, READ_LOCK);
2495 if (!tcell) return ENOENT;
2496 temp = tcell->states;
2497 afs_PutCell(tcell, READ_LOCK);
2498 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2499 *aoutSize = sizeof(afs_int32);
2503 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2506 struct vrequest *areq;
2509 struct AFS_UCRED *acred;
2510 afs_int32 *aoutSize; /* set this */ {
2511 register struct cell *tcell;
2514 if (!afs_osi_suser(acred))
2516 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2517 return EIO; /* Inappropriate ioctl for device */
2519 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2520 if (!tcell) return ENOENT;
2521 memcpy((char *)&temp, ain, sizeof(afs_int32));
2523 tcell->states |= CNoSUID;
2525 tcell->states &= ~CNoSUID;
2526 afs_PutCell(tcell, WRITE_LOCK);
2530 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2533 struct vrequest *areq;
2536 afs_int32 *aoutSize; /* set this */
2537 struct AFS_UCRED *acred;
2539 extern struct volume *afs_volumes[NVOLS];
2540 register afs_int32 i;
2541 register struct dcache *tdc;
2542 register struct vcache *tvc;
2543 register struct volume *tv;
2544 afs_int32 cell, volume;
2546 AFS_STATCNT(PFlushVolumeData);
2549 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2550 return EIO; /* Inappropriate ioctl for device */
2552 volume = avc->fid.Fid.Volume; /* who to zap */
2553 cell = avc->fid.Cell;
2556 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2557 * the vcaches associated with the volume.
2559 ObtainReadLock(&afs_xvcache);
2560 for(i = 0; i < VCSIZE; i++) {
2561 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2562 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2563 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2564 VN_HOLD((struct vnode *)tvc);
2566 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2572 ReleaseReadLock(&afs_xvcache);
2573 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2574 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2576 ObtainWriteLock(&tvc->lock,232);
2578 ObtainWriteLock(&afs_xcbhash, 458);
2579 afs_DequeueCallback(tvc);
2580 tvc->states &= ~(CStatd | CDirty);
2581 ReleaseWriteLock(&afs_xcbhash);
2582 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2583 osi_dnlc_purgedp(tvc);
2584 afs_TryToSmush(tvc, acred, 1);
2585 ReleaseWriteLock(&tvc->lock);
2586 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2587 afs_BozonUnlock(&tvc->pvnLock, tvc);
2589 ObtainReadLock(&afs_xvcache);
2590 /* our tvc ptr is still good until now */
2595 ReleaseReadLock(&afs_xvcache);
2598 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2599 for(i=0;i<afs_cacheFiles;i++) {
2600 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2601 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2602 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2603 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2604 if (! (afs_indexFlags[i] & IFDataMod)) {
2605 /* if the file is modified, but has a ref cnt of only 1, then
2606 someone probably has the file open and is writing into it.
2607 Better to skip flushing such a file, it will be brought back
2608 immediately on the next write anyway.
2610 If we *must* flush, then this code has to be rearranged to call
2611 afs_storeAllSegments() first */
2612 afs_FlushDCache(tdc);
2616 tdc->refCount--; /* bumped by getdslot */
2618 MReleaseWriteLock(&afs_xdcache);
2620 ObtainReadLock(&afs_xvolume);
2621 for (i=0;i<NVOLS;i++) {
2622 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2623 if (tv->volume == volume) {
2624 afs_ResetVolumeInfo(tv);
2629 ReleaseReadLock(&afs_xvolume);
2631 /* probably, a user is doing this, probably, because things are screwed up.
2632 * maybe it's the dnlc's fault? */
2639 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2642 struct vrequest *areq;
2645 afs_int32 *aoutSize; /* set this */ {
2646 register afs_int32 code;
2647 struct vcxstat stat;
2650 /* AFS_STATCNT(PGetVnodeXStatus); */
2651 if (!avc) return EINVAL;
2652 code = afs_VerifyVCache(avc, areq);
2653 if (code) return code;
2654 if (vType(avc) == VDIR)
2655 mode = PRSFS_LOOKUP;
2658 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2660 stat.fid = avc->fid;
2661 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2662 stat.lock = avc->lock;
2663 stat.parentVnode = avc->parentVnode;
2664 stat.parentUnique = avc->parentUnique;
2665 hset(stat.flushDV, avc->flushDV);
2666 hset(stat.mapDV, avc->mapDV);
2667 stat.truncPos = avc->truncPos;
2668 { /* just grab the first two - won't break anything... */
2669 struct axscache *ac;
2671 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2672 stat.randomUid[i] = ac->uid;
2673 stat.randomAccess[i] = ac->axess;
2676 stat.callback = afs_data_pointer_to_int32(avc->callback);
2677 stat.cbExpires = avc->cbExpires;
2678 stat.anyAccess = avc->anyAccess;
2679 stat.opens = avc->opens;
2680 stat.execsOrWriters = avc->execsOrWriters;
2681 stat.flockCount = avc->flockCount;
2682 stat.mvstat = avc->mvstat;
2683 stat.states = avc->states;
2684 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2685 *aoutSize = sizeof(struct vcxstat);
2690 /* We require root for local sysname changes, but not for remote */
2691 /* (since we don't really believe remote uids anyway) */
2692 /* outname[] shouldn't really be needed- this is left as an excercise */
2693 /* for the reader. */
2694 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2697 struct vrequest *areq;
2700 afs_int32 *aoutSize; /* set this */
2701 register struct AFS_UCRED *acred;
2703 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2704 int setsysname, foundname=0;
2705 register struct afs_exporter *exporter;
2706 extern struct unixuser *afs_FindUser();
2707 extern char *afs_sysname;
2708 extern char *afs_sysnamelist[];
2709 extern int afs_sysnamecount;
2710 register struct unixuser *au;
2711 register afs_int32 pag, error;
2715 AFS_STATCNT(PSetSysName);
2716 if (!afs_globalVFS) {
2717 /* Afsd is NOT running; disable it */
2718 #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)
2721 return (setuerror(EINVAL), EINVAL);
2724 memset(inname, 0, MAXSYSNAME);
2725 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2726 ain += sizeof(afs_int32);
2730 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2732 for(cp = ain,count = 0;count < setsysname;count++) {
2733 /* won't go past end of ain since maxsysname*num < ain length */
2735 if (t >= MAXSYSNAME || t <= 0)
2737 /* check for names that can shoot us in the foot */
2738 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2744 /* inname gets first entry in case we're being a translater */
2746 memcpy(inname, ain, t+1); /* include terminating null */
2749 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2750 pag = PagInCred(acred);
2752 return EINVAL; /* Better than panicing */
2754 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2755 return EINVAL; /* Better than panicing */
2757 if (!(exporter = au->exporter)) {
2758 afs_PutUser(au, READ_LOCK);
2759 return EINVAL; /* Better than panicing */
2761 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2763 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2765 afs_PutUser(au, READ_LOCK);
2770 afs_PutUser(au, READ_LOCK);
2773 /* Not xlating, so local case */
2774 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2775 if (!setsysname) { /* user just wants the info */
2776 strcpy(outname, afs_sysname);
2777 foundname = afs_sysnamecount;
2778 } else { /* Local guy; only root can change sysname */
2779 if (!afs_osi_suser(acred))
2782 /* clear @sys entries from the dnlc, once afs_lookup can
2783 do lookups of @sys entries and thinks it can trust them */
2784 /* privs ok, store the entry, ... */
2785 strcpy(afs_sysname, inname);
2786 if (setsysname > 1) { /* ... or list */
2788 for(count=1; count < setsysname;++count) {
2789 if (!afs_sysnamelist[count])
2790 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2792 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2796 afs_sysnamecount = setsysname;
2800 cp = aout; /* not changing so report back the count and ... */
2801 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2802 cp += sizeof(afs_int32);
2804 strcpy(cp, outname); /* ... the entry, ... */
2805 cp += strlen(outname)+1;
2806 for(count=1; count < foundname; ++count) { /* ... or list. */
2807 /* Note: we don't support @sys lists for exporters */
2808 if (!afs_sysnamelist[count])
2809 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2810 t = strlen(afs_sysnamelist[count]);
2811 if (t >= MAXSYSNAME)
2812 osi_Panic("PSetSysName: sysname entry garbled\n");
2813 strcpy(cp, afs_sysnamelist[count]);
2817 *aoutSize = cp - aout;
2822 /* sequential search through the list of touched cells is not a good
2823 * long-term solution here. For small n, though, it should be just
2824 * fine. Should consider special-casing the local cell for large n.
2825 * Likewise for PSetSPrefs.
2827 static void ReSortCells(s,l, vlonly)
2828 int s; /* number of ids in array l[] -- NOT index of last id */
2829 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2830 int vlonly; /* sort vl servers or file servers?*/
2832 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2841 tcell = afs_GetCell(l[k], WRITE_LOCK);
2842 if (!tcell) continue;
2843 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2844 afs_PutCell(tcell, WRITE_LOCK);
2849 ObtainReadLock(&afs_xvolume);
2850 for (i= 0; i< NVOLS; i++) {
2851 for (j=afs_volumes[i];j;j=j->next) {
2853 if (j->cell == l[k]) {
2854 ObtainWriteLock(&j->lock,233);
2855 afs_SortServers(j->serverHost, MAXHOSTS);
2856 ReleaseWriteLock(&j->lock);
2861 ReleaseReadLock(&afs_xvolume);
2866 static int afs_setsprefs(sp, num, vlonly)
2869 unsigned int vlonly;
2872 int i,j,k,matches,touchedSize;
2873 struct server *srvr = NULL;
2874 afs_int32 touched[34];
2878 for (k=0; k < num; sp++, k++) {
2880 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2883 ObtainReadLock(&afs_xserver);
2885 i = SHash(sp->host.s_addr);
2886 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2887 if (sa->sa_ip == sp->host.s_addr) {
2889 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2890 || (sa->sa_portal == AFS_FSPORT);
2891 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2898 if (sa && matches) { /* found one! */
2900 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2902 sa->sa_iprank = sp->rank + afs_randomMod15();
2903 afs_SortOneServer(sa->server);
2906 /* if we don't know yet what cell it's in, this is moot */
2907 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2908 /* is it in our list of touched cells ? */ ;
2909 if (j < 0) { /* no, it's not */
2910 touched[touchedSize++] = srvr->cell->cell;
2911 if (touchedSize >= 32) { /* watch for ovrflow */
2912 ReleaseReadLock(&afs_xserver);
2913 ReSortCells(touchedSize, touched, vlonly);
2915 ObtainReadLock(&afs_xserver);
2921 ReleaseReadLock(&afs_xserver);
2922 /* if we didn't find one, start to create one. */
2923 /* Note that it doesn't have a cell yet... */
2925 afs_uint32 temp = sp->host.s_addr;
2926 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2927 WRITE_LOCK, (afsUUID *)0,0);
2928 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2929 afs_PutServer(srvr, WRITE_LOCK);
2931 } /* for all cited preferences */
2933 ReSortCells(touchedSize, touched, vlonly);
2937 /* Note that this may only be performed by the local root user.
2940 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2943 struct vrequest *areq;
2946 struct AFS_UCRED *acred;
2947 afs_int32 *aoutSize;
2949 struct setspref *ssp;
2950 AFS_STATCNT(PSetSPrefs);
2952 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2953 return EIO; /* Inappropriate ioctl for device */
2955 if (!afs_osi_suser(acred))
2958 if (ainSize < sizeof(struct setspref))
2961 ssp = (struct setspref *)ain;
2962 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2965 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2966 (ssp->flags & DBservers));
2971 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2974 struct vrequest *areq;
2977 struct AFS_UCRED *acred;
2978 afs_int32 *aoutSize;
2981 AFS_STATCNT(PSetSPrefs);
2982 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2983 return EIO; /* Inappropriate ioctl for device */
2986 if (!afs_osi_suser(acred))
2989 sp = (struct spref *)ain;
2990 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2994 /* some notes on the following code...
2995 * in the hash table of server structs, all servers with the same IP address
2996 * will be on the same overflow chain.
2997 * This could be sped slightly in some circumstances by having it cache the
2998 * immediately previous slot in the hash table and some supporting information
2999 * Only reports file servers now.
3002 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3005 struct vrequest *areq;
3008 afs_int32 *aoutSize;
3010 struct sprefrequest *spin; /* input */
3011 struct sprefinfo *spout; /* output */
3012 struct spref *srvout; /* one output component */
3013 int i,j; /* counters for hash table traversal */
3014 struct server *srvr; /* one of CM's server structs */
3017 int vlonly; /* just return vlservers ? */
3020 AFS_STATCNT(PGetSPrefs);
3021 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3022 return EIO; /* Inappropriate ioctl for device */
3025 if (ainSize < sizeof (struct sprefrequest_33)) {
3029 spin = ((struct sprefrequest *) ain);
3032 if (ainSize > sizeof (struct sprefrequest_33)) {
3033 vlonly = (spin->flags & DBservers);
3037 /* struct sprefinfo includes 1 server struct... that size gets added
3038 * in during the loop that follows.
3040 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
3041 spout = (struct sprefinfo *) aout;
3042 spout->next_offset = spin->offset;
3043 spout->num_servers = 0;
3044 srvout = spout->servers;
3046 ObtainReadLock(&afs_xserver);
3047 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
3048 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
3049 if (spin->offset > (unsigned short)i) {
3050 continue; /* catch up to where we left off */
3052 spout->next_offset++;
3055 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3056 || (sa->sa_portal == AFS_FSPORT);
3058 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3059 /* only report ranks for vl servers */
3063 srvout->host.s_addr = sa->sa_ip;
3064 srvout->rank = sa->sa_iprank;
3065 *aoutSize += sizeof(struct spref);
3066 spout->num_servers++;
3069 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3070 ReleaseReadLock(&afs_xserver); /* no more room! */
3075 ReleaseReadLock(&afs_xserver);
3077 spout->next_offset = 0; /* start over from the beginning next time */
3081 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3082 int afs_NFSRootOnly = 1;
3083 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3086 struct vrequest *areq;
3089 afs_int32 *aoutSize; /* set this */
3090 struct AFS_UCRED *acred;
3092 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
3093 extern struct afs_exporter *exporter_find();
3094 register struct afs_exporter *exporter;
3096 AFS_STATCNT(PExportAfs);
3097 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
3098 type = handleValue >> 24;
3103 exporter = exporter_find(type);
3105 export = handleValue & 3;
3106 changestate = handleValue & 0xff;
3107 smounts = (handleValue >> 2) & 3;
3108 pwsync = (handleValue >> 4) & 3;
3109 convmode = (handleValue >> 6) & 3;
3111 changestate = (handleValue >> 16) & 0x1;
3112 convmode = (handleValue >> 16) & 0x2;
3113 pwsync = (handleValue >> 16) & 0x4;
3114 smounts = (handleValue >> 16) & 0x8;
3115 export = handleValue & 0xff;
3118 /* Failed finding desired exporter; */
3122 handleValue = exporter->exp_states;
3123 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3124 *aoutSize = sizeof(afs_int32);
3126 if (!afs_osi_suser(acred))
3127 return EACCES; /* Only superuser can do this */
3131 exporter->exp_states |= EXP_EXPORTED;
3133 exporter->exp_states &= ~EXP_EXPORTED;
3137 exporter->exp_states |= EXP_UNIXMODE;
3139 exporter->exp_states &= ~EXP_UNIXMODE;
3143 exporter->exp_states |= EXP_PWSYNC;
3145 exporter->exp_states &= ~EXP_PWSYNC;
3149 afs_NFSRootOnly = 0;
3150 exporter->exp_states |= EXP_SUBMOUNTS;
3152 afs_NFSRootOnly = 1;
3153 exporter->exp_states &= ~EXP_SUBMOUNTS;
3156 handleValue = exporter->exp_states;
3157 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3158 *aoutSize = sizeof(afs_int32);
3161 exporter->exp_states |= EXP_EXPORTED;
3163 exporter->exp_states &= ~EXP_EXPORTED;
3165 exporter->exp_states |= EXP_UNIXMODE;
3167 exporter->exp_states &= ~EXP_UNIXMODE;
3169 exporter->exp_states |= EXP_PWSYNC;
3171 exporter->exp_states &= ~EXP_PWSYNC;
3173 afs_NFSRootOnly = 0;
3174 exporter->exp_states |= EXP_SUBMOUNTS;
3176 afs_NFSRootOnly = 1;
3177 exporter->exp_states &= ~EXP_SUBMOUNTS;
3186 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3189 struct vrequest *areq;
3192 struct AFS_UCRED *acred;
3193 afs_int32 *aoutSize; /* set this */
3195 struct gaginfo *gagflags;
3197 if (!afs_osi_suser(acred))
3200 gagflags = (struct gaginfo *) ain;
3201 afs_showflags = gagflags->showflags;
3208 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3211 struct vrequest *areq;
3214 struct AFS_UCRED *acred;
3215 afs_int32 *aoutSize;
3217 struct rxparams *rxp;
3219 if (!afs_osi_suser(acred))
3222 rxp = (struct rxparams *) ain;
3224 if (rxp->rx_initReceiveWindow)
3225 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3226 if (rxp->rx_maxReceiveWindow)
3227 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3228 if (rxp->rx_initSendWindow)
3229 rx_initSendWindow = rxp->rx_initSendWindow;
3230 if (rxp->rx_maxSendWindow)
3231 rx_maxSendWindow = rxp->rx_maxSendWindow;
3232 if (rxp->rxi_nSendFrags)
3233 rxi_nSendFrags = rxp->rxi_nSendFrags;
3234 if (rxp->rxi_nRecvFrags)
3235 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3236 if (rxp->rxi_OrphanFragSize)
3237 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3238 if (rxp->rx_maxReceiveSize)
3240 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3241 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3243 if (rxp->rx_MyMaxSendSize)
3244 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3249 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3252 struct vrequest *areq;
3256 afs_int32 *aoutSize; /* set this */
3258 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3261 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3262 *aoutSize = sizeof(struct cm_initparams);
3266 #ifdef AFS_SGI65_ENV
3267 /* They took crget() from us, so fake it. */
3268 static cred_t *crget(void)
3271 cr = crdup(get_current_cred());
3272 memset((char*)cr, 0, sizeof(cred_t));
3273 #if CELL || CELL_PREPARE
3281 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3284 struct vrequest *areq;
3287 afs_int32 *aoutSize;
3288 struct AFS_UCRED *acred;
3290 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3291 *aoutSize=sizeof(afs_int32);
3296 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3299 struct vrequest *areq;
3302 afs_int32 *aoutSize;
3303 struct AFS_UCRED *acred;
3307 if (!afs_osi_suser(acred))
3309 if (ainSize != sizeof(afs_int32) || ain == NULL)
3311 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3312 /* if new mappings added later this will need to be changed */
3313 if (tmpval != 0 && tmpval != 1)
3320 * Create new credentials to correspond to a remote user with given
3321 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3322 * provide pioctl (and other) services to foreign clients (i.e. nfs
3323 * clients) by using this call to `become' the client.
3326 #define PIOCTL_HEADER 6
3327 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3330 afs_uint32 hostaddr;
3331 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3332 extern struct afs_exporter *exporter_find();
3333 struct afs_exporter *exporter, *outexporter;
3334 struct AFS_UCRED *newcred;
3335 struct unixuser *au;
3337 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3338 return EINVAL; /* NFS trans not supported for Ultrix */
3340 #if defined(AFS_SGIMP_ENV)
3341 osi_Assert(ISAFS_GLOCK());
3343 AFS_STATCNT(HandleClientContext);
3344 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3345 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3346 return EINVAL; /* Too small to be good */
3348 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3349 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3351 osi_FreeLargeSpace(inData);
3355 /* Extract information for remote user */
3356 hostaddr = *((afs_uint32 *)ain);
3357 ain += sizeof(hostaddr);
3358 uid = *((afs_uint32 *)ain);
3360 g0 = *((afs_uint32 *)ain);
3362 g1 = *((afs_uint32 *)ain);
3364 *com = *((afs_uint32 *)ain);
3365 ain += sizeof(afs_int32);
3366 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3369 * Of course, one must be root for most of these functions, but
3370 * we'll allow (for knfs) you to set things if the pag is 0 and
3371 * you're setting tokens or unlogging.
3374 if (!afs_osi_suser(credp)) {
3376 #ifndef AFS_SGI64_ENV
3377 /* Since SGI's suser() returns explicit failure after the call.. */
3381 /* check for acceptable opcodes for normal folks, which are, so far,
3382 * set tokens and unlog.
3384 if (i != 9 && i != 3 && i != 38 && i != 8) {
3385 osi_FreeLargeSpace(inData);
3390 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3391 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3392 osi_FreeLargeSpace(inData);
3395 * We map uid 0 to nobody to match the mapping that the nfs
3396 * server does and to ensure that the suser() calls in the afs
3397 * code fails for remote client roots.
3399 uid = afs_nobody; /* NFS_NOBODY == -2 */
3402 #ifdef AFS_AIX41_ENV
3405 newcred->cr_gid = RMTUSER_REQ;
3406 newcred->cr_groups[0] = g0;
3407 newcred->cr_groups[1] = g1;
3409 newcred->cr_ngrps = 2;
3411 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3412 newcred->cr_ngroups = 2;
3414 for (i=2; i<NGROUPS; i++)
3415 newcred->cr_groups[i] = NOGROUP;
3418 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3419 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3421 if (!(exporter = exporter_find(exporter_type))) {
3422 /* Exporter wasn't initialized or an invalid exporter type */
3426 if (exporter->exp_states & EXP_PWSYNC) {
3427 if (uid != credp->cr_uid) {
3429 return ENOEXEC; /* XXX Find a better errno XXX */
3432 newcred->cr_uid = uid; /* Only temporary */
3433 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3434 /* The client's pag is the only unique identifier for it */
3435 newcred->cr_uid = pag;
3437 if (!code && *com == PSETPAG) {
3438 /* Special case for 'setpag' */
3439 afs_uint32 pagvalue = genpag();
3441 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3443 * Note that we leave the 'outexporter' struct held so it won't
3446 au->exporter = outexporter;
3447 if (ablob->out_size >= 4) {
3448 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3450 afs_PutUser(au, WRITE_LOCK);
3451 if (code) return code;
3452 return PSETPAG; /* Special return for setpag */
3454 EXP_RELE(outexporter);
3457 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3460 /* get all interface addresses of this client */
3463 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3466 struct vrequest *areq;
3469 afs_int32 *aoutSize;
3471 struct sprefrequest *spin; /* input */
3472 struct sprefinfo *spout; /* output */
3473 struct spref *srvout; /* one output component */
3477 AFS_STATCNT(PGetCPrefs);
3478 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3479 return EIO; /* Inappropriate ioctl for device */
3481 if ( ainSize < sizeof (struct sprefrequest ))
3484 spin = (struct sprefrequest *) ain;
3485 spout = (struct sprefinfo *) aout;
3487 maxNumber = spin->num_servers; /* max addrs this time */
3488 srvout = spout->servers;
3490 ObtainReadLock(&afs_xinterface);
3492 /* copy out the client interface information from the
3493 ** kernel data structure "interface" to the output buffer
3495 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3496 && ( j< maxNumber) ; i++, j++, srvout++)
3497 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3499 spout->num_servers = j;
3500 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3502 if ( i >= afs_cb_interface.numberOfInterfaces )
3503 spout->next_offset = 0; /* start from beginning again */
3505 spout->next_offset = spin->offset + j;
3507 ReleaseReadLock(&afs_xinterface);
3512 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3515 struct vrequest *areq;
3518 afs_int32 *aoutSize;
3520 struct setspref *sin;
3523 AFS_STATCNT(PSetCPrefs);
3524 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3525 return EIO; /* Inappropriate ioctl for device */
3527 sin = (struct setspref *)ain;
3529 if ( ainSize < sizeof(struct setspref) )
3531 #if 0 /* num_servers is unsigned */
3532 if ( sin->num_servers < 0 )
3535 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3538 ObtainWriteLock(&afs_xinterface, 412);
3539 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3540 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3541 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3543 ReleaseWriteLock(&afs_xinterface);
3547 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3550 struct vrequest *areq;
3553 afs_int32 *aoutSize;
3554 struct AFS_UCRED *acred; {
3555 register afs_int32 code;
3556 register struct vcache *tvc;
3557 register struct dcache *tdc;
3558 struct VenusFid tfid;
3560 struct sysname_info sysState;
3561 afs_int32 offset, len;
3563 AFS_STATCNT(PFlushMount);
3564 if (!avc) return EINVAL;
3565 code = afs_VerifyVCache(avc, areq);
3566 if (code) return code;
3567 if (vType(avc) != VDIR) {
3570 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3571 if (!tdc) return ENOENT;
3572 Check_AtSys(avc, ain, &sysState, areq);
3574 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3575 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3576 bufp = sysState.name;
3581 tfid.Cell = avc->fid.Cell;
3582 tfid.Fid.Volume = avc->fid.Fid.Volume;
3583 afs_PutDCache(tdc); /* we're done with the data */
3584 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3585 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3587 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3594 if (vType(tvc) != VLNK) {
3595 afs_PutVCache(tvc, WRITE_LOCK);
3599 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3600 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3602 ObtainWriteLock(&tvc->lock,645);
3603 ObtainWriteLock(&afs_xcbhash, 646);
3604 afs_DequeueCallback(tvc);
3605 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3606 ReleaseWriteLock(&afs_xcbhash);
3607 /* now find the disk cache entries */
3608 afs_TryToSmush(tvc, acred, 1);
3609 osi_dnlc_purgedp(tvc);
3610 afs_symhint_inval(tvc);
3611 if (tvc->linkData && !(tvc->states & CCore)) {
3612 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3613 tvc->linkData = (char *) 0;
3615 ReleaseWriteLock(&tvc->lock);
3616 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3617 afs_BozonUnlock(&tvc->pvnLock, tvc);
3619 afs_PutVCache(tvc, WRITE_LOCK);
3621 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3625 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3628 struct vrequest *areq;
3631 afs_int32 *aoutSize;
3632 struct AFS_UCRED *acred;
3637 if (!afs_osi_suser(acred)) {
3641 if (ainSize != sizeof(afs_int32)) {
3645 memcpy((char *)&flags, ain, sizeof(afs_int32));
3646 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3650 if (flags & AFSCALL_RXSTATS_ENABLE) {
3651 rx_enableProcessRPCStats();
3653 if (flags & AFSCALL_RXSTATS_DISABLE) {
3654 rx_disableProcessRPCStats();
3656 if (flags & AFSCALL_RXSTATS_CLEAR) {
3657 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3665 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3668 struct vrequest *areq;
3671 afs_int32 *aoutSize;
3672 struct AFS_UCRED *acred;
3677 if (!afs_osi_suser(acred)) {
3681 if (ainSize != sizeof(afs_int32)) {
3685 memcpy((char *)&flags, ain, sizeof(afs_int32));
3686 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3690 if (flags & AFSCALL_RXSTATS_ENABLE) {
3691 rx_enablePeerRPCStats();
3693 if (flags & AFSCALL_RXSTATS_DISABLE) {
3694 rx_disablePeerRPCStats();
3696 if (flags & AFSCALL_RXSTATS_CLEAR) {
3697 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3704 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3707 struct vrequest *areq;
3710 afs_int32 *aoutSize; /* set this */
3712 register afs_int32 code, code1;
3715 struct rx_call *tcall;
3716 struct AFSVolSync tsync;
3717 struct AFSFetchStatus OutStatus;
3718 struct AFSCallBack CallBack;
3719 struct VenusFid tfid;
3724 AFS_STATCNT(PSetAcl);
3728 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3729 Fid = (struct AFSFid *) ain;
3731 Fid = &avc->fid.Fid;
3732 tfid.Cell = avc->fid.Cell;
3733 tfid.Fid.Volume = Fid->Volume;
3734 tfid.Fid.Vnode = Fid->Vnode;
3735 tfid.Fid.Unique = Fid->Unique;
3737 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3740 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3741 ICL_TYPE_POINTER, tvc,
3742 ICL_TYPE_FID, &tfid,
3743 ICL_TYPE_FID, &avc->fid);
3746 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3747 ICL_TYPE_POINTER, tvc,
3748 ICL_TYPE_FID, &tfid,
3749 ICL_TYPE_FID, &tvc->fid);
3752 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3755 #ifdef RX_ENABLE_LOCKS
3757 #endif /* RX_ENABLE_LOCKS */
3758 tcall = rx_NewCall(tc->id);
3759 code = StartRXAFS_FetchData(tcall,
3760 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3762 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3763 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3765 code1 = rx_EndCall(tcall, code);
3766 #ifdef RX_ENABLE_LOCKS
3768 #endif /* RX_ENABLE_LOCKS */
3772 (afs_Analyze(tc, code, &tvc->fid, areq,
3773 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3775 /* This call is done only to have the callback things handled correctly */
3776 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3777 afs_PutVCache(tvc, WRITE_LOCK);
3780 *aoutSize = sizeof(afs_int32);
3785 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3788 struct vrequest *areq;
3791 afs_int32 *aoutSize; /* set this */
3793 register afs_int32 code;
3796 struct ResidencyCmdInputs *Inputs;
3797 struct ResidencyCmdOutputs *Outputs;
3798 struct VenusFid tfid;
3801 Inputs = (struct ResidencyCmdInputs *) ain;
3802 Outputs = (struct ResidencyCmdOutputs *) aout;
3803 if (!avc) return EINVAL;
3804 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3808 Fid = &avc->fid.Fid;
3810 tfid.Cell = avc->fid.Cell;
3811 tfid.Fid.Volume = Fid->Volume;
3812 tfid.Fid.Vnode = Fid->Vnode;
3813 tfid.Fid.Unique = Fid->Unique;
3815 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3817 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3818 ICL_TYPE_POINTER, tvc,
3819 ICL_TYPE_INT32, Inputs->command,
3820 ICL_TYPE_FID, &tfid);
3824 if (Inputs->command) {
3826 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3828 #ifdef RX_ENABLE_LOCKS
3830 #endif /* RX_ENABLE_LOCKS */
3831 code = RXAFS_ResidencyCmd(tc->id, Fid,
3833 (struct ResidencyCmdOutputs *) aout);
3834 #ifdef RX_ENABLE_LOCKS
3836 #endif /* RX_ENABLE_LOCKS */
3840 (afs_Analyze(tc, code, &tvc->fid, areq,
3841 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3843 /* This call is done to have the callback things handled correctly */
3844 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3845 } else { /* just a status request, return also link data */
3847 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3848 Outputs->chars[0] = 0;
3849 if (vType(tvc) == VLNK) {
3850 ObtainWriteLock(&tvc->lock,555);
3851 if (afs_HandleLink(tvc, areq) == 0)
3852 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3853 ReleaseWriteLock(&tvc->lock);
3857 afs_PutVCache(tvc, WRITE_LOCK);
3860 *aoutSize = sizeof(struct ResidencyCmdOutputs);