2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include "../afs/param.h" /* Should be always first */
11 #include "../afs/sysincludes.h" /* Standard vendor system headers */
12 #include "../afs/afsincludes.h" /* Afs-based standard headers */
13 #include "../afs/afs_stats.h" /* afs statistics */
14 #include "../afs/vice.h"
15 #include "../rx/rx_globals.h"
17 extern void afs_ComputePAGStats();
18 extern struct vcache *afs_LookupVCache();
19 struct VenusFid afs_rootFid;
20 afs_int32 afs_waitForever=0;
21 short afs_waitForeverCount = 0;
22 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
23 extern afs_int32 PROBE_INTERVAL;
25 extern int cacheDiskType;
26 extern afs_int32 afs_cacheBlocks;
27 extern struct afs_q CellLRU;
28 extern char *afs_indexFlags; /* only one: is there data there? */
29 extern afs_int32 afs_blocksUsed;
30 extern struct unixuser *afs_users[NUSERS];
31 extern struct server *afs_servers[NSERVERS];
32 extern struct interfaceAddr afs_cb_interface; /* client interface addresses */
33 extern afs_rwlock_t afs_xserver;
34 extern afs_rwlock_t afs_xinterface;
35 extern afs_rwlock_t afs_xcell;
36 extern afs_rwlock_t afs_xuser;
37 #ifndef AFS_FINEG_SUNLOCK
38 extern afs_rwlock_t afs_xconn;
40 extern afs_rwlock_t afs_xvolume;
41 extern afs_lock_t afs_xdcache; /* lock: alloc new disk cache entries */
42 extern afs_rwlock_t afs_xvcache;
43 extern afs_rwlock_t afs_xcbhash;
44 extern afs_int32 afs_mariner, afs_marinerHost;
45 extern struct srvAddr *afs_srvAddrs[NSERVERS];
46 extern int afs_resourceinit_flag;
47 extern afs_int32 cryptall;
49 static int PBogus(), PSetAcl(), PGetAcl(), PSetTokens(), PGetVolumeStatus();
50 static int PSetVolumeStatus(), PFlush(), PNewStatMount(), PGetTokens(), PUnlog();
51 static int PCheckServers(), PCheckVolNames(), PCheckAuth(), PFindVolume();
52 static int PViceAccess(), PSetCacheSize(), Prefetch();
53 static int PRemoveCallBack(), PNewCell(), PListCells(), PRemoveMount();
54 static int PMariner(), PGetUserCell(), PGetWSCell(), PGetFileCell();
55 static int PVenusLogging(), PNoop(), PSetCellStatus(), PGetCellStatus();
56 static int PFlushVolumeData(), PGetCacheSize();
57 static int PSetSysName(),PGetFID();
58 static int PGetVnodeXStatus();
59 static int PSetSPrefs(), PGetSPrefs(), PGag(), PTwiddleRx();
60 static int PSetSPrefs33(), PStoreBehind(), PGCPAGs();
61 static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */
62 static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer();
63 static int PGetRxkcrypt(), PSetRxkcrypt();
64 static int PPrefetchFromTape(), PResidencyCmd();
67 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
69 extern struct cm_initparams cm_initParams;
71 static int (*(pioctlSw[]))() = {
76 PGetVolumeStatus, /* 4 */
77 PSetVolumeStatus, /* 5 */
82 PCheckServers, /* 10 */
83 PCheckVolNames, /* 11 */
85 PBogus, /* 13 -- used to be quick check time */
87 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
88 PBogus, /* 16 -- used to be testing code */
89 PNoop, /* 17 -- used to be enable group */
90 PNoop, /* 18 -- used to be disable group */
91 PBogus, /* 19 -- used to be list group */
93 PUnlog, /* 21 -- unlog *is* unpag in this system */
94 PGetFID, /* 22 -- get file ID */
95 PBogus, /* 23 -- used to be waitforever */
96 PSetCacheSize, /* 24 */
97 PRemoveCallBack, /* 25 -- flush only the callback */
100 PRemoveMount, /* 28 -- delete mount point */
101 PNewStatMount, /* 29 -- new style mount point stat */
102 PGetFileCell, /* 30 -- get cell name for input file */
103 PGetWSCell, /* 31 -- get cell name for workstation */
104 PMariner, /* 32 - set/get mariner host */
105 PGetUserCell, /* 33 -- get cell name for user */
106 PVenusLogging, /* 34 -- Enable/Disable logging */
107 PGetCellStatus, /* 35 */
108 PSetCellStatus, /* 36 */
109 PFlushVolumeData, /* 37 -- flush all data from a volume */
110 PSetSysName, /* 38 - Set system name */
111 PExportAfs, /* 39 - Export Afs to remote nfs clients */
112 PGetCacheSize, /* 40 - get cache size and usage */
113 PGetVnodeXStatus, /* 41 - get vcache's special status */
114 PSetSPrefs33, /* 42 - Set CM Server preferences... */
115 PGetSPrefs, /* 43 - Get CM Server preferences... */
116 PGag, /* 44 - turn off/on all CM messages */
117 PTwiddleRx, /* 45 - adjust some RX params */
118 PSetSPrefs, /* 46 - Set CM Server preferences... */
119 PStoreBehind, /* 47 - set degree of store behind to be done */
120 PGCPAGs, /* 48 - disable automatic pag gc-ing */
121 PGetInitParams, /* 49 - get initial cm params */
122 PGetCPrefs, /* 50 - get client interface addresses */
123 PSetCPrefs, /* 51 - set client interface addresses */
124 PFlushMount, /* 52 - flush mount symlink data */
125 PRxStatProc, /* 53 - control process RX statistics */
126 PRxStatPeer, /* 54 - control peer RX statistics */
127 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
128 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
129 PNoop, /* 57 -- arla: set file prio */
130 PNoop, /* 58 -- arla: fallback getfh */
131 PNoop, /* 59 -- arla: fallback fhopen */
132 PNoop, /* 60 -- arla: controls xfsdebug */
133 PNoop, /* 61 -- arla: controls arla debug */
134 PNoop, /* 62 -- arla: debug interface */
135 PNoop, /* 63 -- arla: print xfs status */
136 PNoop, /* 64 -- arla: force cache check */
137 PNoop, /* 65 -- arla: break callback */
138 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
139 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
142 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
143 int afs_nobody = NFS_NOBODY;
146 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
148 dst->in = (char *)(unsigned long)src->in;
149 dst->out = (char *)(unsigned long)src->out;
150 dst->in_size = src->in_size;
151 dst->out_size = src->out_size;
155 * If you need to change copyin_afs_ioctl(), you may also need to change
160 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
164 #if defined(AFS_HPUX_64BIT_ENV)
165 struct afs_ioctl32 dst32;
167 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
169 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
171 afs_ioctl32_to_afs_ioctl(&dst32, dst);
174 #endif /* defined(AFS_HPUX_64BIT_ENV) */
176 #if defined(AFS_SUN57_64BIT_ENV)
177 struct afs_ioctl32 dst32;
179 if (get_udatamodel() == DATAMODEL_ILP32) {
180 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
182 afs_ioctl32_to_afs_ioctl(&dst32, dst);
185 #endif /* defined(AFS_SUN57_64BIT_ENV) */
187 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
188 struct afs_ioctl32 dst32;
190 if (!ABI_IS_64BIT(get_current_abi()))
192 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
194 afs_ioctl32_to_afs_ioctl(&dst32, dst);
197 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
199 #if defined(AFS_LINUX_64BIT_KERNEL)
200 struct afs_ioctl32 dst32;
202 #ifdef AFS_SPARC64_LINUX20_ENV
203 if (current->tss.flags & SPARC_FLAG_32BIT) {
205 #error Not done for this linux type
207 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
209 afs_ioctl32_to_afs_ioctl(&dst32, dst);
212 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
214 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
218 HandleIoctl(avc, acom, adata)
219 register struct vcache *avc;
220 register afs_int32 acom;
221 struct afs_ioctl *adata; {
222 register afs_int32 code;
225 AFS_STATCNT(HandleIoctl);
227 switch(acom & 0xff) {
229 avc->states |= CSafeStore;
233 /* case 2 used to be abort store, but this is no longer provided,
234 since it is impossible to implement under normal Unix.
238 /* return the name of the cell this file is open on */
239 register struct cell *tcell;
240 register afs_int32 i;
242 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
244 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
246 if (i > adata->out_size) {
247 /* 0 means we're not interested in the output */
248 if (adata->out_size != 0) code = EFAULT;
252 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
254 afs_PutCell(tcell, READ_LOCK);
260 case 49: /* VIOC_GETINITPARAMS */
261 if (adata->out_size < sizeof(struct cm_initparams)) {
265 AFS_COPYOUT(&cm_initParams, adata->out,
266 sizeof(struct cm_initparams), code);
275 return code; /* so far, none implemented */
280 /* For aix we don't temporarily bypass ioctl(2) but rather do our
281 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
282 * is now called from afs_gn_ioctl.
284 afs_ioctl(tvc, cmd, arg)
289 struct afs_ioctl data;
292 AFS_STATCNT(afs_ioctl);
293 if (((cmd >> 8) & 0xff) == 'V') {
294 /* This is a VICEIOCTL call */
295 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
298 error = HandleIoctl(tvc, cmd, &data);
301 /* No-op call; just return. */
305 #endif /* AFS_AIX_ENV */
307 #if defined(AFS_SGI_ENV)
308 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
314 struct afs_ioctl data;
320 AFS_STATCNT(afs_ioctl);
321 if (((cmd >> 8) & 0xff) == 'V') {
322 /* This is a VICEIOCTL call */
323 error = copyin_afs_ioctl(arg, &data);
326 locked = ISAFS_GLOCK();
329 error = HandleIoctl(tvc, cmd, &data);
334 /* No-op call; just return. */
338 #endif /* AFS_SGI_ENV */
341 /* unlike most calls here, this one uses u.u_error to return error conditions,
342 since this is really an intercepted chapter 2 call, rather than a vnode
345 /* AFS_HPUX102 and up uses VNODE ioctl instead */
346 #ifndef AFS_HPUX102_ENV
347 #if !defined(AFS_SGI_ENV)
349 kioctl(fdes, com, arg, ext)
356 } u_uap, *uap = &u_uap;
360 struct afs_ioctl_sys {
366 afs_xioctl (uap, rvp)
367 struct afs_ioctl_sys *uap;
372 afs_xioctl (p, args, retval)
381 } *uap = (struct a *)args;
382 #else /* AFS_OSF_ENV */
383 #ifdef AFS_LINUX22_ENV
384 struct afs_ioctl_sys {
388 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
389 unsigned int com, unsigned long arg)
391 struct afs_ioctl_sys ua, *uap = &ua;
399 } *uap = (struct a *)u.u_ap;
400 #endif /* AFS_LINUX22_ENV */
401 #endif /* AFS_OSF_ENV */
402 #endif /* AFS_SUN5_ENV */
404 #ifndef AFS_LINUX22_ENV
405 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
408 register struct file *fd;
411 register struct vcache *tvc;
412 register int ioctlDone = 0, code = 0;
414 AFS_STATCNT(afs_xioctl);
415 #ifdef AFS_LINUX22_ENV
423 if (setuerror(getf(uap->fd, &fd))) {
429 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
431 #else /* AFS_OSF_ENV */
433 #if defined(AFS_SUN57_ENV)
435 if (!fd) return(EBADF);
436 #elif defined(AFS_SUN54_ENV)
438 if (!fd) return(EBADF);
440 if (code = getf(uap->fd, &fd)) {
452 /* first determine whether this is any sort of vnode */
453 #ifdef AFS_LINUX22_ENV
454 tvc = (struct vcache *)ip;
458 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
460 if (fd->f_type == DTYPE_VNODE) {
462 /* good, this is a vnode; next see if it is an AFS vnode */
463 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
464 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
466 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
468 #endif /* AFS_LINUX22_ENV */
469 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
471 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
472 if (!tvc) { /* shouldn't happen with held gnodes */
477 /* This is an AFS vnode */
478 if (((uap->com >> 8) & 0xff) == 'V') {
479 register struct afs_ioctl *datap;
481 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
482 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
484 osi_FreeSmallSpace(datap);
486 #if defined(AFS_SUN5_ENV)
501 #else /* AFS_OSF_ENV */
505 #ifdef AFS_LINUX22_ENV
514 code = HandleIoctl(tvc, uap->com, datap);
515 osi_FreeSmallSpace(datap);
529 #if defined(AFS_LINUX22_ENV)
539 code = okioctl(fdes, com, arg, ext);
543 okioctl(fdes, com, arg, ext);
545 #if defined(AFS_SUN5_ENV)
546 #if defined(AFS_SUN57_ENV)
548 #elif defined(AFS_SUN54_ENV)
553 code = ioctl(uap, rvp);
556 code = ioctl(p, args, retval);
563 #else /* AFS_OSF_ENV */
564 #ifndef AFS_LINUX22_ENV
581 #ifdef AFS_LINUX22_ENV
584 #if !defined(AFS_OSF_ENV)
587 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
588 return (getuerror() ? -1 : u.u_ioctlrv);
590 return getuerror() ? -1 : 0;
593 #endif /* AFS_LINUX22_ENV */
594 #endif /* AFS_SUN5_ENV */
599 #endif /* AFS_SGI_ENV */
600 #endif /* AFS_HPUX102_ENV */
602 #if defined(AFS_SGI_ENV)
603 /* "pioctl" system call entry point; just pass argument to the parameterized
612 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
616 AFS_STATCNT(afs_pioctl);
618 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
626 #endif /* AFS_SGI_ENV */
629 afs_pioctl(p, args, retval)
639 } *uap = (struct a *) args;
641 AFS_STATCNT(afs_pioctl);
642 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
645 extern struct mount *afs_globalVFS;
646 #else /* AFS_OSF_ENV */
647 extern struct vfs *afs_globalVFS;
650 /* macro to avoid adding any more #ifdef's to pioctl code. */
651 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
652 #define PIOCTL_FREE_CRED() crfree(credp)
654 #define PIOCTL_FREE_CRED()
658 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
660 struct AFS_UCRED *credp;
662 afs_syscall_pioctl(path, com, cmarg, follow)
669 struct afs_ioctl data;
670 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
671 register afs_int32 code = 0;
677 struct ucred *credp = crref(); /* don't free until done! */
679 #ifdef AFS_LINUX22_ENV
680 cred_t *credp = crref(); /* don't free until done! */
683 AFS_STATCNT(afs_syscall_pioctl);
684 if (follow) follow = 1; /* compat. with old venus */
686 if (! _VALIDVICEIOCTL(com)) {
690 #else /* AFS_OSF_ENV */
691 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
700 code = copyin_afs_ioctl(cmarg, &data);
703 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
710 if ((com & 0xff) == PSetClientContext) {
711 #ifdef AFS_LINUX22_ENV
712 return EINVAL; /* Not handling these yet. */
714 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
715 code = HandleClientContext(&data, &com, &foreigncreds, credp);
717 #if defined(AFS_HPUX101_ENV)
718 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
721 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
723 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
724 #endif /* AFS_SGI_ENV */
729 crfree(foreigncreds);
732 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
735 return (setuerror(code), code);
739 #ifndef AFS_LINUX22_ENV
742 * We could have done without temporary setting the u.u_cred below
743 * (foreigncreds could be passed as param the pioctl modules)
744 * but calls such as afs_osi_suser() doesn't allow that since it
745 * references u.u_cred directly. We could, of course, do something
746 * like afs_osi_suser(cred) which, I think, is better since it
747 * generalizes and supports multi cred environments...
751 credp = foreigncreds;
754 tmpcred = crref(); /* XXX */
757 #if defined(AFS_HPUX101_ENV)
758 tmpcred = p_cred(u.u_procp);
759 set_p_cred(u.u_procp, foreigncreds);
762 tmpcred = OSI_GET_CURRENT_CRED();
763 OSI_SET_CURRENT_CRED(foreigncreds);
766 u.u_cred = foreigncreds;
767 #endif /* AFS_SGI64_ENV */
768 #endif /* AFS_HPUX101_ENV */
773 if ((com & 0xff) == 15) {
774 /* special case prefetch so entire pathname eval occurs in helper process.
775 otherwise, the pioctl call is essentially useless */
776 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
777 code = Prefetch(path, &data, follow,
778 foreigncreds ? foreigncreds : credp);
780 #if defined(AFS_HPUX101_ENV)
781 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
784 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
786 code = Prefetch(path, &data, follow, u.u_cred);
787 #endif /* AFS_SGI64_ENV */
788 #endif /* AFS_HPUX101_ENV */
790 #ifndef AFS_LINUX22_ENV
793 crset(tmpcred); /* restore original credentials */
795 #if defined(AFS_HPUX101_ENV)
796 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
800 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
802 u.u_cred = tmpcred; /* restore original credentials */
805 #endif /* AFS_HPUX101_ENV */
806 crfree(foreigncreds);
809 #endif /* AFS_LINUX22_ENV */
811 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
814 return (setuerror(code), code);
820 code = lookupname(path, USR, follow, NULL, &vp,
821 foreigncreds ? foreigncreds : credp);
823 #ifdef AFS_LINUX22_ENV
824 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
826 vp = (struct vnode *)dp->d_inode;
828 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
829 #endif /* AFS_LINUX22_ENV */
830 #endif /* AFS_AIX41_ENV */
833 #ifndef AFS_LINUX22_ENV
836 crset(tmpcred); /* restore original credentials */
838 #if defined(AFS_HPUX101_ENV)
839 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
841 #if !defined(AFS_SUN5_ENV)
843 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
845 u.u_cred = tmpcred; /* restore original credentials */
846 #endif /* AFS_SGI64_ENV */
848 #endif /* AFS_HPUX101_ENV */
849 crfree(foreigncreds);
852 #endif /* AFS_LINUX22_ENV */
854 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
857 return(setuerror(code), code);
861 else vp = (struct vnode *) 0;
863 /* now make the call if we were passed no file, or were passed an AFS file */
864 if (!vp || IsAfsVnode(vp)) {
866 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
867 * So, we must test in this part of the code. Also, must arrange to
868 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
869 * we hold gnodes, whose references hold our vcache entries.
872 gp = vp; /* remember for "put" */
873 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
875 else gp = (struct vnode *) 0;
878 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
882 struct ucred *cred1, *cred2;
885 cred1 = cred2 = foreigncreds;
887 cred1 = cred2 = credp;
889 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
890 if (cred1 != cred2) {
891 /* something changed the creds */
896 #if defined(AFS_HPUX101_ENV)
898 struct ucred *cred = p_cred(u.u_procp);
899 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
905 credp = OSI_GET_CURRENT_CRED();
906 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
909 #ifdef AFS_LINUX22_ENV
910 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
912 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
914 #endif /* AFS_SGI_ENV */
915 #endif /* AFS_HPUX101_ENV */
916 #endif /* AFS_AIX41_ENV */
917 #endif /* AFS_SUN5_ENV */
919 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
920 code = EINVAL; /* not in /afs */
927 vp = (struct vnode *) 0;
932 #ifndef AFS_LINUX22_ENV
937 #if defined(AFS_HPUX101_ENV)
938 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
942 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
944 u.u_cred = tmpcred; /* restore original credentials */
945 #endif /* ASF_SGI64_ENV */
947 #endif /* AFS_HPUX101_ENV */
948 crfree(foreigncreds);
951 #endif /* AFS_LINUX22_ENV */
953 #ifdef AFS_LINUX22_ENV
956 AFS_RELE(vp); /* put vnode back */
960 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
965 return (getuerror());
970 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
971 register struct vcache *avc;
973 struct AFS_UCRED **acred;
974 register struct afs_ioctl *ablob;
977 struct vrequest treq;
978 register afs_int32 code;
979 register afs_int32 function;
980 afs_int32 inSize, outSize;
981 char *inData, *outData;
983 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
984 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
985 AFS_STATCNT(HandlePioctl);
986 if (code = afs_InitReq(&treq, *acred)) return code;
987 function = acom & 0xff;
988 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
989 return EINVAL; /* out of range */
991 inSize = ablob->in_size;
992 if (inSize >= PIGGYSIZE) return E2BIG;
993 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
995 AFS_COPYIN(ablob->in, inData, inSize, code);
999 osi_FreeLargeSpace(inData);
1002 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1004 if (function == 3) /* PSetTokens */
1005 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1007 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
1008 osi_FreeLargeSpace(inData);
1009 if (code == 0 && ablob->out_size > 0) {
1010 if (outSize > ablob->out_size) outSize = ablob->out_size;
1011 if (outSize >= PIGGYSIZE) code = E2BIG;
1013 AFS_COPYOUT(outData, ablob->out, outSize, code);
1015 osi_FreeLargeSpace(outData);
1016 return afs_CheckCode(code, &treq, 41);
1019 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
1022 struct vrequest *areq;
1025 afs_int32 *aoutSize; /* set this */ {
1026 register afs_int32 code;
1028 AFS_STATCNT(PGetFID);
1029 if (!avc) return EINVAL;
1030 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1031 *aoutSize = sizeof(struct VenusFid);
1035 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1038 struct vrequest *areq;
1041 afs_int32 *aoutSize; /* set this */ {
1042 register afs_int32 code;
1044 struct AFSOpaque acl;
1045 struct AFSVolSync tsync;
1046 struct AFSFetchStatus OutStatus;
1049 AFS_STATCNT(PSetAcl);
1052 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1055 acl.AFSOpaque_val = ain;
1057 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1059 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1060 #ifdef RX_ENABLE_LOCKS
1062 #endif /* RX_ENABLE_LOCKS */
1063 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1064 &acl, &OutStatus, &tsync);
1065 #ifdef RX_ENABLE_LOCKS
1067 #endif /* RX_ENABLE_LOCKS */
1072 (afs_Analyze(tconn, code, &avc->fid, areq,
1073 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1075 /* now we've forgotten all of the access info */
1076 ObtainWriteLock(&afs_xcbhash, 455);
1078 afs_DequeueCallback(avc);
1079 avc->states &= ~(CStatd | CUnique);
1080 ReleaseWriteLock(&afs_xcbhash);
1081 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1082 osi_dnlc_purgedp(avc);
1086 int afs_defaultAsynchrony = 0;
1088 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1091 struct vrequest *areq;
1094 afs_int32 *aoutSize; /* set this */
1095 struct AFS_UCRED *acred;
1098 struct sbstruct *sbr;
1100 sbr = (struct sbstruct *)ain;
1101 if (sbr->sb_default != -1) {
1102 if (afs_osi_suser(acred))
1103 afs_defaultAsynchrony = sbr->sb_default;
1107 if (avc && (sbr->sb_thisfile != -1))
1108 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1109 areq, DONT_CHECK_MODE_BITS))
1110 avc->asynchrony = sbr->sb_thisfile;
1113 *aoutSize = sizeof(struct sbstruct);
1114 sbr = (struct sbstruct *)aout;
1115 sbr->sb_default = afs_defaultAsynchrony;
1117 sbr->sb_thisfile = avc->asynchrony;
1123 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1126 struct vrequest *areq;
1129 afs_int32 *aoutSize; /* set this */
1130 struct AFS_UCRED *acred;
1132 if (!afs_osi_suser(acred)) {
1135 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1139 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1142 struct vrequest *areq;
1145 afs_int32 *aoutSize; /* set this */ {
1146 struct AFSOpaque acl;
1147 struct AFSVolSync tsync;
1148 struct AFSFetchStatus OutStatus;
1154 AFS_STATCNT(PGetAcl);
1155 if (!avc) return EINVAL;
1156 Fid.Volume = avc->fid.Fid.Volume;
1157 Fid.Vnode = avc->fid.Fid.Vnode;
1158 Fid.Unique = avc->fid.Fid.Unique;
1159 if (avc->states & CForeign) {
1161 * For a dfs xlator acl we have a special hack so that the
1162 * xlator will distinguish which type of acl will return. So
1163 * we currently use the top 2-bytes (vals 0-4) to tell which
1164 * type of acl to bring back. Horrible hack but this will
1165 * cause the least number of changes to code size and interfaces.
1167 if (Fid.Vnode & 0xc0000000)
1169 Fid.Vnode |= (ainSize << 30);
1171 acl.AFSOpaque_val = aout;
1173 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1176 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1177 #ifdef RX_ENABLE_LOCKS
1179 #endif /* RX_ENABLE_LOCKS */
1180 code = RXAFS_FetchACL(tconn->id, &Fid,
1181 &acl, &OutStatus, &tsync);
1182 #ifdef RX_ENABLE_LOCKS
1184 #endif /* RX_ENABLE_LOCKS */
1189 (afs_Analyze(tconn, code, &avc->fid, areq,
1190 AFS_STATS_FS_RPCIDX_FETCHACL,
1191 SHARED_LOCK, (struct cell *)0));
1194 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1205 AFS_STATCNT(PBogus);
1209 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1212 struct vrequest *areq;
1216 afs_int32 *aoutSize; /* set this */ {
1217 register struct cell *tcell;
1219 AFS_STATCNT(PGetFileCell);
1220 if (!avc) return EINVAL;
1221 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1222 if (!tcell) return ESRCH;
1223 strcpy(aout, tcell->cellName);
1224 afs_PutCell(tcell, READ_LOCK);
1225 *aoutSize = strlen(aout) + 1;
1229 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1232 struct vrequest *areq;
1236 afs_int32 *aoutSize; /* set this */ {
1237 register struct cell *tcell=0, *cellOne=0;
1238 register struct afs_q *cq, *tq;
1240 AFS_STATCNT(PGetWSCell);
1241 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1242 return EIO; /* Inappropriate ioctl for device */
1244 ObtainReadLock(&afs_xcell);
1245 cellOne = (struct cell *) 0;
1247 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1248 tcell = QTOC(cq); tq = QNext(cq);
1249 if (tcell->states & CPrimary) break;
1250 if (tcell->cell == 1) cellOne = tcell;
1253 ReleaseReadLock(&afs_xcell);
1254 if (!tcell) { /* no primary cell, use cell #1 */
1255 if (!cellOne) return ESRCH;
1258 strcpy(aout, tcell->cellName);
1259 *aoutSize = strlen(aout) + 1;
1263 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1266 struct vrequest *areq;
1270 afs_int32 *aoutSize; /* set this */ {
1271 register afs_int32 i;
1272 register struct unixuser *tu;
1273 register struct cell *tcell;
1275 AFS_STATCNT(PGetUserCell);
1276 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1277 return EIO; /* Inappropriate ioctl for device */
1279 /* return the cell name of the primary cell for this user */
1280 i = UHash(areq->uid);
1281 ObtainWriteLock(&afs_xuser,224);
1282 for(tu = afs_users[i]; tu; tu = tu->next) {
1283 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1285 ReleaseWriteLock(&afs_xuser);
1290 tcell = afs_GetCell(tu->cell, READ_LOCK);
1291 afs_PutUser(tu, WRITE_LOCK);
1292 if (!tcell) return ESRCH;
1294 strcpy(aout, tcell->cellName);
1295 afs_PutCell(tcell, READ_LOCK);
1296 *aoutSize = strlen(aout)+1; /* 1 for the null */
1300 ReleaseWriteLock(&afs_xuser);
1307 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1310 struct vrequest *areq;
1314 afs_int32 *aoutSize; /* set this */
1315 struct AFS_UCRED **acred;
1318 register struct unixuser *tu;
1319 struct ClearToken clear;
1320 register struct cell *tcell;
1323 struct vrequest treq;
1324 afs_int32 flag, set_parent_pag = 0;
1326 AFS_STATCNT(PSetTokens);
1327 if (!afs_resourceinit_flag) {
1330 bcopy(ain, (char *)&i, sizeof(afs_int32));
1331 ain += sizeof(afs_int32);
1332 stp = ain; /* remember where the ticket is */
1333 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1335 ain += i; /* skip over ticket */
1336 bcopy(ain, (char *)&i, sizeof(afs_int32));
1337 ain += sizeof(afs_int32);
1338 if (i != sizeof(struct ClearToken)) {
1341 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1342 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1343 ain += sizeof(struct ClearToken);
1344 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1345 /* still stuff left? we've got primary flag and cell name. Set these */
1346 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1347 ain += sizeof(afs_int32); /* skip id field */
1348 /* rest is cell name, look it up */
1349 if (flag & 0x8000) { /* XXX Use Constant XXX */
1353 tcell = afs_GetCellByName(ain, READ_LOCK);
1362 /* default to cell 1, primary id */
1363 flag = 1; /* primary id */
1364 i = 1; /* cell number */
1365 tcell = afs_GetCell(1, READ_LOCK);
1366 if (!tcell) goto nocell;
1368 afs_PutCell(tcell, READ_LOCK);
1369 if (set_parent_pag) {
1372 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1374 if (!setpag(acred, -1, &pag, 1)) {
1376 afs_InitReq(&treq, *acred);
1380 /* now we just set the tokens */
1381 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1382 tu->vid = clear.ViceId;
1383 if (tu->stp != (char *) 0) {
1384 afs_osi_Free(tu->stp, tu->stLen);
1386 tu->stp = (char *) afs_osi_Alloc(stLen);
1388 bcopy(stp, tu->stp, stLen);
1391 afs_stats_cmfullperf.authent.TicketUpdates++;
1392 afs_ComputePAGStats();
1393 #endif /* AFS_NOSTATS */
1394 tu->states |= UHasTokens;
1395 tu->states &= ~UTokensBad;
1396 afs_SetPrimary(tu, flag);
1397 tu->tokenTime =osi_Time();
1398 afs_ResetUserConns(tu);
1399 afs_PutUser(tu, WRITE_LOCK);
1414 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1417 struct vrequest *areq;
1420 afs_int32 *aoutSize; /* set this */ {
1422 char offLineMsg[256];
1424 register struct conn *tc;
1425 register afs_int32 code;
1426 struct VolumeStatus volstat;
1428 char *Name, *OfflineMsg, *MOTD;
1431 AFS_STATCNT(PGetVolumeStatus);
1432 if (!avc) return EINVAL;
1434 OfflineMsg = offLineMsg;
1437 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1439 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1440 #ifdef RX_ENABLE_LOCKS
1442 #endif /* RX_ENABLE_LOCKS */
1443 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1444 &Name, &OfflineMsg, &MOTD);
1445 #ifdef RX_ENABLE_LOCKS
1447 #endif /* RX_ENABLE_LOCKS */
1452 (afs_Analyze(tc, code, &avc->fid, areq,
1453 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1454 SHARED_LOCK, (struct cell *)0));
1456 if (code) return code;
1457 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1459 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1460 cp += sizeof(VolumeStatus);
1461 strcpy(cp, volName);
1462 cp += strlen(volName)+1;
1463 strcpy(cp, offLineMsg);
1464 cp += strlen(offLineMsg)+1;
1466 cp += strlen(motd)+1;
1467 *aoutSize = (cp - aout);
1471 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1474 struct vrequest *areq;
1477 afs_int32 *aoutSize; /* set this */ {
1479 char offLineMsg[256];
1481 register struct conn *tc;
1482 register afs_int32 code;
1483 struct AFSFetchVolumeStatus volstat;
1484 struct AFSStoreVolumeStatus storeStat;
1485 register struct volume *tvp;
1489 AFS_STATCNT(PSetVolumeStatus);
1490 if (!avc) return EINVAL;
1492 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1494 if (tvp->states & (VRO | VBackup)) {
1495 afs_PutVolume(tvp, READ_LOCK);
1498 afs_PutVolume(tvp, READ_LOCK);
1501 /* Copy the junk out, using cp as a roving pointer. */
1503 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1504 cp += sizeof(AFSFetchVolumeStatus);
1505 strcpy(volName, cp);
1506 cp += strlen(volName)+1;
1507 strcpy(offLineMsg, cp);
1508 cp += strlen(offLineMsg)+1;
1511 if (volstat.MinQuota != -1) {
1512 storeStat.MinQuota = volstat.MinQuota;
1513 storeStat.Mask |= AFS_SETMINQUOTA;
1515 if (volstat.MaxQuota != -1) {
1516 storeStat.MaxQuota = volstat.MaxQuota;
1517 storeStat.Mask |= AFS_SETMAXQUOTA;
1520 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1522 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1523 #ifdef RX_ENABLE_LOCKS
1525 #endif /* RX_ENABLE_LOCKS */
1526 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1527 &storeStat, volName, offLineMsg, motd);
1528 #ifdef RX_ENABLE_LOCKS
1530 #endif /* RX_ENABLE_LOCKS */
1535 (afs_Analyze(tc, code, &avc->fid, areq,
1536 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1537 SHARED_LOCK, (struct cell *)0));
1539 if (code) return code;
1540 /* we are sending parms back to make compat. with prev system. should
1541 change interface later to not ask for current status, just set new status */
1543 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1544 cp += sizeof(VolumeStatus);
1545 strcpy(cp, volName);
1546 cp += strlen(volName)+1;
1547 strcpy(cp, offLineMsg);
1548 cp += strlen(offLineMsg)+1;
1550 cp += strlen(motd)+1;
1551 *aoutSize = cp - aout;
1555 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1556 register struct vcache *avc;
1558 struct vrequest *areq;
1561 afs_int32 *aoutSize; /* set this */
1562 struct AFS_UCRED *acred;
1565 AFS_STATCNT(PFlush);
1566 if (!avc) return EINVAL;
1567 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1568 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1570 ObtainWriteLock(&avc->lock,225);
1571 ObtainWriteLock(&afs_xcbhash, 456);
1572 afs_DequeueCallback(avc);
1573 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1574 ReleaseWriteLock(&afs_xcbhash);
1575 /* now find the disk cache entries */
1576 afs_TryToSmush(avc, acred, 1);
1577 osi_dnlc_purgedp(avc);
1578 afs_symhint_inval(avc);
1579 if (avc->linkData && !(avc->states & CCore)) {
1580 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1581 avc->linkData = (char *) 0;
1583 ReleaseWriteLock(&avc->lock);
1584 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1585 afs_BozonUnlock(&avc->pvnLock, avc);
1590 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1593 struct vrequest *areq;
1596 afs_int32 *aoutSize; /* set this */ {
1597 register afs_int32 code;
1598 register struct vcache *tvc;
1599 register struct dcache *tdc;
1600 struct VenusFid tfid;
1602 afs_int32 offset, len, hasatsys=0;
1604 AFS_STATCNT(PNewStatMount);
1605 if (!avc) return EINVAL;
1606 code = afs_VerifyVCache(avc, areq);
1607 if (code) return code;
1608 if (vType(avc) != VDIR) {
1611 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1612 if (!tdc) return ENOENT;
1613 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1614 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1619 tfid.Cell = avc->fid.Cell;
1620 tfid.Fid.Volume = avc->fid.Fid.Volume;
1621 afs_PutDCache(tdc); /* we're done with the data */
1622 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1623 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1625 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1632 if (vType(tvc) != VLNK) {
1633 afs_PutVCache(tvc, WRITE_LOCK);
1637 ObtainWriteLock(&tvc->lock,226);
1638 code = afs_HandleLink(tvc, areq);
1640 if (tvc->linkData) {
1641 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1644 /* we have the data */
1645 strcpy(aout, tvc->linkData);
1646 *aoutSize = strlen(tvc->linkData)+1;
1651 ReleaseWriteLock(&tvc->lock);
1652 afs_PutVCache(tvc, WRITE_LOCK);
1654 if (hasatsys) osi_FreeLargeSpace(bufp);
1658 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1661 struct vrequest *areq;
1664 afs_int32 *aoutSize; /* set this */ {
1665 register struct cell *tcell;
1666 register afs_int32 i;
1667 register struct unixuser *tu;
1672 AFS_STATCNT(PGetTokens);
1673 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1674 return EIO; /* Inappropriate ioctl for device */
1676 /* weird interface. If input parameter is present, it is an integer and
1677 we're supposed to return the parm'th tokens for this unix uid.
1678 If not present, we just return tokens for cell 1.
1679 If counter out of bounds, return EDOM.
1680 If no tokens for the particular cell, return ENOTCONN.
1681 Also, if this mysterious parm is present, we return, along with the
1682 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1683 at the end, in that order.
1685 if (newStyle = (ainSize > 0)) {
1686 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1688 i = UHash(areq->uid);
1689 ObtainReadLock(&afs_xuser);
1690 for(tu = afs_users[i]; tu; tu=tu->next) {
1692 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1693 if (iterator-- == 0) break; /* are we done yet? */
1697 if (tu->uid == areq->uid && tu->cell == 1) break;
1702 * No need to hold a read lock on each user entry
1706 ReleaseReadLock(&afs_xuser);
1711 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1712 tu->states |= (UTokensBad | UNeedsReset);
1713 afs_PutUser(tu, READ_LOCK);
1716 /* use iterator for temp */
1718 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1719 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1720 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1721 cp += sizeof(afs_int32);
1722 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1724 iterator = sizeof(struct ClearToken);
1725 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1726 cp += sizeof(afs_int32);
1727 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1728 cp += sizeof(struct ClearToken);
1730 /* put out primary id and cell name, too */
1731 iterator = (tu->states & UPrimary ? 1 : 0);
1732 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1733 cp += sizeof(afs_int32);
1734 tcell = afs_GetCell(tu->cell, READ_LOCK);
1736 strcpy(cp, tcell->cellName);
1737 cp += strlen(tcell->cellName)+1;
1738 afs_PutCell(tcell, READ_LOCK);
1742 *aoutSize = cp - aout;
1743 afs_PutUser(tu, READ_LOCK);
1747 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1750 struct vrequest *areq;
1753 afs_int32 *aoutSize; /* set this */ {
1754 register afs_int32 i;
1755 register struct unixuser *tu;
1757 AFS_STATCNT(PUnlog);
1758 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1759 return EIO; /* Inappropriate ioctl for device */
1761 i = UHash(areq->uid);
1762 ObtainWriteLock(&afs_xuser,227);
1763 for(tu=afs_users[i]; tu; tu=tu->next) {
1764 if (tu->uid == areq->uid) {
1766 tu->states &= ~UHasTokens;
1767 /* security is not having to say you're sorry */
1768 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1770 ReleaseWriteLock(&afs_xuser);
1771 /* We have to drop the lock over the call to afs_ResetUserConns, since
1772 * it obtains the afs_xvcache lock. We could also keep the lock, and
1773 * modify ResetUserConns to take parm saying we obtained the lock
1774 * already, but that is overkill. By keeping the "tu" pointer
1775 * held over the released lock, we guarantee that we won't lose our
1776 * place, and that we'll pass over every user conn that existed when
1777 * we began this call.
1779 afs_ResetUserConns(tu);
1781 ObtainWriteLock(&afs_xuser,228);
1784 ReleaseWriteLock(&afs_xuser);
1788 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1791 struct vrequest *areq;
1794 afs_int32 *aoutSize; /* set this */ {
1795 afs_int32 newHostAddr;
1796 afs_int32 oldHostAddr;
1798 AFS_STATCNT(PMariner);
1800 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1802 oldHostAddr = 0xffffffff; /* disabled */
1804 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1805 if (newHostAddr == 0xffffffff) {
1806 /* disable mariner operations */
1809 else if (newHostAddr) {
1811 afs_marinerHost = newHostAddr;
1813 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1814 *aoutSize = sizeof(afs_int32);
1818 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1821 struct vrequest *areq;
1824 afs_int32 *aoutSize; /* set this */
1825 struct AFS_UCRED *acred;
1827 register char *cp = 0;
1829 register struct server *ts;
1830 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1832 struct chservinfo *pcheck;
1834 AFS_STATCNT(PCheckServers);
1836 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1837 return EIO; /* Inappropriate ioctl for device */
1839 if (*lp == 0x12345678) { /* For afs3.3 version */
1840 pcheck=(struct chservinfo *)ain;
1841 if (pcheck->tinterval >= 0) {
1843 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1844 *aoutSize = sizeof(afs_int32);
1845 if (pcheck->tinterval > 0) {
1846 if (!afs_osi_suser(acred))
1848 PROBE_INTERVAL=pcheck->tinterval;
1854 temp=pcheck->tflags;
1855 cp = pcheck->tbuffer;
1856 } else { /* For pre afs3.3 versions */
1857 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1858 cp = ain+sizeof(afs_int32);
1859 if (ainSize > sizeof(afs_int32))
1864 * 1: fast check, don't contact servers.
1865 * 2: local cell only.
1868 /* have cell name, too */
1869 cellp = afs_GetCellByName(cp, READ_LOCK);
1870 if (!cellp) return ENOENT;
1872 else cellp = (struct cell *) 0;
1873 if (!cellp && (temp & 2)) {
1874 /* use local cell */
1875 cellp = afs_GetCell(1, READ_LOCK);
1877 if (!(temp & 1)) { /* if not fast, call server checker routine */
1878 afs_CheckServers(1, cellp); /* check down servers */
1879 afs_CheckServers(0, cellp); /* check up servers */
1881 /* now return the current down server list */
1883 ObtainReadLock(&afs_xserver);
1884 for(i=0;i<NSERVERS;i++) {
1885 for(ts = afs_servers[i]; ts; ts=ts->next) {
1886 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1887 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1888 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1889 cp += sizeof(afs_int32);
1893 ReleaseReadLock(&afs_xserver);
1894 if (cellp) afs_PutCell(cellp, READ_LOCK);
1895 *aoutSize = cp - aout;
1899 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1902 struct vrequest *areq;
1905 afs_int32 *aoutSize; /* set this */ {
1906 AFS_STATCNT(PCheckVolNames);
1907 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1908 return EIO; /* Inappropriate ioctl for device */
1910 afs_CheckRootVolume();
1911 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1912 AFS_VOLCHECK_EXPIRED |
1914 AFS_VOLCHECK_MTPTS);
1918 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1921 struct vrequest *areq;
1924 afs_int32 *aoutSize; /* set this */ {
1928 struct unixuser *tu;
1930 extern afs_rwlock_t afs_xsrvAddr;
1932 AFS_STATCNT(PCheckAuth);
1933 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1934 return EIO; /* Inappropriate ioctl for device */
1937 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1938 if (!tu) retValue = EACCES;
1940 /* we have a user */
1941 ObtainReadLock(&afs_xsrvAddr);
1942 ObtainReadLock(&afs_xconn);
1944 /* any tokens set? */
1945 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1946 /* all connections in cell 1 working? */
1947 for(i=0;i<NSERVERS;i++) {
1948 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1949 for (tc = sa->conns; tc; tc=tc->next) {
1950 if (tc->user == tu && (tu->states & UTokensBad))
1955 ReleaseReadLock(&afs_xsrvAddr);
1956 ReleaseReadLock(&afs_xconn);
1957 afs_PutUser(tu, READ_LOCK);
1959 bcopy((char *)&retValue, aout, sizeof(afs_int32));
1960 *aoutSize = sizeof(afs_int32);
1964 static Prefetch(apath, adata, afollow, acred)
1966 struct afs_ioctl *adata;
1968 struct AFS_UCRED *acred;
1971 register afs_int32 code;
1974 AFS_STATCNT(Prefetch);
1975 if (!apath) return EINVAL;
1976 tp = osi_AllocLargeSpace(1024);
1977 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1979 osi_FreeLargeSpace(tp);
1982 if (afs_BBusy()) { /* do this as late as possible */
1983 osi_FreeLargeSpace(tp);
1984 return EWOULDBLOCK; /* pretty close */
1986 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
1990 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
1993 struct vrequest *areq;
1996 afs_int32 *aoutSize; /* set this */ {
1997 register struct volume *tvp;
1998 register struct server *ts;
1999 register afs_int32 i;
2002 AFS_STATCNT(PFindVolume);
2003 if (!avc) return EINVAL;
2004 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2007 for(i=0;i<MAXHOSTS;i++) {
2008 ts = tvp->serverHost[i];
2010 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
2011 cp += sizeof(afs_int32);
2014 /* still room for terminating NULL, add it on */
2015 ainSize = 0; /* reuse vbl */
2016 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
2017 cp += sizeof(afs_int32);
2019 *aoutSize = cp - aout;
2020 afs_PutVolume(tvp, READ_LOCK);
2026 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
2029 struct vrequest *areq;
2032 afs_int32 *aoutSize; /* set this */ {
2033 register afs_int32 code;
2036 AFS_STATCNT(PViceAccess);
2037 if (!avc) return EINVAL;
2038 code = afs_VerifyVCache(avc, areq);
2039 if (code) return code;
2040 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2041 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2046 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2049 struct vrequest *areq;
2052 afs_int32 *aoutSize; /* set this */
2053 struct AFS_UCRED *acred;
2058 AFS_STATCNT(PSetCacheSize);
2059 if (!afs_osi_suser(acred))
2061 /* too many things are setup initially in mem cache version */
2062 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2063 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2064 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2066 extern u_int afs_min_cache;
2067 if (newValue < afs_min_cache)
2068 afs_cacheBlocks = afs_min_cache;
2070 afs_cacheBlocks = newValue;
2072 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2073 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2074 afs_MaybeWakeupTruncateDaemon();
2075 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2076 afs_osi_Wait(1000, 0, 0);
2077 afs_MaybeWakeupTruncateDaemon();
2082 #define MAXGCSTATS 16
2083 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2086 struct vrequest *areq;
2089 afs_int32 *aoutSize; /* set this */ {
2090 afs_int32 results[MAXGCSTATS];
2092 AFS_STATCNT(PGetCacheSize);
2093 bzero((char *)results, sizeof(results));
2094 results[0] = afs_cacheBlocks;
2095 results[1] = afs_blocksUsed;
2096 bcopy((char *)results, aout, sizeof(results));
2097 *aoutSize = sizeof(results);
2101 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2104 struct vrequest *areq;
2107 afs_int32 *aoutSize; /* set this */ {
2108 register struct conn *tc;
2109 register afs_int32 code;
2110 struct AFSCallBack CallBacks_Array[1];
2111 struct AFSCBFids theFids;
2112 struct AFSCBs theCBs;
2115 AFS_STATCNT(PRemoveCallBack);
2116 if (!avc) return EINVAL;
2117 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2118 ObtainWriteLock(&avc->lock,229);
2119 theFids.AFSCBFids_len = 1;
2120 theCBs.AFSCBs_len = 1;
2121 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2122 theCBs.AFSCBs_val = CallBacks_Array;
2123 CallBacks_Array[0].CallBackType = CB_DROPPED;
2124 if (avc->callback) {
2126 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2128 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2129 #ifdef RX_ENABLE_LOCKS
2131 #endif /* RX_ENABLE_LOCKS */
2132 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2133 #ifdef RX_ENABLE_LOCKS
2135 #endif /* RX_ENABLE_LOCKS */
2138 /* don't set code on failure since we wouldn't use it */
2140 (afs_Analyze(tc, code, &avc->fid, areq,
2141 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2142 SHARED_LOCK, (struct cell *)0));
2144 ObtainWriteLock(&afs_xcbhash, 457);
2145 afs_DequeueCallback(avc);
2147 avc->states &= ~(CStatd | CUnique);
2148 ReleaseWriteLock(&afs_xcbhash);
2149 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2150 osi_dnlc_purgedp(avc);
2152 ReleaseWriteLock(&avc->lock);
2156 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2159 struct vrequest *areq;
2163 struct AFS_UCRED *acred;
2164 afs_int32 *aoutSize; /* set this */ {
2165 /* create a new cell */
2166 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2167 register struct cell *tcell;
2168 char *newcell=0, *linkedcell=0, *tp= ain;
2169 register afs_int32 code, linkedstate=0, ls;
2170 u_short fsport = 0, vlport = 0;
2173 AFS_STATCNT(PNewCell);
2174 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2175 return EIO; /* Inappropriate ioctl for device */
2177 if (!afs_osi_suser(acred))
2180 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2181 tp += sizeof(afs_int32);
2182 if (magic != 0x12345678)
2185 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2186 * server addresses while the 3.5 fs newcell command passes
2187 * MAXHOSTS. To figure out which is which, check if the cellname
2190 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2191 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2193 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2194 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2195 tp += (scount * sizeof(afs_int32));
2197 lp = (afs_int32 *)tp;
2200 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2201 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2202 tp += (3 * sizeof(afs_int32));
2204 if ((ls = *lp) & 1) {
2205 linkedcell = tp + strlen(newcell)+1;
2206 linkedstate |= CLinkedCell;
2209 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2210 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport);
2214 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2217 struct vrequest *areq;
2220 afs_int32 *aoutSize; /* set this */ {
2221 afs_int32 whichCell;
2222 register struct cell *tcell=0;
2223 register afs_int32 i;
2224 register char *cp, *tp = ain;
2225 register struct afs_q *cq, *tq;
2227 AFS_STATCNT(PListCells);
2228 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2229 return EIO; /* Inappropriate ioctl for device */
2231 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2232 tp += sizeof(afs_int32);
2233 ObtainReadLock(&afs_xcell);
2234 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2235 tcell = QTOC(cq); tq = QNext(cq);
2236 if (whichCell == 0) break;
2237 if (tq == &CellLRU) tcell = 0;
2242 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2243 for(i=0;i<MAXCELLHOSTS;i++) {
2244 if (tcell->cellHosts[i] == 0) break;
2245 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2246 cp += sizeof(afs_int32);
2248 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2249 strcpy(cp, tcell->cellName);
2250 cp += strlen(tcell->cellName)+1;
2251 *aoutSize = cp - aout;
2253 ReleaseReadLock(&afs_xcell);
2254 if (tcell) return 0;
2258 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2261 struct vrequest *areq;
2265 afs_int32 *aoutSize; /* set this */ {
2266 register afs_int32 code;
2268 afs_int32 offset, len, hasatsys = 0;
2269 register struct conn *tc;
2270 register struct dcache *tdc;
2271 register struct vcache *tvc;
2272 struct AFSFetchStatus OutDirStatus;
2273 struct VenusFid tfid;
2274 struct AFSVolSync tsync;
2278 /* "ain" is the name of the file in this dir to remove */
2280 AFS_STATCNT(PRemoveMount);
2281 if (!avc) return EINVAL;
2282 code = afs_VerifyVCache(avc, areq);
2283 if (code) return code;
2284 if (vType(avc) != VDIR) return ENOTDIR;
2286 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2287 if (!tdc) return ENOENT;
2288 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2289 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2294 tfid.Cell = avc->fid.Cell;
2295 tfid.Fid.Volume = avc->fid.Fid.Volume;
2296 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2297 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2299 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2300 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2307 if (vType(tvc) != VLNK) {
2309 afs_PutVCache(tvc, WRITE_LOCK);
2313 ObtainWriteLock(&tvc->lock,230);
2314 code = afs_HandleLink(tvc, areq);
2316 if (tvc->linkData) {
2317 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2322 ReleaseWriteLock(&tvc->lock);
2323 osi_dnlc_purgedp(tvc);
2324 afs_PutVCache(tvc, WRITE_LOCK);
2329 ObtainWriteLock(&avc->lock,231);
2330 osi_dnlc_remove(avc, bufp, tvc);
2332 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2334 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2335 #ifdef RX_ENABLE_LOCKS
2337 #endif /* RX_ENABLE_LOCKS */
2338 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2339 bufp, &OutDirStatus, &tsync);
2340 #ifdef RX_ENABLE_LOCKS
2342 #endif /* RX_ENABLE_LOCKS */
2347 (afs_Analyze(tc, code, &avc->fid, areq,
2348 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2349 SHARED_LOCK, (struct cell *)0));
2352 if (tdc) afs_PutDCache(tdc);
2353 ReleaseWriteLock(&avc->lock);
2357 /* we have the thing in the cache */
2358 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2359 /* we can do it locally */
2360 code = afs_dir_Delete(&tdc->f.inode, bufp);
2362 ZapDCE(tdc); /* surprise error -- invalid value */
2363 DZap(&tdc->f.inode);
2366 afs_PutDCache(tdc); /* drop ref count */
2368 avc->states &= ~CUnique; /* For the dfs xlator */
2369 ReleaseWriteLock(&avc->lock);
2372 if (hasatsys) osi_FreeLargeSpace(bufp);
2376 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2379 struct vrequest *areq;
2383 struct AFS_UCRED *acred;
2384 afs_int32 *aoutSize; /* set this */ {
2385 return EINVAL; /* OBSOLETE */
2388 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2391 struct vrequest *areq;
2394 afs_int32 *aoutSize; /* set this */ {
2395 register struct cell *tcell;
2398 AFS_STATCNT(PGetCellStatus);
2399 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2400 return EIO; /* Inappropriate ioctl for device */
2402 tcell = afs_GetCellByName(ain, READ_LOCK);
2403 if (!tcell) return ENOENT;
2404 temp = tcell->states;
2405 afs_PutCell(tcell, READ_LOCK);
2406 bcopy((char *)&temp, aout, sizeof(afs_int32));
2407 *aoutSize = sizeof(afs_int32);
2411 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2414 struct vrequest *areq;
2417 struct AFS_UCRED *acred;
2418 afs_int32 *aoutSize; /* set this */ {
2419 register struct cell *tcell;
2422 if (!afs_osi_suser(acred))
2424 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2425 return EIO; /* Inappropriate ioctl for device */
2427 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2428 if (!tcell) return ENOENT;
2429 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2431 tcell->states |= CNoSUID;
2433 tcell->states &= ~CNoSUID;
2434 afs_PutCell(tcell, WRITE_LOCK);
2438 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2441 struct vrequest *areq;
2444 afs_int32 *aoutSize; /* set this */
2445 struct AFS_UCRED *acred;
2447 extern struct volume *afs_volumes[NVOLS];
2448 register afs_int32 i;
2449 register struct dcache *tdc;
2450 register struct vcache *tvc;
2451 register struct volume *tv;
2452 afs_int32 cell, volume;
2454 AFS_STATCNT(PFlushVolumeData);
2457 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2458 return EIO; /* Inappropriate ioctl for device */
2460 volume = avc->fid.Fid.Volume; /* who to zap */
2461 cell = avc->fid.Cell;
2464 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2465 * the vcaches associated with the volume.
2467 ObtainReadLock(&afs_xvcache);
2468 for(i = 0; i < VCSIZE; i++) {
2469 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2470 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2471 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2472 VN_HOLD((struct vnode *)tvc);
2476 ReleaseReadLock(&afs_xvcache);
2477 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2478 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2480 ObtainWriteLock(&tvc->lock,232);
2482 ObtainWriteLock(&afs_xcbhash, 458);
2483 afs_DequeueCallback(tvc);
2484 tvc->states &= ~(CStatd | CDirty);
2485 ReleaseWriteLock(&afs_xcbhash);
2486 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2487 osi_dnlc_purgedp(tvc);
2488 afs_TryToSmush(tvc, acred, 1);
2489 ReleaseWriteLock(&tvc->lock);
2490 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2491 afs_BozonUnlock(&tvc->pvnLock, tvc);
2493 ObtainReadLock(&afs_xvcache);
2494 /* our tvc ptr is still good until now */
2499 ReleaseReadLock(&afs_xvcache);
2502 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2503 for(i=0;i<afs_cacheFiles;i++) {
2504 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2505 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2506 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2507 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2508 if (! (afs_indexFlags[i] & IFDataMod)) {
2509 /* if the file is modified, but has a ref cnt of only 1, then
2510 someone probably has the file open and is writing into it.
2511 Better to skip flushing such a file, it will be brought back
2512 immediately on the next write anyway.
2514 If we *must* flush, then this code has to be rearranged to call
2515 afs_storeAllSegments() first */
2516 afs_FlushDCache(tdc);
2520 tdc->refCount--; /* bumped by getdslot */
2522 MReleaseWriteLock(&afs_xdcache);
2524 ObtainReadLock(&afs_xvolume);
2525 for (i=0;i<NVOLS;i++) {
2526 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2527 if (tv->volume == volume) {
2528 afs_ResetVolumeInfo(tv);
2533 ReleaseReadLock(&afs_xvolume);
2535 /* probably, a user is doing this, probably, because things are screwed up.
2536 * maybe it's the dnlc's fault? */
2543 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2546 struct vrequest *areq;
2549 afs_int32 *aoutSize; /* set this */ {
2550 register afs_int32 code;
2551 struct vcxstat stat;
2554 /* AFS_STATCNT(PGetVnodeXStatus); */
2555 if (!avc) return EINVAL;
2556 code = afs_VerifyVCache(avc, areq);
2557 if (code) return code;
2558 if (vType(avc) == VDIR)
2559 mode = PRSFS_LOOKUP;
2562 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2564 stat.fid = avc->fid;
2565 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2566 stat.lock = avc->lock;
2567 stat.parentVnode = avc->parentVnode;
2568 stat.parentUnique = avc->parentUnique;
2569 hset(stat.flushDV, avc->flushDV);
2570 hset(stat.mapDV, avc->mapDV);
2571 stat.truncPos = avc->truncPos;
2572 { /* just grab the first two - won't break anything... */
2573 struct axscache *ac;
2575 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2576 stat.randomUid[i] = ac->uid;
2577 stat.randomAccess[i] = ac->axess;
2580 stat.callback = afs_data_pointer_to_int32(avc->callback);
2581 stat.cbExpires = avc->cbExpires;
2582 stat.anyAccess = avc->anyAccess;
2583 stat.opens = avc->opens;
2584 stat.execsOrWriters = avc->execsOrWriters;
2585 stat.flockCount = avc->flockCount;
2586 stat.mvstat = avc->mvstat;
2587 stat.states = avc->states;
2588 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2589 *aoutSize = sizeof(struct vcxstat);
2594 /* We require root for local sysname changes, but not for remote */
2595 /* (since we don't really believe remote uids anyway) */
2596 /* outname[] shouldn't really be needed- this is left as an excercise */
2597 /* for the reader. */
2599 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2602 struct vrequest *areq;
2605 afs_int32 *aoutSize; /* set this */
2606 register struct AFS_UCRED *acred;
2608 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2609 int setsysname, foundname=0;
2610 register struct afs_exporter *exporter;
2611 extern struct unixuser *afs_FindUser();
2612 extern char *afs_sysname;
2613 register struct unixuser *au;
2614 register afs_int32 pag, error;
2618 AFS_STATCNT(PSetSysName);
2619 if (!afs_globalVFS) {
2620 /* Afsd is NOT running; disable it */
2621 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
2624 return (setuerror(EINVAL), EINVAL);
2627 bzero(inname, MAXSYSNAME);
2628 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2629 ain += sizeof(afs_int32);
2634 bcopy(ain, inname, t+1); /* include terminating null */
2637 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2638 pag = PagInCred(acred);
2640 return EINVAL; /* Better than panicing */
2642 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2643 return EINVAL; /* Better than panicing */
2645 if (!(exporter = au->exporter)) {
2646 afs_PutUser(au, READ_LOCK);
2647 return EINVAL; /* Better than panicing */
2649 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2651 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2653 afs_PutUser(au, READ_LOCK);
2658 afs_PutUser(au, READ_LOCK);
2660 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2662 strcpy(outname, afs_sysname);
2665 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2667 strcpy(afs_sysname, inname);
2672 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2673 cp += sizeof(afs_int32);
2675 strcpy(cp, outname);
2676 cp += strlen(outname)+1;
2678 *aoutSize = cp - aout;
2683 /* sequential search through the list of touched cells is not a good
2684 * long-term solution here. For small n, though, it should be just
2685 * fine. Should consider special-casing the local cell for large n.
2686 * Likewise for PSetSPrefs.
2688 static void ReSortCells(s,l, vlonly)
2689 int s; /* number of ids in array l[] -- NOT index of last id */
2690 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2691 int vlonly; /* sort vl servers or file servers?*/
2693 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2702 tcell = afs_GetCell(l[k], WRITE_LOCK);
2703 if (!tcell) continue;
2704 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2705 afs_PutCell(tcell, WRITE_LOCK);
2710 ObtainReadLock(&afs_xvolume);
2711 for (i= 0; i< NVOLS; i++) {
2712 for (j=afs_volumes[i];j;j=j->next) {
2714 if (j->cell == l[k]) {
2715 ObtainWriteLock(&j->lock,233);
2716 afs_SortServers(j->serverHost, MAXHOSTS);
2717 ReleaseWriteLock(&j->lock);
2722 ReleaseReadLock(&afs_xvolume);
2727 static int afs_setsprefs(sp, num, vlonly)
2730 unsigned int vlonly;
2733 int i,j,k,matches,touchedSize;
2734 struct server *srvr = NULL;
2735 afs_int32 touched[34];
2739 for (k=0; k < num; sp++, k++) {
2741 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2744 ObtainReadLock(&afs_xserver);
2746 i = SHash(sp->host.s_addr);
2747 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2748 if (sa->sa_ip == sp->host.s_addr) {
2750 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2751 || (sa->sa_portal == AFS_FSPORT);
2752 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2759 if (sa && matches) { /* found one! */
2761 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2763 sa->sa_iprank = sp->rank + afs_randomMod15();
2764 afs_SortOneServer(sa->server);
2767 /* if we don't know yet what cell it's in, this is moot */
2768 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2769 /* is it in our list of touched cells ? */ ;
2770 if (j < 0) { /* no, it's not */
2771 touched[touchedSize++] = srvr->cell->cell;
2772 if (touchedSize >= 32) { /* watch for ovrflow */
2773 ReleaseReadLock(&afs_xserver);
2774 ReSortCells(touchedSize, touched, vlonly);
2776 ObtainReadLock(&afs_xserver);
2782 ReleaseReadLock(&afs_xserver);
2783 /* if we didn't find one, start to create one. */
2784 /* Note that it doesn't have a cell yet... */
2786 afs_uint32 temp = sp->host.s_addr;
2787 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2788 WRITE_LOCK, (afsUUID *)0,0);
2789 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2790 afs_PutServer(srvr, WRITE_LOCK);
2792 } /* for all cited preferences */
2794 ReSortCells(touchedSize, touched, vlonly);
2798 /* Note that this may only be performed by the local root user.
2801 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2804 struct vrequest *areq;
2807 struct AFS_UCRED *acred;
2808 afs_int32 *aoutSize;
2810 struct setspref *ssp;
2811 AFS_STATCNT(PSetSPrefs);
2813 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2814 return EIO; /* Inappropriate ioctl for device */
2816 if (!afs_osi_suser(acred))
2819 if (ainSize < sizeof(struct setspref))
2822 ssp = (struct setspref *)ain;
2823 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2826 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2827 (ssp->flags & DBservers));
2832 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2835 struct vrequest *areq;
2838 struct AFS_UCRED *acred;
2839 afs_int32 *aoutSize;
2842 AFS_STATCNT(PSetSPrefs);
2843 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2844 return EIO; /* Inappropriate ioctl for device */
2847 if (!afs_osi_suser(acred))
2850 sp = (struct spref *)ain;
2851 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2855 /* some notes on the following code...
2856 * in the hash table of server structs, all servers with the same IP address
2857 * will be on the same overflow chain.
2858 * This could be sped slightly in some circumstances by having it cache the
2859 * immediately previous slot in the hash table and some supporting information
2860 * Only reports file servers now.
2863 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2866 struct vrequest *areq;
2869 afs_int32 *aoutSize;
2871 struct sprefrequest *spin; /* input */
2872 struct sprefinfo *spout; /* output */
2873 struct spref *srvout; /* one output component */
2874 int i,j; /* counters for hash table traversal */
2875 struct server *srvr; /* one of CM's server structs */
2878 int vlonly; /* just return vlservers ? */
2881 AFS_STATCNT(PGetSPrefs);
2882 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2883 return EIO; /* Inappropriate ioctl for device */
2886 if (ainSize < sizeof (struct sprefrequest_33)) {
2890 spin = ((struct sprefrequest *) ain);
2893 if (ainSize > sizeof (struct sprefrequest_33)) {
2894 vlonly = (spin->flags & DBservers);
2898 /* struct sprefinfo includes 1 server struct... that size gets added
2899 * in during the loop that follows.
2901 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2902 spout = (struct sprefinfo *) aout;
2903 spout->next_offset = spin->offset;
2904 spout->num_servers = 0;
2905 srvout = spout->servers;
2907 ObtainReadLock(&afs_xserver);
2908 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2909 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2910 if (spin->offset > (unsigned short)i) {
2911 continue; /* catch up to where we left off */
2913 spout->next_offset++;
2916 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2917 || (sa->sa_portal == AFS_FSPORT);
2919 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2920 /* only report ranks for vl servers */
2924 srvout->host.s_addr = sa->sa_ip;
2925 srvout->rank = sa->sa_iprank;
2926 *aoutSize += sizeof(struct spref);
2927 spout->num_servers++;
2930 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2931 ReleaseReadLock(&afs_xserver); /* no more room! */
2936 ReleaseReadLock(&afs_xserver);
2938 spout->next_offset = 0; /* start over from the beginning next time */
2942 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2943 int afs_NFSRootOnly = 1;
2944 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2947 struct vrequest *areq;
2950 afs_int32 *aoutSize; /* set this */
2951 struct AFS_UCRED *acred;
2953 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2954 extern struct afs_exporter *exporter_find();
2955 register struct afs_exporter *exporter;
2957 AFS_STATCNT(PExportAfs);
2958 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
2959 type = handleValue >> 24;
2964 exporter = exporter_find(type);
2966 export = handleValue & 3;
2967 changestate = handleValue & 0xff;
2968 smounts = (handleValue >> 2) & 3;
2969 pwsync = (handleValue >> 4) & 3;
2970 convmode = (handleValue >> 6) & 3;
2972 changestate = (handleValue >> 16) & 0x1;
2973 convmode = (handleValue >> 16) & 0x2;
2974 pwsync = (handleValue >> 16) & 0x4;
2975 smounts = (handleValue >> 16) & 0x8;
2976 export = handleValue & 0xff;
2979 /* Failed finding desired exporter; */
2983 handleValue = exporter->exp_states;
2984 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2985 *aoutSize = sizeof(afs_int32);
2987 if (!afs_osi_suser(acred))
2988 return EACCES; /* Only superuser can do this */
2992 exporter->exp_states |= EXP_EXPORTED;
2994 exporter->exp_states &= ~EXP_EXPORTED;
2998 exporter->exp_states |= EXP_UNIXMODE;
3000 exporter->exp_states &= ~EXP_UNIXMODE;
3004 exporter->exp_states |= EXP_PWSYNC;
3006 exporter->exp_states &= ~EXP_PWSYNC;
3010 afs_NFSRootOnly = 0;
3011 exporter->exp_states |= EXP_SUBMOUNTS;
3013 afs_NFSRootOnly = 1;
3014 exporter->exp_states &= ~EXP_SUBMOUNTS;
3017 handleValue = exporter->exp_states;
3018 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
3019 *aoutSize = sizeof(afs_int32);
3022 exporter->exp_states |= EXP_EXPORTED;
3024 exporter->exp_states &= ~EXP_EXPORTED;
3026 exporter->exp_states |= EXP_UNIXMODE;
3028 exporter->exp_states &= ~EXP_UNIXMODE;
3030 exporter->exp_states |= EXP_PWSYNC;
3032 exporter->exp_states &= ~EXP_PWSYNC;
3034 afs_NFSRootOnly = 0;
3035 exporter->exp_states |= EXP_SUBMOUNTS;
3037 afs_NFSRootOnly = 1;
3038 exporter->exp_states &= ~EXP_SUBMOUNTS;
3047 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3050 struct vrequest *areq;
3053 struct AFS_UCRED *acred;
3054 afs_int32 *aoutSize; /* set this */
3056 struct gaginfo *gagflags;
3058 if (!afs_osi_suser(acred))
3061 gagflags = (struct gaginfo *) ain;
3062 afs_showflags = gagflags->showflags;
3069 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3072 struct vrequest *areq;
3075 struct AFS_UCRED *acred;
3076 afs_int32 *aoutSize;
3078 struct rxparams *rxp;
3080 if (!afs_osi_suser(acred))
3083 rxp = (struct rxparams *) ain;
3085 if (rxp->rx_initReceiveWindow)
3086 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3087 if (rxp->rx_maxReceiveWindow)
3088 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3089 if (rxp->rx_initSendWindow)
3090 rx_initSendWindow = rxp->rx_initSendWindow;
3091 if (rxp->rx_maxSendWindow)
3092 rx_maxSendWindow = rxp->rx_maxSendWindow;
3093 if (rxp->rxi_nSendFrags)
3094 rxi_nSendFrags = rxp->rxi_nSendFrags;
3095 if (rxp->rxi_nRecvFrags)
3096 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3097 if (rxp->rxi_OrphanFragSize)
3098 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3099 if (rxp->rx_maxReceiveSize)
3101 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3102 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3104 if (rxp->rx_MyMaxSendSize)
3105 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3110 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3113 struct vrequest *areq;
3117 afs_int32 *aoutSize; /* set this */
3119 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3122 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3123 *aoutSize = sizeof(struct cm_initparams);
3127 #ifdef AFS_SGI65_ENV
3128 /* They took crget() from us, so fake it. */
3129 static cred_t *crget(void)
3132 cr = crdup(get_current_cred());
3133 bzero((char*)cr, sizeof(cred_t));
3134 #if CELL || CELL_PREPARE
3142 PGetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3145 struct vrequest *areq;
3148 afs_int32 *aoutSize;
3149 struct AFS_UCRED *acred;
3151 bcopy((char *)&cryptall, aout, sizeof(afs_int32));
3152 *aoutSize=sizeof(afs_int32);
3157 PSetRxkcrypt(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3160 struct vrequest *areq;
3163 afs_int32 *aoutSize;
3164 struct AFS_UCRED *acred;
3168 if (!afs_osi_suser(acred))
3170 if (ainSize != sizeof(afs_int32) || ain == NULL)
3172 bcopy(ain, (char *)&tmpval, sizeof(afs_int32));
3173 /* if new mappings added later this will need to be changed */
3174 if (tmpval != 0 && tmpval != 1)
3181 * Create new credentials to correspond to a remote user with given
3182 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3183 * provide pioctl (and other) services to foreign clients (i.e. nfs
3184 * clients) by using this call to `become' the client.
3187 #define PIOCTL_HEADER 6
3188 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3191 afs_uint32 hostaddr;
3192 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3193 extern struct afs_exporter *exporter_find();
3194 struct afs_exporter *exporter, *outexporter;
3195 struct AFS_UCRED *newcred;
3196 struct unixuser *au;
3198 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3199 return EINVAL; /* NFS trans not supported for Ultrix */
3201 #if defined(AFS_SGIMP_ENV)
3202 osi_Assert(ISAFS_GLOCK());
3204 AFS_STATCNT(HandleClientContext);
3205 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3206 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3207 return EINVAL; /* Too small to be good */
3209 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3210 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3212 osi_FreeLargeSpace(inData);
3216 /* Extract information for remote user */
3217 hostaddr = *((afs_uint32 *)ain);
3218 ain += sizeof(hostaddr);
3219 uid = *((afs_uint32 *)ain);
3221 g0 = *((afs_uint32 *)ain);
3223 g1 = *((afs_uint32 *)ain);
3225 *com = *((afs_uint32 *)ain);
3226 ain += sizeof(afs_int32);
3227 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3230 * Of course, one must be root for most of these functions, but
3231 * we'll allow (for knfs) you to set things if the pag is 0 and
3232 * you're setting tokens or unlogging.
3235 if (!afs_osi_suser(credp)) {
3237 #ifndef AFS_SGI64_ENV
3238 /* Since SGI's suser() returns explicit failure after the call.. */
3242 /* check for acceptable opcodes for normal folks, which are, so far,
3243 * set tokens and unlog.
3245 if (i != 9 && i != 3 && i != 38 && i != 8) {
3246 osi_FreeLargeSpace(inData);
3251 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3252 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3253 osi_FreeLargeSpace(inData);
3256 * We map uid 0 to nobody to match the mapping that the nfs
3257 * server does and to ensure that the suser() calls in the afs
3258 * code fails for remote client roots.
3260 uid = afs_nobody; /* NFS_NOBODY == -2 */
3263 #ifdef AFS_AIX41_ENV
3266 newcred->cr_gid = RMTUSER_REQ;
3267 newcred->cr_groups[0] = g0;
3268 newcred->cr_groups[1] = g1;
3270 newcred->cr_ngrps = 2;
3272 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3273 newcred->cr_ngroups = 2;
3275 for (i=2; i<NGROUPS; i++)
3276 newcred->cr_groups[i] = NOGROUP;
3279 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3280 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3282 if (!(exporter = exporter_find(exporter_type))) {
3283 /* Exporter wasn't initialized or an invalid exporter type */
3287 if (exporter->exp_states & EXP_PWSYNC) {
3288 if (uid != credp->cr_uid) {
3290 return ENOEXEC; /* XXX Find a better errno XXX */
3293 newcred->cr_uid = uid; /* Only temporary */
3294 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3295 /* The client's pag is the only unique identifier for it */
3296 newcred->cr_uid = pag;
3298 if (!code && *com == PSETPAG) {
3299 /* Special case for 'setpag' */
3300 afs_uint32 pagvalue = genpag();
3302 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3304 * Note that we leave the 'outexporter' struct held so it won't
3307 au->exporter = outexporter;
3308 if (ablob->out_size >= 4) {
3309 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3311 afs_PutUser(au, WRITE_LOCK);
3312 if (code) return code;
3313 return PSETPAG; /* Special return for setpag */
3315 EXP_RELE(outexporter);
3318 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3321 /* get all interface addresses of this client */
3324 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3327 struct vrequest *areq;
3330 afs_int32 *aoutSize;
3332 struct sprefrequest *spin; /* input */
3333 struct sprefinfo *spout; /* output */
3334 struct spref *srvout; /* one output component */
3338 AFS_STATCNT(PGetCPrefs);
3339 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3340 return EIO; /* Inappropriate ioctl for device */
3342 if ( ainSize < sizeof (struct sprefrequest ))
3345 spin = (struct sprefrequest *) ain;
3346 spout = (struct sprefinfo *) aout;
3348 maxNumber = spin->num_servers; /* max addrs this time */
3349 srvout = spout->servers;
3351 ObtainReadLock(&afs_xinterface);
3353 /* copy out the client interface information from the
3354 ** kernel data structure "interface" to the output buffer
3356 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3357 && ( j< maxNumber) ; i++, j++, srvout++)
3358 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3360 spout->num_servers = j;
3361 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3363 if ( i >= afs_cb_interface.numberOfInterfaces )
3364 spout->next_offset = 0; /* start from beginning again */
3366 spout->next_offset = spin->offset + j;
3368 ReleaseReadLock(&afs_xinterface);
3373 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3376 struct vrequest *areq;
3379 afs_int32 *aoutSize;
3381 struct setspref *sin;
3384 AFS_STATCNT(PSetCPrefs);
3385 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3386 return EIO; /* Inappropriate ioctl for device */
3388 sin = (struct setspref *)ain;
3390 if ( ainSize < sizeof(struct setspref) )
3392 #if 0 /* num_servers is unsigned */
3393 if ( sin->num_servers < 0 )
3396 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3399 ObtainWriteLock(&afs_xinterface, 412);
3400 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3401 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3402 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3404 ReleaseWriteLock(&afs_xinterface);
3408 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3411 struct vrequest *areq;
3414 afs_int32 *aoutSize;
3415 struct AFS_UCRED *acred; {
3416 register afs_int32 code;
3417 register struct vcache *tvc;
3418 register struct dcache *tdc;
3419 struct VenusFid tfid;
3421 afs_int32 offset, len, hasatsys=0;
3423 AFS_STATCNT(PFlushMount);
3424 if (!avc) return EINVAL;
3425 code = afs_VerifyVCache(avc, areq);
3426 if (code) return code;
3427 if (vType(avc) != VDIR) {
3430 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3431 if (!tdc) return ENOENT;
3432 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3433 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3438 tfid.Cell = avc->fid.Cell;
3439 tfid.Fid.Volume = avc->fid.Fid.Volume;
3440 afs_PutDCache(tdc); /* we're done with the data */
3441 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3442 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3444 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3451 if (vType(tvc) != VLNK) {
3452 afs_PutVCache(tvc, WRITE_LOCK);
3456 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3457 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3459 ObtainWriteLock(&tvc->lock,645);
3460 ObtainWriteLock(&afs_xcbhash, 646);
3461 afs_DequeueCallback(tvc);
3462 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3463 ReleaseWriteLock(&afs_xcbhash);
3464 /* now find the disk cache entries */
3465 afs_TryToSmush(tvc, acred, 1);
3466 osi_dnlc_purgedp(tvc);
3467 afs_symhint_inval(tvc);
3468 if (tvc->linkData && !(tvc->states & CCore)) {
3469 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3470 tvc->linkData = (char *) 0;
3472 ReleaseWriteLock(&tvc->lock);
3473 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3474 afs_BozonUnlock(&tvc->pvnLock, tvc);
3476 afs_PutVCache(tvc, WRITE_LOCK);
3478 if (hasatsys) osi_FreeLargeSpace(bufp);
3482 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3485 struct vrequest *areq;
3488 afs_int32 *aoutSize;
3489 struct AFS_UCRED *acred;
3494 if (!afs_osi_suser(acred)) {
3498 if (ainSize != sizeof(afs_int32)) {
3502 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3503 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3507 if (flags & AFSCALL_RXSTATS_ENABLE) {
3508 rx_enableProcessRPCStats();
3510 if (flags & AFSCALL_RXSTATS_DISABLE) {
3511 rx_disableProcessRPCStats();
3513 if (flags & AFSCALL_RXSTATS_CLEAR) {
3514 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3522 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3525 struct vrequest *areq;
3528 afs_int32 *aoutSize;
3529 struct AFS_UCRED *acred;
3534 if (!afs_osi_suser(acred)) {
3538 if (ainSize != sizeof(afs_int32)) {
3542 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3543 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3547 if (flags & AFSCALL_RXSTATS_ENABLE) {
3548 rx_enablePeerRPCStats();
3550 if (flags & AFSCALL_RXSTATS_DISABLE) {
3551 rx_disablePeerRPCStats();
3553 if (flags & AFSCALL_RXSTATS_CLEAR) {
3554 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3561 static PPrefetchFromTape(avc, afun, areq, ain, aout, ainSize, aoutSize)
3564 struct vrequest *areq;
3567 afs_int32 *aoutSize; /* set this */
3569 register afs_int32 code, code1;
3572 struct rx_call *tcall;
3573 struct AFSVolSync tsync;
3574 struct AFSFetchStatus OutStatus;
3575 struct AFSCallBack CallBack;
3576 struct VenusFid tfid;
3581 AFS_STATCNT(PSetAcl);
3585 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3586 Fid = (struct AFSFid *) ain;
3588 Fid = &avc->fid.Fid;
3589 tfid.Cell = avc->fid.Cell;
3590 tfid.Fid.Volume = Fid->Volume;
3591 tfid.Fid.Vnode = Fid->Vnode;
3592 tfid.Fid.Unique = Fid->Unique;
3594 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3597 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3598 ICL_TYPE_POINTER, tvc,
3599 ICL_TYPE_FID, &tfid,
3600 ICL_TYPE_FID, &avc->fid);
3603 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3604 ICL_TYPE_POINTER, tvc,
3605 ICL_TYPE_FID, &tfid,
3606 ICL_TYPE_FID, &tvc->fid);
3609 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3612 #ifdef RX_ENABLE_LOCKS
3614 #endif /* RX_ENABLE_LOCKS */
3615 tcall = rx_NewCall(tc->id);
3616 code = StartRXAFS_FetchData(tcall,
3617 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3619 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3620 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3622 code1 = rx_EndCall(tcall, code);
3623 #ifdef RX_ENABLE_LOCKS
3625 #endif /* RX_ENABLE_LOCKS */
3629 (afs_Analyze(tc, code, &tvc->fid, areq,
3630 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3632 /* This call is done only to have the callback things handled correctly */
3633 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3634 afs_PutVCache(tvc, WRITE_LOCK);
3637 *aoutSize = sizeof(afs_int32);
3642 static PResidencyCmd(avc, afun, areq, ain, aout, ainSize, aoutSize)
3645 struct vrequest *areq;
3648 afs_int32 *aoutSize; /* set this */
3650 register afs_int32 code;
3653 struct ResidencyCmdInputs *Inputs;
3654 struct ResidencyCmdOutputs *Outputs;
3655 struct VenusFid tfid;
3658 Inputs = (struct ResidencyCmdInputs *) ain;
3659 Outputs = (struct ResidencyCmdOutputs *) aout;
3660 if (!avc) return EINVAL;
3661 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3665 Fid = &avc->fid.Fid;
3667 tfid.Cell = avc->fid.Cell;
3668 tfid.Fid.Volume = Fid->Volume;
3669 tfid.Fid.Vnode = Fid->Vnode;
3670 tfid.Fid.Unique = Fid->Unique;
3672 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache *)0,
3674 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3675 ICL_TYPE_POINTER, tvc,
3676 ICL_TYPE_INT32, Inputs->command,
3677 ICL_TYPE_FID, &tfid);
3681 if (Inputs->command) {
3683 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3685 #ifdef RX_ENABLE_LOCKS
3687 #endif /* RX_ENABLE_LOCKS */
3688 code = RXAFS_ResidencyCmd(tc->id, Fid,
3690 (struct ResidencyCmdOutputs *) aout);
3691 #ifdef RX_ENABLE_LOCKS
3693 #endif /* RX_ENABLE_LOCKS */
3697 (afs_Analyze(tc, code, &tvc->fid, areq,
3698 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3700 /* This call is done to have the callback things handled correctly */
3701 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3702 } else { /* just a status request, return also link data */
3704 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3705 Outputs->chars[0] = 0;
3706 if (vType(tvc) == VLNK) {
3707 ObtainWriteLock(&tvc->lock,555);
3708 if (afs_HandleLink(tvc, areq) == 0)
3709 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3710 ReleaseWriteLock(&tvc->lock);
3714 afs_PutVCache(tvc, WRITE_LOCK);
3717 *aoutSize = sizeof(struct ResidencyCmdOutputs);