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;
48 static int PBogus(), PSetAcl(), PGetAcl(), PSetTokens(), PGetVolumeStatus();
49 static int PSetVolumeStatus(), PFlush(), PNewStatMount(), PGetTokens(), PUnlog();
50 static int PCheckServers(), PCheckVolNames(), PCheckAuth(), PFindVolume();
51 static int PViceAccess(), PSetCacheSize(), Prefetch();
52 static int PRemoveCallBack(), PNewCell(), PListCells(), PRemoveMount();
53 static int PMariner(), PGetUserCell(), PGetWSCell(), PGetFileCell();
54 static int PVenusLogging(), PNoop(), PSetCellStatus(), PGetCellStatus();
55 static int PFlushVolumeData(), PGetCacheSize();
56 static int PSetSysName(),PGetFID();
57 static int PGetVnodeXStatus();
58 static int PSetSPrefs(), PGetSPrefs(), PGag(), PTwiddleRx();
59 static int PSetSPrefs33(), PStoreBehind(), PGCPAGs();
60 static int PGetCPrefs(), PSetCPrefs(); /* client network addresses */
61 static int PGetInitParams(), PFlushMount(), PRxStatProc(), PRxStatPeer();
64 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp);
66 extern struct cm_initparams cm_initParams;
68 static int (*(pioctlSw[]))() = {
73 PGetVolumeStatus, /* 4 */
74 PSetVolumeStatus, /* 5 */
79 PCheckServers, /* 10 */
80 PCheckVolNames, /* 11 */
82 PBogus, /* 13 -- used to be quick check time */
84 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
85 PBogus, /* 16 -- used to be testing code */
86 PNoop, /* 17 -- used to be enable group */
87 PNoop, /* 18 -- used to be disable group */
88 PBogus, /* 19 -- used to be list group */
90 PUnlog, /* 21 -- unlog *is* unpag in this system */
91 PGetFID, /* 22 -- get file ID */
92 PBogus, /* 23 -- used to be waitforever */
93 PSetCacheSize, /* 24 */
94 PRemoveCallBack, /* 25 -- flush only the callback */
97 PRemoveMount, /* 28 -- delete mount point */
98 PNewStatMount, /* 29 -- new style mount point stat */
99 PGetFileCell, /* 30 -- get cell name for input file */
100 PGetWSCell, /* 31 -- get cell name for workstation */
101 PMariner, /* 32 - set/get mariner host */
102 PGetUserCell, /* 33 -- get cell name for user */
103 PVenusLogging, /* 34 -- Enable/Disable logging */
104 PGetCellStatus, /* 35 */
105 PSetCellStatus, /* 36 */
106 PFlushVolumeData, /* 37 -- flush all data from a volume */
107 PSetSysName, /* 38 - Set system name */
108 PExportAfs, /* 39 - Export Afs to remote nfs clients */
109 PGetCacheSize, /* 40 - get cache size and usage */
110 PGetVnodeXStatus, /* 41 - get vcache's special status */
111 PSetSPrefs33, /* 42 - Set CM Server preferences... */
112 PGetSPrefs, /* 43 - Get CM Server preferences... */
113 PGag, /* 44 - turn off/on all CM messages */
114 PTwiddleRx, /* 45 - adjust some RX params */
115 PSetSPrefs, /* 46 - Set CM Server preferences... */
116 PStoreBehind, /* 47 - set degree of store behind to be done */
117 PGCPAGs, /* 48 - disable automatic pag gc-ing */
118 PGetInitParams, /* 49 - get initial cm params */
119 PGetCPrefs, /* 50 - get client interface addresses */
120 PSetCPrefs, /* 51 - set client interface addresses */
121 PFlushMount, /* 52 - flush mount symlink data */
122 PRxStatProc, /* 53 - control process RX statistics */
123 PRxStatPeer, /* 54 - control peer RX statistics */
126 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
127 int afs_nobody = NFS_NOBODY;
130 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
132 dst->in = (char *)(unsigned long)src->in;
133 dst->out = (char *)(unsigned long)src->out;
134 dst->in_size = src->in_size;
135 dst->out_size = src->out_size;
139 * If you need to change copyin_afs_ioctl(), you may also need to change
144 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
148 #if defined(AFS_HPUX_64BIT_ENV)
149 struct afs_ioctl32 dst32;
151 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
153 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
155 afs_ioctl32_to_afs_ioctl(&dst32, dst);
158 #endif /* defined(AFS_HPUX_64BIT_ENV) */
160 #if defined(AFS_SUN57_64BIT_ENV)
161 struct afs_ioctl32 dst32;
163 if (get_udatamodel() == DATAMODEL_ILP32) {
164 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
166 afs_ioctl32_to_afs_ioctl(&dst32, dst);
169 #endif /* defined(AFS_SUN57_64BIT_ENV) */
171 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
172 struct afs_ioctl32 dst32;
174 if (!ABI_IS_64BIT(get_current_abi()))
176 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
178 afs_ioctl32_to_afs_ioctl(&dst32, dst);
181 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
183 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
187 HandleIoctl(avc, acom, adata)
188 register struct vcache *avc;
189 register afs_int32 acom;
190 struct afs_ioctl *adata; {
191 register afs_int32 code;
194 AFS_STATCNT(HandleIoctl);
196 switch(acom & 0xff) {
198 avc->states |= CSafeStore;
202 /* case 2 used to be abort store, but this is no longer provided,
203 since it is impossible to implement under normal Unix.
207 /* return the name of the cell this file is open on */
208 register struct cell *tcell;
209 register afs_int32 i;
211 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
213 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
215 if (i > adata->out_size) {
216 /* 0 means we're not interested in the output */
217 if (adata->out_size != 0) code = EFAULT;
221 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
223 afs_PutCell(tcell, READ_LOCK);
229 case 49: /* VIOC_GETINITPARAMS */
230 if (adata->out_size < sizeof(struct cm_initparams)) {
234 AFS_COPYOUT(&cm_initParams, adata->out,
235 sizeof(struct cm_initparams), code);
244 return code; /* so far, none implemented */
249 /* For aix we don't temporarily bypass ioctl(2) but rather do our
250 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
251 * is now called from afs_gn_ioctl.
253 afs_ioctl(tvc, cmd, arg)
258 struct afs_ioctl data;
261 AFS_STATCNT(afs_ioctl);
262 if (((cmd >> 8) & 0xff) == 'V') {
263 /* This is a VICEIOCTL call */
264 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
267 error = HandleIoctl(tvc, cmd, &data);
270 /* No-op call; just return. */
274 #endif /* AFS_AIX_ENV */
276 #if defined(AFS_SGI_ENV)
277 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
283 struct afs_ioctl data;
289 AFS_STATCNT(afs_ioctl);
290 if (((cmd >> 8) & 0xff) == 'V') {
291 /* This is a VICEIOCTL call */
292 error = copyin_afs_ioctl(arg, &data);
295 locked = ISAFS_GLOCK();
298 error = HandleIoctl(tvc, cmd, &data);
303 /* No-op call; just return. */
307 #endif /* AFS_SGI_ENV */
310 /* unlike most calls here, this one uses u.u_error to return error conditions,
311 since this is really an intercepted chapter 2 call, rather than a vnode
314 /* AFS_HPUX102 and up uses VNODE ioctl instead */
315 #ifndef AFS_HPUX102_ENV
316 #if !defined(AFS_SGI_ENV)
318 kioctl(fdes, com, arg, ext)
325 } u_uap, *uap = &u_uap;
329 struct afs_ioctl_sys {
335 afs_xioctl (uap, rvp)
336 struct afs_ioctl_sys *uap;
341 afs_xioctl (p, args, retval)
350 } *uap = (struct a *)args;
351 #else /* AFS_OSF_ENV */
352 #ifdef AFS_LINUX22_ENV
353 struct afs_ioctl_sys {
357 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
358 unsigned int com, unsigned long arg)
360 struct afs_ioctl_sys ua, *uap = &ua;
368 } *uap = (struct a *)u.u_ap;
369 #endif /* AFS_LINUX22_ENV */
370 #endif /* AFS_OSF_ENV */
371 #endif /* AFS_SUN5_ENV */
373 #ifndef AFS_LINUX22_ENV
374 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV)
377 register struct file *fd;
380 register struct vcache *tvc;
381 register int ioctlDone = 0, code = 0;
383 AFS_STATCNT(afs_xioctl);
384 #ifdef AFS_LINUX22_ENV
392 if (setuerror(getf(uap->fd, &fd))) {
398 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
400 #else /* AFS_OSF_ENV */
402 #if defined(AFS_SUN57_ENV)
404 if (!fd) return(EBADF);
405 #elif defined(AFS_SUN54_ENV)
407 if (!fd) return(EBADF);
409 if (code = getf(uap->fd, &fd)) {
421 /* first determine whether this is any sort of vnode */
422 #ifdef AFS_LINUX22_ENV
423 tvc = (struct vcache *)ip;
427 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
429 if (fd->f_type == DTYPE_VNODE) {
431 /* good, this is a vnode; next see if it is an AFS vnode */
432 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
433 tvc = (struct vcache *) fd->f_vnode; /* valid, given a vnode */
435 tvc = (struct vcache *) fd->f_data; /* valid, given a vnode */
437 #endif /* AFS_LINUX22_ENV */
438 if (tvc && IsAfsVnode((struct vnode *)tvc)) {
440 tvc = (struct vcache *) afs_gntovn((struct gnode *) tvc);
441 if (!tvc) { /* shouldn't happen with held gnodes */
446 /* This is an AFS vnode */
447 if (((uap->com >> 8) & 0xff) == 'V') {
448 register struct afs_ioctl *datap;
450 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
451 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
453 osi_FreeSmallSpace(datap);
455 #if defined(AFS_SUN5_ENV)
470 #else /* AFS_OSF_ENV */
474 #ifdef AFS_LINUX22_ENV
483 code = HandleIoctl(tvc, uap->com, datap);
484 osi_FreeSmallSpace(datap);
498 #if defined(AFS_LINUX22_ENV)
508 code = okioctl(fdes, com, arg, ext);
512 okioctl(fdes, com, arg, ext);
514 #if defined(AFS_SUN5_ENV)
515 #if defined(AFS_SUN57_ENV)
517 #elif defined(AFS_SUN54_ENV)
522 code = ioctl(uap, rvp);
525 code = ioctl(p, args, retval);
532 #else /* AFS_OSF_ENV */
533 #ifndef AFS_LINUX22_ENV
550 #ifdef AFS_LINUX22_ENV
553 #if !defined(AFS_OSF_ENV)
556 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
557 return (getuerror() ? -1 : u.u_ioctlrv);
559 return getuerror() ? -1 : 0;
562 #endif /* AFS_LINUX22_ENV */
563 #endif /* AFS_SUN5_ENV */
568 #endif /* AFS_SGI_ENV */
569 #endif /* AFS_HPUX102_ENV */
571 #if defined(AFS_SGI_ENV)
572 /* "pioctl" system call entry point; just pass argument to the parameterized
581 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
585 AFS_STATCNT(afs_pioctl);
587 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
595 #endif /* AFS_SGI_ENV */
598 afs_pioctl(p, args, retval)
608 } *uap = (struct a *) args;
610 AFS_STATCNT(afs_pioctl);
611 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
614 extern struct mount *afs_globalVFS;
615 #else /* AFS_OSF_ENV */
616 extern struct vfs *afs_globalVFS;
619 /* macro to avoid adding any more #ifdef's to pioctl code. */
620 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
621 #define PIOCTL_FREE_CRED() crfree(credp)
623 #define PIOCTL_FREE_CRED()
627 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
629 struct AFS_UCRED *credp;
631 afs_syscall_pioctl(path, com, cmarg, follow)
638 struct afs_ioctl data;
639 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
640 register afs_int32 code = 0;
646 struct ucred *credp = crref(); /* don't free until done! */
648 #ifdef AFS_LINUX22_ENV
649 cred_t *credp = crref(); /* don't free until done! */
652 AFS_STATCNT(afs_syscall_pioctl);
653 if (follow) follow = 1; /* compat. with old venus */
655 if (! _VALIDVICEIOCTL(com)) {
659 #else /* AFS_OSF_ENV */
660 #if defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
669 code = copyin_afs_ioctl(cmarg, &data);
672 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
679 if ((com & 0xff) == PSetClientContext) {
680 #ifdef AFS_LINUX22_ENV
681 return EINVAL; /* Not handling these yet. */
683 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
684 code = HandleClientContext(&data, &com, &foreigncreds, credp);
686 #if defined(AFS_HPUX101_ENV)
687 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
690 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
692 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
693 #endif /* AFS_SGI_ENV */
698 crfree(foreigncreds);
701 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
704 return (setuerror(code), code);
708 #ifndef AFS_LINUX22_ENV
711 * We could have done without temporary setting the u.u_cred below
712 * (foreigncreds could be passed as param the pioctl modules)
713 * but calls such as afs_osi_suser() doesn't allow that since it
714 * references u.u_cred directly. We could, of course, do something
715 * like afs_osi_suser(cred) which, I think, is better since it
716 * generalizes and supports multi cred environments...
720 credp = foreigncreds;
723 tmpcred = crref(); /* XXX */
726 #if defined(AFS_HPUX101_ENV)
727 tmpcred = p_cred(u.u_procp);
728 set_p_cred(u.u_procp, foreigncreds);
731 tmpcred = OSI_GET_CURRENT_CRED();
732 OSI_SET_CURRENT_CRED(foreigncreds);
735 u.u_cred = foreigncreds;
736 #endif /* AFS_SGI64_ENV */
737 #endif /* AFS_HPUX101_ENV */
742 if ((com & 0xff) == 15) {
743 /* special case prefetch so entire pathname eval occurs in helper process.
744 otherwise, the pioctl call is essentially useless */
745 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
746 code = Prefetch(path, &data, follow,
747 foreigncreds ? foreigncreds : credp);
749 #if defined(AFS_HPUX101_ENV)
750 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
753 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
755 code = Prefetch(path, &data, follow, u.u_cred);
756 #endif /* AFS_SGI64_ENV */
757 #endif /* AFS_HPUX101_ENV */
759 #ifndef AFS_LINUX22_ENV
762 crset(tmpcred); /* restore original credentials */
764 #if defined(AFS_HPUX101_ENV)
765 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
769 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
771 u.u_cred = tmpcred; /* restore original credentials */
774 #endif /* AFS_HPUX101_ENV */
775 crfree(foreigncreds);
778 #endif /* AFS_LINUX22_ENV */
780 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
783 return (setuerror(code), code);
789 code = lookupname(path, USR, follow, NULL, &vp,
790 foreigncreds ? foreigncreds : credp);
792 #ifdef AFS_LINUX22_ENV
793 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &dp);
795 vp = (struct vnode *)dp->d_inode;
797 code = gop_lookupname(path, AFS_UIOUSER, follow, (struct vnode **) 0, &vp);
798 #endif /* AFS_LINUX22_ENV */
799 #endif /* AFS_AIX41_ENV */
802 #ifndef AFS_LINUX22_ENV
805 crset(tmpcred); /* restore original credentials */
807 #if defined(AFS_HPUX101_ENV)
808 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
810 #if !defined(AFS_SUN5_ENV)
812 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
814 u.u_cred = tmpcred; /* restore original credentials */
815 #endif /* AFS_SGI64_ENV */
817 #endif /* AFS_HPUX101_ENV */
818 crfree(foreigncreds);
821 #endif /* AFS_LINUX22_ENV */
823 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
826 return(setuerror(code), code);
830 else vp = (struct vnode *) 0;
832 /* now make the call if we were passed no file, or were passed an AFS file */
833 if (!vp || IsAfsVnode(vp)) {
835 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
836 * So, we must test in this part of the code. Also, must arrange to
837 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
838 * we hold gnodes, whose references hold our vcache entries.
841 gp = vp; /* remember for "put" */
842 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
844 else gp = (struct vnode *) 0;
847 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
851 struct ucred *cred1, *cred2;
854 cred1 = cred2 = foreigncreds;
856 cred1 = cred2 = credp;
858 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
859 if (cred1 != cred2) {
860 /* something changed the creds */
865 #if defined(AFS_HPUX101_ENV)
867 struct ucred *cred = p_cred(u.u_procp);
868 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
874 credp = OSI_GET_CURRENT_CRED();
875 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
878 #ifdef AFS_LINUX22_ENV
879 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
881 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
883 #endif /* AFS_SGI_ENV */
884 #endif /* AFS_HPUX101_ENV */
885 #endif /* AFS_AIX41_ENV */
886 #endif /* AFS_SUN5_ENV */
888 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
889 code = EINVAL; /* not in /afs */
896 vp = (struct vnode *) 0;
901 #ifndef AFS_LINUX22_ENV
906 #if defined(AFS_HPUX101_ENV)
907 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
911 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
913 u.u_cred = tmpcred; /* restore original credentials */
914 #endif /* ASF_SGI64_ENV */
916 #endif /* AFS_HPUX101_ENV */
917 crfree(foreigncreds);
920 #endif /* AFS_LINUX22_ENV */
922 #ifdef AFS_LINUX22_ENV
925 AFS_RELE(vp); /* put vnode back */
929 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
934 return (getuerror());
939 afs_HandlePioctl(avc, acom, ablob, afollow, acred)
940 register struct vcache *avc;
942 struct AFS_UCRED **acred;
943 register struct afs_ioctl *ablob;
946 struct vrequest treq;
947 register afs_int32 code;
948 register afs_int32 function;
949 afs_int32 inSize, outSize;
950 char *inData, *outData;
952 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
953 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
954 AFS_STATCNT(HandlePioctl);
955 if (code = afs_InitReq(&treq, *acred)) return code;
956 function = acom & 0xff;
957 if (function >= (sizeof(pioctlSw) / sizeof(char *))) {
958 return EINVAL; /* out of range */
960 inSize = ablob->in_size;
961 if (inSize >= PIGGYSIZE) return E2BIG;
962 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
964 AFS_COPYIN(ablob->in, inData, inSize, code);
968 osi_FreeLargeSpace(inData);
971 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
973 if (function == 3) /* PSetTokens */
974 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
976 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, *acred);
977 osi_FreeLargeSpace(inData);
978 if (code == 0 && ablob->out_size > 0) {
979 if (outSize > ablob->out_size) outSize = ablob->out_size;
980 if (outSize >= PIGGYSIZE) code = E2BIG;
982 AFS_COPYOUT(outData, ablob->out, outSize, code);
984 osi_FreeLargeSpace(outData);
985 return afs_CheckCode(code, &treq, 41);
988 static PGetFID(avc, afun, areq, ain, aout, ainSize, aoutSize)
991 struct vrequest *areq;
994 afs_int32 *aoutSize; /* set this */ {
995 register afs_int32 code;
997 AFS_STATCNT(PGetFID);
998 if (!avc) return EINVAL;
999 bcopy((char *)&avc->fid, aout, sizeof(struct VenusFid));
1000 *aoutSize = sizeof(struct VenusFid);
1004 static PSetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1007 struct vrequest *areq;
1010 afs_int32 *aoutSize; /* set this */ {
1011 register afs_int32 code;
1013 struct AFSOpaque acl;
1014 struct AFSVolSync tsync;
1015 struct AFSFetchStatus OutStatus;
1018 AFS_STATCNT(PSetAcl);
1021 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1024 acl.AFSOpaque_val = ain;
1026 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1028 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1029 #ifdef RX_ENABLE_LOCKS
1031 #endif /* RX_ENABLE_LOCKS */
1032 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1033 &acl, &OutStatus, &tsync);
1034 #ifdef RX_ENABLE_LOCKS
1036 #endif /* RX_ENABLE_LOCKS */
1041 (afs_Analyze(tconn, code, &avc->fid, areq,
1042 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, (struct cell *)0));
1044 /* now we've forgotten all of the access info */
1045 ObtainWriteLock(&afs_xcbhash, 455);
1047 afs_DequeueCallback(avc);
1048 avc->states &= ~(CStatd | CUnique);
1049 ReleaseWriteLock(&afs_xcbhash);
1050 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1051 osi_dnlc_purgedp(avc);
1055 int afs_defaultAsynchrony = 0;
1057 static PStoreBehind(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1060 struct vrequest *areq;
1063 afs_int32 *aoutSize; /* set this */
1064 struct AFS_UCRED *acred;
1067 struct sbstruct *sbr;
1069 sbr = (struct sbstruct *)ain;
1070 if (sbr->sb_default != -1) {
1071 if (afs_osi_suser(acred))
1072 afs_defaultAsynchrony = sbr->sb_default;
1076 if (avc && (sbr->sb_thisfile != -1))
1077 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1078 areq, DONT_CHECK_MODE_BITS))
1079 avc->asynchrony = sbr->sb_thisfile;
1082 *aoutSize = sizeof(struct sbstruct);
1083 sbr = (struct sbstruct *)aout;
1084 sbr->sb_default = afs_defaultAsynchrony;
1086 sbr->sb_thisfile = avc->asynchrony;
1092 static PGCPAGs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1095 struct vrequest *areq;
1098 afs_int32 *aoutSize; /* set this */
1099 struct AFS_UCRED *acred;
1101 if (!afs_osi_suser(acred)) {
1104 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1108 static PGetAcl(avc, afun, areq, ain, aout, ainSize, aoutSize)
1111 struct vrequest *areq;
1114 afs_int32 *aoutSize; /* set this */ {
1115 struct AFSOpaque acl;
1116 struct AFSVolSync tsync;
1117 struct AFSFetchStatus OutStatus;
1123 AFS_STATCNT(PGetAcl);
1124 if (!avc) return EINVAL;
1125 Fid.Volume = avc->fid.Fid.Volume;
1126 Fid.Vnode = avc->fid.Fid.Vnode;
1127 Fid.Unique = avc->fid.Fid.Unique;
1128 if (avc->states & CForeign) {
1130 * For a dfs xlator acl we have a special hack so that the
1131 * xlator will distinguish which type of acl will return. So
1132 * we currently use the top 2-bytes (vals 0-4) to tell which
1133 * type of acl to bring back. Horrible hack but this will
1134 * cause the least number of changes to code size and interfaces.
1136 if (Fid.Vnode & 0xc0000000)
1138 Fid.Vnode |= (ainSize << 30);
1140 acl.AFSOpaque_val = aout;
1142 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1145 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1146 #ifdef RX_ENABLE_LOCKS
1148 #endif /* RX_ENABLE_LOCKS */
1149 code = RXAFS_FetchACL(tconn->id, &Fid,
1150 &acl, &OutStatus, &tsync);
1151 #ifdef RX_ENABLE_LOCKS
1153 #endif /* RX_ENABLE_LOCKS */
1158 (afs_Analyze(tconn, code, &avc->fid, areq,
1159 AFS_STATS_FS_RPCIDX_FETCHACL,
1160 SHARED_LOCK, (struct cell *)0));
1163 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1174 AFS_STATCNT(PBogus);
1178 static PGetFileCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1181 struct vrequest *areq;
1185 afs_int32 *aoutSize; /* set this */ {
1186 register struct cell *tcell;
1188 AFS_STATCNT(PGetFileCell);
1189 if (!avc) return EINVAL;
1190 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1191 if (!tcell) return ESRCH;
1192 strcpy(aout, tcell->cellName);
1193 afs_PutCell(tcell, READ_LOCK);
1194 *aoutSize = strlen(aout) + 1;
1198 static PGetWSCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1201 struct vrequest *areq;
1205 afs_int32 *aoutSize; /* set this */ {
1206 register struct cell *tcell=0, *cellOne=0;
1207 register struct afs_q *cq, *tq;
1209 AFS_STATCNT(PGetWSCell);
1210 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1211 return EIO; /* Inappropriate ioctl for device */
1213 ObtainReadLock(&afs_xcell);
1214 cellOne = (struct cell *) 0;
1216 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1217 tcell = QTOC(cq); tq = QNext(cq);
1218 if (tcell->states & CPrimary) break;
1219 if (tcell->cell == 1) cellOne = tcell;
1222 ReleaseReadLock(&afs_xcell);
1223 if (!tcell) { /* no primary cell, use cell #1 */
1224 if (!cellOne) return ESRCH;
1227 strcpy(aout, tcell->cellName);
1228 *aoutSize = strlen(aout) + 1;
1232 static PGetUserCell(avc, afun, areq, ain, aout, ainSize, aoutSize)
1235 struct vrequest *areq;
1239 afs_int32 *aoutSize; /* set this */ {
1240 register afs_int32 i;
1241 register struct unixuser *tu;
1242 register struct cell *tcell;
1244 AFS_STATCNT(PGetUserCell);
1245 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1246 return EIO; /* Inappropriate ioctl for device */
1248 /* return the cell name of the primary cell for this user */
1249 i = UHash(areq->uid);
1250 ObtainWriteLock(&afs_xuser,224);
1251 for(tu = afs_users[i]; tu; tu = tu->next) {
1252 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1254 ReleaseWriteLock(&afs_xuser);
1259 tcell = afs_GetCell(tu->cell, READ_LOCK);
1260 afs_PutUser(tu, WRITE_LOCK);
1261 if (!tcell) return ESRCH;
1263 strcpy(aout, tcell->cellName);
1264 afs_PutCell(tcell, READ_LOCK);
1265 *aoutSize = strlen(aout)+1; /* 1 for the null */
1269 ReleaseWriteLock(&afs_xuser);
1276 static PSetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1279 struct vrequest *areq;
1283 afs_int32 *aoutSize; /* set this */
1284 struct AFS_UCRED **acred;
1287 register struct unixuser *tu;
1288 struct ClearToken clear;
1289 register struct cell *tcell;
1292 struct vrequest treq;
1293 afs_int32 flag, set_parent_pag = 0;
1295 AFS_STATCNT(PSetTokens);
1296 if (!afs_resourceinit_flag) {
1299 bcopy(ain, (char *)&i, sizeof(afs_int32));
1300 ain += sizeof(afs_int32);
1301 stp = ain; /* remember where the ticket is */
1302 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1304 ain += i; /* skip over ticket */
1305 bcopy(ain, (char *)&i, sizeof(afs_int32));
1306 ain += sizeof(afs_int32);
1307 if (i != sizeof(struct ClearToken)) {
1310 bcopy(ain, (char *)&clear, sizeof(struct ClearToken));
1311 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1312 ain += sizeof(struct ClearToken);
1313 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1314 /* still stuff left? we've got primary flag and cell name. Set these */
1315 bcopy(ain, (char *)&flag, sizeof(afs_int32)); /* primary id flag */
1316 ain += sizeof(afs_int32); /* skip id field */
1317 /* rest is cell name, look it up */
1318 if (flag & 0x8000) { /* XXX Use Constant XXX */
1322 tcell = afs_GetCellByName(ain, READ_LOCK);
1331 /* default to cell 1, primary id */
1332 flag = 1; /* primary id */
1333 i = 1; /* cell number */
1334 tcell = afs_GetCell(1, READ_LOCK);
1335 if (!tcell) goto nocell;
1337 afs_PutCell(tcell, READ_LOCK);
1338 if (set_parent_pag) {
1341 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1343 if (!setpag(acred, -1, &pag, 1)) {
1345 afs_InitReq(&treq, *acred);
1349 /* now we just set the tokens */
1350 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1351 tu->vid = clear.ViceId;
1352 if (tu->stp != (char *) 0) {
1353 afs_osi_Free(tu->stp, tu->stLen);
1355 tu->stp = (char *) afs_osi_Alloc(stLen);
1357 bcopy(stp, tu->stp, stLen);
1360 afs_stats_cmfullperf.authent.TicketUpdates++;
1361 afs_ComputePAGStats();
1362 #endif /* AFS_NOSTATS */
1363 tu->states |= UHasTokens;
1364 tu->states &= ~UTokensBad;
1365 afs_SetPrimary(tu, flag);
1366 tu->tokenTime =osi_Time();
1367 afs_ResetUserConns(tu);
1368 afs_PutUser(tu, WRITE_LOCK);
1383 static PGetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1386 struct vrequest *areq;
1389 afs_int32 *aoutSize; /* set this */ {
1391 char offLineMsg[256];
1393 register struct conn *tc;
1394 register afs_int32 code;
1395 struct VolumeStatus volstat;
1397 char *Name, *OfflineMsg, *MOTD;
1400 AFS_STATCNT(PGetVolumeStatus);
1401 if (!avc) return EINVAL;
1403 OfflineMsg = offLineMsg;
1406 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1408 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1409 #ifdef RX_ENABLE_LOCKS
1411 #endif /* RX_ENABLE_LOCKS */
1412 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1413 &Name, &OfflineMsg, &MOTD);
1414 #ifdef RX_ENABLE_LOCKS
1416 #endif /* RX_ENABLE_LOCKS */
1421 (afs_Analyze(tc, code, &avc->fid, areq,
1422 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1423 SHARED_LOCK, (struct cell *)0));
1425 if (code) return code;
1426 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1428 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1429 cp += sizeof(VolumeStatus);
1430 strcpy(cp, volName);
1431 cp += strlen(volName)+1;
1432 strcpy(cp, offLineMsg);
1433 cp += strlen(offLineMsg)+1;
1435 cp += strlen(motd)+1;
1436 *aoutSize = (cp - aout);
1440 static PSetVolumeStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
1443 struct vrequest *areq;
1446 afs_int32 *aoutSize; /* set this */ {
1448 char offLineMsg[256];
1450 register struct conn *tc;
1451 register afs_int32 code;
1452 struct AFSFetchVolumeStatus volstat;
1453 struct AFSStoreVolumeStatus storeStat;
1454 register struct volume *tvp;
1458 AFS_STATCNT(PSetVolumeStatus);
1459 if (!avc) return EINVAL;
1461 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1463 if (tvp->states & (VRO | VBackup)) {
1464 afs_PutVolume(tvp, READ_LOCK);
1467 afs_PutVolume(tvp, READ_LOCK);
1470 /* Copy the junk out, using cp as a roving pointer. */
1472 bcopy(cp, (char *)&volstat, sizeof(AFSFetchVolumeStatus));
1473 cp += sizeof(AFSFetchVolumeStatus);
1474 strcpy(volName, cp);
1475 cp += strlen(volName)+1;
1476 strcpy(offLineMsg, cp);
1477 cp += strlen(offLineMsg)+1;
1480 if (volstat.MinQuota != -1) {
1481 storeStat.MinQuota = volstat.MinQuota;
1482 storeStat.Mask |= AFS_SETMINQUOTA;
1484 if (volstat.MaxQuota != -1) {
1485 storeStat.MaxQuota = volstat.MaxQuota;
1486 storeStat.Mask |= AFS_SETMAXQUOTA;
1489 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1491 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1492 #ifdef RX_ENABLE_LOCKS
1494 #endif /* RX_ENABLE_LOCKS */
1495 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1496 &storeStat, volName, offLineMsg, motd);
1497 #ifdef RX_ENABLE_LOCKS
1499 #endif /* RX_ENABLE_LOCKS */
1504 (afs_Analyze(tc, code, &avc->fid, areq,
1505 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1506 SHARED_LOCK, (struct cell *)0));
1508 if (code) return code;
1509 /* we are sending parms back to make compat. with prev system. should
1510 change interface later to not ask for current status, just set new status */
1512 bcopy((char *)&volstat, cp, sizeof(VolumeStatus));
1513 cp += sizeof(VolumeStatus);
1514 strcpy(cp, volName);
1515 cp += strlen(volName)+1;
1516 strcpy(cp, offLineMsg);
1517 cp += strlen(offLineMsg)+1;
1519 cp += strlen(motd)+1;
1520 *aoutSize = cp - aout;
1524 static PFlush(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1525 register struct vcache *avc;
1527 struct vrequest *areq;
1530 afs_int32 *aoutSize; /* set this */
1531 struct AFS_UCRED *acred;
1534 AFS_STATCNT(PFlush);
1535 if (!avc) return EINVAL;
1536 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1537 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1539 ObtainWriteLock(&avc->lock,225);
1540 ObtainWriteLock(&afs_xcbhash, 456);
1541 afs_DequeueCallback(avc);
1542 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1543 ReleaseWriteLock(&afs_xcbhash);
1544 /* now find the disk cache entries */
1545 afs_TryToSmush(avc, acred, 1);
1546 osi_dnlc_purgedp(avc);
1547 afs_symhint_inval(avc);
1548 if (avc->linkData && !(avc->states & CCore)) {
1549 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1550 avc->linkData = (char *) 0;
1552 ReleaseWriteLock(&avc->lock);
1553 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1554 afs_BozonUnlock(&avc->pvnLock, avc);
1559 static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
1562 struct vrequest *areq;
1565 afs_int32 *aoutSize; /* set this */ {
1566 register afs_int32 code;
1567 register struct vcache *tvc;
1568 register struct dcache *tdc;
1569 struct VenusFid tfid;
1571 afs_int32 offset, len, hasatsys=0;
1573 AFS_STATCNT(PNewStatMount);
1574 if (!avc) return EINVAL;
1575 code = afs_VerifyVCache(avc, areq);
1576 if (code) return code;
1577 if (vType(avc) != VDIR) {
1580 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
1581 if (!tdc) return ENOENT;
1582 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
1583 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
1588 tfid.Cell = avc->fid.Cell;
1589 tfid.Fid.Volume = avc->fid.Fid.Volume;
1590 afs_PutDCache(tdc); /* we're done with the data */
1591 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1592 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
1594 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
1601 if (vType(tvc) != VLNK) {
1602 afs_PutVCache(tvc, WRITE_LOCK);
1606 ObtainWriteLock(&tvc->lock,226);
1607 code = afs_HandleLink(tvc, areq);
1609 if (tvc->linkData) {
1610 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1613 /* we have the data */
1614 strcpy(aout, tvc->linkData);
1615 *aoutSize = strlen(tvc->linkData)+1;
1620 ReleaseWriteLock(&tvc->lock);
1621 afs_PutVCache(tvc, WRITE_LOCK);
1623 if (hasatsys) osi_FreeLargeSpace(bufp);
1627 static PGetTokens(avc, afun, areq, ain, aout, ainSize, aoutSize)
1630 struct vrequest *areq;
1633 afs_int32 *aoutSize; /* set this */ {
1634 register struct cell *tcell;
1635 register afs_int32 i;
1636 register struct unixuser *tu;
1641 AFS_STATCNT(PGetTokens);
1642 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1643 return EIO; /* Inappropriate ioctl for device */
1645 /* weird interface. If input parameter is present, it is an integer and
1646 we're supposed to return the parm'th tokens for this unix uid.
1647 If not present, we just return tokens for cell 1.
1648 If counter out of bounds, return EDOM.
1649 If no tokens for the particular cell, return ENOTCONN.
1650 Also, if this mysterious parm is present, we return, along with the
1651 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1652 at the end, in that order.
1654 if (newStyle = (ainSize > 0)) {
1655 bcopy(ain, (char *)&iterator, sizeof(afs_int32));
1657 i = UHash(areq->uid);
1658 ObtainReadLock(&afs_xuser);
1659 for(tu = afs_users[i]; tu; tu=tu->next) {
1661 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1662 if (iterator-- == 0) break; /* are we done yet? */
1666 if (tu->uid == areq->uid && tu->cell == 1) break;
1671 * No need to hold a read lock on each user entry
1675 ReleaseReadLock(&afs_xuser);
1680 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1681 tu->states |= (UTokensBad | UNeedsReset);
1682 afs_PutUser(tu, READ_LOCK);
1685 /* use iterator for temp */
1687 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1688 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1689 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1690 cp += sizeof(afs_int32);
1691 bcopy(tu->stp, cp, tu->stLen); /* copy out st */
1693 iterator = sizeof(struct ClearToken);
1694 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1695 cp += sizeof(afs_int32);
1696 bcopy((char *)&tu->ct, cp, sizeof(struct ClearToken));
1697 cp += sizeof(struct ClearToken);
1699 /* put out primary id and cell name, too */
1700 iterator = (tu->states & UPrimary ? 1 : 0);
1701 bcopy((char *)&iterator, cp, sizeof(afs_int32));
1702 cp += sizeof(afs_int32);
1703 tcell = afs_GetCell(tu->cell, READ_LOCK);
1705 strcpy(cp, tcell->cellName);
1706 cp += strlen(tcell->cellName)+1;
1707 afs_PutCell(tcell, READ_LOCK);
1711 *aoutSize = cp - aout;
1712 afs_PutUser(tu, READ_LOCK);
1716 static PUnlog(avc, afun, areq, ain, aout, ainSize, aoutSize)
1719 struct vrequest *areq;
1722 afs_int32 *aoutSize; /* set this */ {
1723 register afs_int32 i;
1724 register struct unixuser *tu;
1726 AFS_STATCNT(PUnlog);
1727 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1728 return EIO; /* Inappropriate ioctl for device */
1730 i = UHash(areq->uid);
1731 ObtainWriteLock(&afs_xuser,227);
1732 for(tu=afs_users[i]; tu; tu=tu->next) {
1733 if (tu->uid == areq->uid) {
1735 tu->states &= ~UHasTokens;
1736 /* security is not having to say you're sorry */
1737 bzero((char *)&tu->ct, sizeof(struct ClearToken));
1739 ReleaseWriteLock(&afs_xuser);
1740 /* We have to drop the lock over the call to afs_ResetUserConns, since
1741 * it obtains the afs_xvcache lock. We could also keep the lock, and
1742 * modify ResetUserConns to take parm saying we obtained the lock
1743 * already, but that is overkill. By keeping the "tu" pointer
1744 * held over the released lock, we guarantee that we won't lose our
1745 * place, and that we'll pass over every user conn that existed when
1746 * we began this call.
1748 afs_ResetUserConns(tu);
1750 ObtainWriteLock(&afs_xuser,228);
1753 ReleaseWriteLock(&afs_xuser);
1757 static PMariner(avc, afun, areq, ain, aout, ainSize, aoutSize)
1760 struct vrequest *areq;
1763 afs_int32 *aoutSize; /* set this */ {
1764 afs_int32 newHostAddr;
1765 afs_int32 oldHostAddr;
1767 AFS_STATCNT(PMariner);
1769 bcopy((char *)&afs_marinerHost, (char *)&oldHostAddr, sizeof(afs_int32));
1771 oldHostAddr = 0xffffffff; /* disabled */
1773 bcopy(ain, (char *)&newHostAddr, sizeof(afs_int32));
1774 if (newHostAddr == 0xffffffff) {
1775 /* disable mariner operations */
1778 else if (newHostAddr) {
1780 afs_marinerHost = newHostAddr;
1782 bcopy((char *)&oldHostAddr, aout, sizeof(afs_int32));
1783 *aoutSize = sizeof(afs_int32);
1787 static PCheckServers(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
1790 struct vrequest *areq;
1793 afs_int32 *aoutSize; /* set this */
1794 struct AFS_UCRED *acred;
1796 register char *cp = 0;
1798 register struct server *ts;
1799 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1801 struct chservinfo *pcheck;
1803 AFS_STATCNT(PCheckServers);
1805 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1806 return EIO; /* Inappropriate ioctl for device */
1808 if (*lp == 0x12345678) { /* For afs3.3 version */
1809 pcheck=(struct chservinfo *)ain;
1810 if (pcheck->tinterval >= 0) {
1812 bcopy((char *)&PROBE_INTERVAL, cp, sizeof(afs_int32));
1813 *aoutSize = sizeof(afs_int32);
1814 if (pcheck->tinterval > 0) {
1815 if (!afs_osi_suser(acred))
1817 PROBE_INTERVAL=pcheck->tinterval;
1823 temp=pcheck->tflags;
1824 cp = pcheck->tbuffer;
1825 } else { /* For pre afs3.3 versions */
1826 bcopy(ain, (char *)&temp, sizeof(afs_int32));
1827 cp = ain+sizeof(afs_int32);
1828 if (ainSize > sizeof(afs_int32))
1833 * 1: fast check, don't contact servers.
1834 * 2: local cell only.
1837 /* have cell name, too */
1838 cellp = afs_GetCellByName(cp, READ_LOCK);
1839 if (!cellp) return ENOENT;
1841 else cellp = (struct cell *) 0;
1842 if (!cellp && (temp & 2)) {
1843 /* use local cell */
1844 cellp = afs_GetCell(1, READ_LOCK);
1846 if (!(temp & 1)) { /* if not fast, call server checker routine */
1847 afs_CheckServers(1, cellp); /* check down servers */
1848 afs_CheckServers(0, cellp); /* check up servers */
1850 /* now return the current down server list */
1852 ObtainReadLock(&afs_xserver);
1853 for(i=0;i<NSERVERS;i++) {
1854 for(ts = afs_servers[i]; ts; ts=ts->next) {
1855 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1856 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1857 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1858 cp += sizeof(afs_int32);
1862 ReleaseReadLock(&afs_xserver);
1863 if (cellp) afs_PutCell(cellp, READ_LOCK);
1864 *aoutSize = cp - aout;
1868 static PCheckVolNames(avc, afun, areq, ain, aout, ainSize, aoutSize)
1871 struct vrequest *areq;
1874 afs_int32 *aoutSize; /* set this */ {
1875 AFS_STATCNT(PCheckVolNames);
1876 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1877 return EIO; /* Inappropriate ioctl for device */
1879 afs_CheckRootVolume();
1880 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1881 AFS_VOLCHECK_EXPIRED |
1883 AFS_VOLCHECK_MTPTS);
1887 static PCheckAuth(avc, afun, areq, ain, aout, ainSize, aoutSize)
1890 struct vrequest *areq;
1893 afs_int32 *aoutSize; /* set this */ {
1897 struct unixuser *tu;
1899 extern afs_rwlock_t afs_xsrvAddr;
1901 AFS_STATCNT(PCheckAuth);
1902 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1903 return EIO; /* Inappropriate ioctl for device */
1906 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1907 if (!tu) retValue = EACCES;
1909 /* we have a user */
1910 ObtainReadLock(&afs_xsrvAddr);
1911 ObtainReadLock(&afs_xconn);
1913 /* any tokens set? */
1914 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1915 /* all connections in cell 1 working? */
1916 for(i=0;i<NSERVERS;i++) {
1917 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1918 for (tc = sa->conns; tc; tc=tc->next) {
1919 if (tc->user == tu && (tu->states & UTokensBad))
1924 ReleaseReadLock(&afs_xsrvAddr);
1925 ReleaseReadLock(&afs_xconn);
1926 afs_PutUser(tu, READ_LOCK);
1928 bcopy((char *)&retValue, aout, sizeof(afs_int32));
1929 *aoutSize = sizeof(afs_int32);
1933 static Prefetch(apath, adata, afollow, acred)
1935 struct afs_ioctl *adata;
1937 struct AFS_UCRED *acred;
1940 register afs_int32 code;
1943 AFS_STATCNT(Prefetch);
1944 if (!apath) return EINVAL;
1945 tp = osi_AllocLargeSpace(1024);
1946 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1948 osi_FreeLargeSpace(tp);
1951 if (afs_BBusy()) { /* do this as late as possible */
1952 osi_FreeLargeSpace(tp);
1953 return EWOULDBLOCK; /* pretty close */
1955 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred, (long)tp, 0L, 0L, 0L);
1959 static PFindVolume(avc, afun, areq, ain, aout, ainSize, aoutSize)
1962 struct vrequest *areq;
1965 afs_int32 *aoutSize; /* set this */ {
1966 register struct volume *tvp;
1967 register struct server *ts;
1968 register afs_int32 i;
1971 AFS_STATCNT(PFindVolume);
1972 if (!avc) return EINVAL;
1973 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1976 for(i=0;i<MAXHOSTS;i++) {
1977 ts = tvp->serverHost[i];
1979 bcopy((char *)&ts->addr->sa_ip, cp, sizeof(afs_int32));
1980 cp += sizeof(afs_int32);
1983 /* still room for terminating NULL, add it on */
1984 ainSize = 0; /* reuse vbl */
1985 bcopy((char *)&ainSize, cp, sizeof(afs_int32));
1986 cp += sizeof(afs_int32);
1988 *aoutSize = cp - aout;
1989 afs_PutVolume(tvp, READ_LOCK);
1995 static PViceAccess(avc, afun, areq, ain, aout, ainSize, aoutSize)
1998 struct vrequest *areq;
2001 afs_int32 *aoutSize; /* set this */ {
2002 register afs_int32 code;
2005 AFS_STATCNT(PViceAccess);
2006 if (!avc) return EINVAL;
2007 code = afs_VerifyVCache(avc, areq);
2008 if (code) return code;
2009 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2010 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2015 static PSetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2018 struct vrequest *areq;
2021 afs_int32 *aoutSize; /* set this */
2022 struct AFS_UCRED *acred;
2027 AFS_STATCNT(PSetCacheSize);
2028 if (!afs_osi_suser(acred))
2030 /* too many things are setup initially in mem cache version */
2031 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2032 bcopy(ain, (char *)&newValue, sizeof(afs_int32));
2033 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2035 extern u_int afs_min_cache;
2036 if (newValue < afs_min_cache)
2037 afs_cacheBlocks = afs_min_cache;
2039 afs_cacheBlocks = newValue;
2041 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2042 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2043 afs_MaybeWakeupTruncateDaemon();
2044 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2045 afs_osi_Wait(1000, 0, 0);
2046 afs_MaybeWakeupTruncateDaemon();
2051 #define MAXGCSTATS 16
2052 static PGetCacheSize(avc, afun, areq, ain, aout, ainSize, aoutSize)
2055 struct vrequest *areq;
2058 afs_int32 *aoutSize; /* set this */ {
2059 afs_int32 results[MAXGCSTATS];
2061 AFS_STATCNT(PGetCacheSize);
2062 bzero((char *)results, sizeof(results));
2063 results[0] = afs_cacheBlocks;
2064 results[1] = afs_blocksUsed;
2065 bcopy((char *)results, aout, sizeof(results));
2066 *aoutSize = sizeof(results);
2070 static PRemoveCallBack(avc, afun, areq, ain, aout, ainSize, aoutSize)
2073 struct vrequest *areq;
2076 afs_int32 *aoutSize; /* set this */ {
2077 register struct conn *tc;
2078 register afs_int32 code;
2079 struct AFSCallBack CallBacks_Array[1];
2080 struct AFSCBFids theFids;
2081 struct AFSCBs theCBs;
2084 AFS_STATCNT(PRemoveCallBack);
2085 if (!avc) return EINVAL;
2086 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2087 ObtainWriteLock(&avc->lock,229);
2088 theFids.AFSCBFids_len = 1;
2089 theCBs.AFSCBs_len = 1;
2090 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2091 theCBs.AFSCBs_val = CallBacks_Array;
2092 CallBacks_Array[0].CallBackType = CB_DROPPED;
2093 if (avc->callback) {
2095 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2097 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2098 #ifdef RX_ENABLE_LOCKS
2100 #endif /* RX_ENABLE_LOCKS */
2101 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2102 #ifdef RX_ENABLE_LOCKS
2104 #endif /* RX_ENABLE_LOCKS */
2107 /* don't set code on failure since we wouldn't use it */
2109 (afs_Analyze(tc, code, &avc->fid, areq,
2110 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2111 SHARED_LOCK, (struct cell *)0));
2113 ObtainWriteLock(&afs_xcbhash, 457);
2114 afs_DequeueCallback(avc);
2116 avc->states &= ~(CStatd | CUnique);
2117 ReleaseWriteLock(&afs_xcbhash);
2118 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2119 osi_dnlc_purgedp(avc);
2121 ReleaseWriteLock(&avc->lock);
2125 static PNewCell(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2128 struct vrequest *areq;
2132 struct AFS_UCRED *acred;
2133 afs_int32 *aoutSize; /* set this */ {
2134 /* create a new cell */
2135 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2136 register struct cell *tcell;
2137 char *newcell=0, *linkedcell=0, *tp= ain;
2138 register afs_int32 code, linkedstate=0, ls;
2139 u_short fsport = 0, vlport = 0;
2142 AFS_STATCNT(PNewCell);
2143 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2144 return EIO; /* Inappropriate ioctl for device */
2146 if (!afs_osi_suser(acred))
2149 bcopy(tp, (char *)&magic, sizeof(afs_int32));
2150 tp += sizeof(afs_int32);
2151 if (magic != 0x12345678)
2154 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2155 * server addresses while the 3.5 fs newcell command passes
2156 * MAXHOSTS. To figure out which is which, check if the cellname
2159 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2160 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2162 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2163 bcopy(tp, (char *)cellHosts, MAXCELLHOSTS * sizeof(afs_int32));
2164 tp += (scount * sizeof(afs_int32));
2166 lp = (afs_int32 *)tp;
2169 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2170 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2171 tp += (3 * sizeof(afs_int32));
2173 if ((ls = *lp) & 1) {
2174 linkedcell = tp + strlen(newcell)+1;
2175 linkedstate |= CLinkedCell;
2178 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2179 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport);
2183 static PListCells(avc, afun, areq, ain, aout, ainSize, aoutSize)
2186 struct vrequest *areq;
2189 afs_int32 *aoutSize; /* set this */ {
2190 afs_int32 whichCell;
2191 register struct cell *tcell=0;
2192 register afs_int32 i;
2193 register char *cp, *tp = ain;
2194 register struct afs_q *cq, *tq;
2196 AFS_STATCNT(PListCells);
2197 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2198 return EIO; /* Inappropriate ioctl for device */
2200 bcopy(tp, (char *)&whichCell, sizeof(afs_int32));
2201 tp += sizeof(afs_int32);
2202 ObtainReadLock(&afs_xcell);
2203 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2204 tcell = QTOC(cq); tq = QNext(cq);
2205 if (whichCell == 0) break;
2206 if (tq == &CellLRU) tcell = 0;
2211 bzero(cp, MAXCELLHOSTS * sizeof(afs_int32));
2212 for(i=0;i<MAXCELLHOSTS;i++) {
2213 if (tcell->cellHosts[i] == 0) break;
2214 bcopy((char *)&tcell->cellHosts[i]->addr->sa_ip, cp, sizeof(afs_int32));
2215 cp += sizeof(afs_int32);
2217 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2218 strcpy(cp, tcell->cellName);
2219 cp += strlen(tcell->cellName)+1;
2220 *aoutSize = cp - aout;
2222 ReleaseReadLock(&afs_xcell);
2223 if (tcell) return 0;
2227 static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize)
2230 struct vrequest *areq;
2234 afs_int32 *aoutSize; /* set this */ {
2235 register afs_int32 code;
2237 afs_int32 offset, len, hasatsys = 0;
2238 register struct conn *tc;
2239 register struct dcache *tdc;
2240 register struct vcache *tvc;
2241 struct AFSFetchStatus OutDirStatus;
2242 struct VenusFid tfid;
2243 struct AFSVolSync tsync;
2247 /* "ain" is the name of the file in this dir to remove */
2249 AFS_STATCNT(PRemoveMount);
2250 if (!avc) return EINVAL;
2251 code = afs_VerifyVCache(avc, areq);
2252 if (code) return code;
2253 if (vType(avc) != VDIR) return ENOTDIR;
2255 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */
2256 if (!tdc) return ENOENT;
2257 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
2258 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
2263 tfid.Cell = avc->fid.Cell;
2264 tfid.Fid.Volume = avc->fid.Fid.Volume;
2265 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2266 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
2268 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0,
2269 (struct vcache*)0/*xxx avc?*/, WRITE_LOCK);
2276 if (vType(tvc) != VLNK) {
2278 afs_PutVCache(tvc, WRITE_LOCK);
2282 ObtainWriteLock(&tvc->lock,230);
2283 code = afs_HandleLink(tvc, areq);
2285 if (tvc->linkData) {
2286 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2291 ReleaseWriteLock(&tvc->lock);
2292 osi_dnlc_purgedp(tvc);
2293 afs_PutVCache(tvc, WRITE_LOCK);
2298 ObtainWriteLock(&avc->lock,231);
2299 osi_dnlc_remove(avc, bufp, tvc);
2301 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2303 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2304 #ifdef RX_ENABLE_LOCKS
2306 #endif /* RX_ENABLE_LOCKS */
2307 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2308 bufp, &OutDirStatus, &tsync);
2309 #ifdef RX_ENABLE_LOCKS
2311 #endif /* RX_ENABLE_LOCKS */
2316 (afs_Analyze(tc, code, &avc->fid, areq,
2317 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2318 SHARED_LOCK, (struct cell *)0));
2321 if (tdc) afs_PutDCache(tdc);
2322 ReleaseWriteLock(&avc->lock);
2326 /* we have the thing in the cache */
2327 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2328 /* we can do it locally */
2329 code = afs_dir_Delete(&tdc->f.inode, bufp);
2331 ZapDCE(tdc); /* surprise error -- invalid value */
2332 DZap(&tdc->f.inode);
2335 afs_PutDCache(tdc); /* drop ref count */
2337 avc->states &= ~CUnique; /* For the dfs xlator */
2338 ReleaseWriteLock(&avc->lock);
2341 if (hasatsys) osi_FreeLargeSpace(bufp);
2345 static PVenusLogging(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2348 struct vrequest *areq;
2352 struct AFS_UCRED *acred;
2353 afs_int32 *aoutSize; /* set this */ {
2354 return EINVAL; /* OBSOLETE */
2357 static PGetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2360 struct vrequest *areq;
2363 afs_int32 *aoutSize; /* set this */ {
2364 register struct cell *tcell;
2367 AFS_STATCNT(PGetCellStatus);
2368 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2369 return EIO; /* Inappropriate ioctl for device */
2371 tcell = afs_GetCellByName(ain, READ_LOCK);
2372 if (!tcell) return ENOENT;
2373 temp = tcell->states;
2374 afs_PutCell(tcell, READ_LOCK);
2375 bcopy((char *)&temp, aout, sizeof(afs_int32));
2376 *aoutSize = sizeof(afs_int32);
2380 static PSetCellStatus(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2383 struct vrequest *areq;
2386 struct AFS_UCRED *acred;
2387 afs_int32 *aoutSize; /* set this */ {
2388 register struct cell *tcell;
2391 if (!afs_osi_suser(acred))
2393 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2394 return EIO; /* Inappropriate ioctl for device */
2396 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2397 if (!tcell) return ENOENT;
2398 bcopy(ain, (char *)&temp, sizeof(afs_int32));
2400 tcell->states |= CNoSUID;
2402 tcell->states &= ~CNoSUID;
2403 afs_PutCell(tcell, WRITE_LOCK);
2407 static PFlushVolumeData(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2410 struct vrequest *areq;
2413 afs_int32 *aoutSize; /* set this */
2414 struct AFS_UCRED *acred;
2416 extern struct volume *afs_volumes[NVOLS];
2417 register afs_int32 i;
2418 register struct dcache *tdc;
2419 register struct vcache *tvc;
2420 register struct volume *tv;
2421 afs_int32 cell, volume;
2423 AFS_STATCNT(PFlushVolumeData);
2426 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2427 return EIO; /* Inappropriate ioctl for device */
2429 volume = avc->fid.Fid.Volume; /* who to zap */
2430 cell = avc->fid.Cell;
2433 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2434 * the vcaches associated with the volume.
2436 ObtainReadLock(&afs_xvcache);
2437 for(i = 0; i < VCSIZE; i++) {
2438 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2439 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2440 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
2441 VN_HOLD((struct vnode *)tvc);
2445 ReleaseReadLock(&afs_xvcache);
2446 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2447 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2449 ObtainWriteLock(&tvc->lock,232);
2451 ObtainWriteLock(&afs_xcbhash, 458);
2452 afs_DequeueCallback(tvc);
2453 tvc->states &= ~(CStatd | CDirty);
2454 ReleaseWriteLock(&afs_xcbhash);
2455 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2456 osi_dnlc_purgedp(tvc);
2457 afs_TryToSmush(tvc, acred, 1);
2458 ReleaseWriteLock(&tvc->lock);
2459 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2460 afs_BozonUnlock(&tvc->pvnLock, tvc);
2462 ObtainReadLock(&afs_xvcache);
2463 /* our tvc ptr is still good until now */
2468 ReleaseReadLock(&afs_xvcache);
2471 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2472 for(i=0;i<afs_cacheFiles;i++) {
2473 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2474 tdc = afs_GetDSlot(i, (struct dcache *) 0);
2475 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2476 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2477 if (! (afs_indexFlags[i] & IFDataMod)) {
2478 /* if the file is modified, but has a ref cnt of only 1, then
2479 someone probably has the file open and is writing into it.
2480 Better to skip flushing such a file, it will be brought back
2481 immediately on the next write anyway.
2483 If we *must* flush, then this code has to be rearranged to call
2484 afs_storeAllSegments() first */
2485 afs_FlushDCache(tdc);
2489 tdc->refCount--; /* bumped by getdslot */
2491 MReleaseWriteLock(&afs_xdcache);
2493 ObtainReadLock(&afs_xvolume);
2494 for (i=0;i<NVOLS;i++) {
2495 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2496 if (tv->volume == volume) {
2497 afs_ResetVolumeInfo(tv);
2502 ReleaseReadLock(&afs_xvolume);
2504 /* probably, a user is doing this, probably, because things are screwed up.
2505 * maybe it's the dnlc's fault? */
2512 static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize)
2515 struct vrequest *areq;
2518 afs_int32 *aoutSize; /* set this */ {
2519 register afs_int32 code;
2520 struct vcxstat stat;
2523 /* AFS_STATCNT(PGetVnodeXStatus); */
2524 if (!avc) return EINVAL;
2525 code = afs_VerifyVCache(avc, areq);
2526 if (code) return code;
2527 if (vType(avc) == VDIR)
2528 mode = PRSFS_LOOKUP;
2531 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2533 stat.fid = avc->fid;
2534 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2535 stat.lock = avc->lock;
2536 stat.parentVnode = avc->parentVnode;
2537 stat.parentUnique = avc->parentUnique;
2538 hset(stat.flushDV, avc->flushDV);
2539 hset(stat.mapDV, avc->mapDV);
2540 stat.truncPos = avc->truncPos;
2541 { /* just grab the first two - won't break anything... */
2542 struct axscache *ac;
2544 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2545 stat.randomUid[i] = ac->uid;
2546 stat.randomAccess[i] = ac->axess;
2549 stat.callback = afs_data_pointer_to_int32(avc->callback);
2550 stat.cbExpires = avc->cbExpires;
2551 stat.anyAccess = avc->anyAccess;
2552 stat.opens = avc->opens;
2553 stat.execsOrWriters = avc->execsOrWriters;
2554 stat.flockCount = avc->flockCount;
2555 stat.mvstat = avc->mvstat;
2556 stat.states = avc->states;
2557 bcopy((char *)&stat, aout, sizeof(struct vcxstat));
2558 *aoutSize = sizeof(struct vcxstat);
2563 /* We require root for local sysname changes, but not for remote */
2564 /* (since we don't really believe remote uids anyway) */
2565 /* outname[] shouldn't really be needed- this is left as an excercise */
2566 /* for the reader. */
2568 static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2571 struct vrequest *areq;
2574 afs_int32 *aoutSize; /* set this */
2575 register struct AFS_UCRED *acred;
2577 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2578 int setsysname, foundname=0;
2579 register struct afs_exporter *exporter;
2580 extern struct unixuser *afs_FindUser();
2581 extern char *afs_sysname;
2582 register struct unixuser *au;
2583 register afs_int32 pag, error;
2587 AFS_STATCNT(PSetSysName);
2588 if (!afs_globalVFS) {
2589 /* Afsd is NOT running; disable it */
2590 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV)
2593 return (setuerror(EINVAL), EINVAL);
2596 bzero(inname, MAXSYSNAME);
2597 bcopy(ain, (char *)&setsysname, sizeof(afs_int32));
2598 ain += sizeof(afs_int32);
2603 bcopy(ain, inname, t+1); /* include terminating null */
2606 if (acred->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2607 pag = PagInCred(acred);
2609 return EINVAL; /* Better than panicing */
2611 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2612 return EINVAL; /* Better than panicing */
2614 if (!(exporter = au->exporter)) {
2615 afs_PutUser(au, READ_LOCK);
2616 return EINVAL; /* Better than panicing */
2618 error = EXP_SYSNAME(exporter, (setsysname? inname : (char *)0), outname);
2620 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2622 afs_PutUser(au, READ_LOCK);
2627 afs_PutUser(au, READ_LOCK);
2629 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2631 strcpy(outname, afs_sysname);
2634 if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */
2636 strcpy(afs_sysname, inname);
2641 bcopy((char *)&foundname, cp, sizeof(afs_int32));
2642 cp += sizeof(afs_int32);
2644 strcpy(cp, outname);
2645 cp += strlen(outname)+1;
2647 *aoutSize = cp - aout;
2652 /* sequential search through the list of touched cells is not a good
2653 * long-term solution here. For small n, though, it should be just
2654 * fine. Should consider special-casing the local cell for large n.
2655 * Likewise for PSetSPrefs.
2657 static void ReSortCells(s,l, vlonly)
2658 int s; /* number of ids in array l[] -- NOT index of last id */
2659 afs_int32 l[]; /* array of cell ids which have volumes that need to be sorted */
2660 int vlonly; /* sort vl servers or file servers?*/
2662 extern struct volume *afs_volumes[NVOLS]; /* volume hash table */
2671 tcell = afs_GetCell(l[k], WRITE_LOCK);
2672 if (!tcell) continue;
2673 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2674 afs_PutCell(tcell, WRITE_LOCK);
2679 ObtainReadLock(&afs_xvolume);
2680 for (i= 0; i< NVOLS; i++) {
2681 for (j=afs_volumes[i];j;j=j->next) {
2683 if (j->cell == l[k]) {
2684 ObtainWriteLock(&j->lock,233);
2685 afs_SortServers(j->serverHost, MAXHOSTS);
2686 ReleaseWriteLock(&j->lock);
2691 ReleaseReadLock(&afs_xvolume);
2696 static int afs_setsprefs(sp, num, vlonly)
2699 unsigned int vlonly;
2702 int i,j,k,matches,touchedSize;
2703 struct server *srvr = NULL;
2704 afs_int32 touched[34];
2708 for (k=0; k < num; sp++, k++) {
2710 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2713 ObtainReadLock(&afs_xserver);
2715 i = SHash(sp->host.s_addr);
2716 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2717 if (sa->sa_ip == sp->host.s_addr) {
2719 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2720 || (sa->sa_portal == AFS_FSPORT);
2721 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2728 if (sa && matches) { /* found one! */
2730 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2732 sa->sa_iprank = sp->rank + afs_randomMod15();
2733 afs_SortOneServer(sa->server);
2736 /* if we don't know yet what cell it's in, this is moot */
2737 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2738 /* is it in our list of touched cells ? */ ;
2739 if (j < 0) { /* no, it's not */
2740 touched[touchedSize++] = srvr->cell->cell;
2741 if (touchedSize >= 32) { /* watch for ovrflow */
2742 ReleaseReadLock(&afs_xserver);
2743 ReSortCells(touchedSize, touched, vlonly);
2745 ObtainReadLock(&afs_xserver);
2751 ReleaseReadLock(&afs_xserver);
2752 /* if we didn't find one, start to create one. */
2753 /* Note that it doesn't have a cell yet... */
2755 afs_uint32 temp = sp->host.s_addr;
2756 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2757 WRITE_LOCK, (afsUUID *)0,0);
2758 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2759 afs_PutServer(srvr, WRITE_LOCK);
2761 } /* for all cited preferences */
2763 ReSortCells(touchedSize, touched, vlonly);
2767 /* Note that this may only be performed by the local root user.
2770 PSetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2773 struct vrequest *areq;
2776 struct AFS_UCRED *acred;
2777 afs_int32 *aoutSize;
2779 struct setspref *ssp;
2780 AFS_STATCNT(PSetSPrefs);
2782 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2783 return EIO; /* Inappropriate ioctl for device */
2785 if (!afs_osi_suser(acred))
2788 if (ainSize < sizeof(struct setspref))
2791 ssp = (struct setspref *)ain;
2792 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2795 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2796 (ssp->flags & DBservers));
2801 PSetSPrefs33(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2804 struct vrequest *areq;
2807 struct AFS_UCRED *acred;
2808 afs_int32 *aoutSize;
2811 AFS_STATCNT(PSetSPrefs);
2812 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2813 return EIO; /* Inappropriate ioctl for device */
2816 if (!afs_osi_suser(acred))
2819 sp = (struct spref *)ain;
2820 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2824 /* some notes on the following code...
2825 * in the hash table of server structs, all servers with the same IP address
2826 * will be on the same overflow chain.
2827 * This could be sped slightly in some circumstances by having it cache the
2828 * immediately previous slot in the hash table and some supporting information
2829 * Only reports file servers now.
2832 PGetSPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
2835 struct vrequest *areq;
2838 afs_int32 *aoutSize;
2840 struct sprefrequest *spin; /* input */
2841 struct sprefinfo *spout; /* output */
2842 struct spref *srvout; /* one output component */
2843 int i,j; /* counters for hash table traversal */
2844 struct server *srvr; /* one of CM's server structs */
2847 int vlonly; /* just return vlservers ? */
2850 AFS_STATCNT(PGetSPrefs);
2851 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2852 return EIO; /* Inappropriate ioctl for device */
2855 if (ainSize < sizeof (struct sprefrequest_33)) {
2859 spin = ((struct sprefrequest *) ain);
2862 if (ainSize > sizeof (struct sprefrequest_33)) {
2863 vlonly = (spin->flags & DBservers);
2867 /* struct sprefinfo includes 1 server struct... that size gets added
2868 * in during the loop that follows.
2870 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2871 spout = (struct sprefinfo *) aout;
2872 spout->next_offset = spin->offset;
2873 spout->num_servers = 0;
2874 srvout = spout->servers;
2876 ObtainReadLock(&afs_xserver);
2877 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2878 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2879 if (spin->offset > (unsigned short)i) {
2880 continue; /* catch up to where we left off */
2882 spout->next_offset++;
2885 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2886 || (sa->sa_portal == AFS_FSPORT);
2888 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2889 /* only report ranks for vl servers */
2893 srvout->host.s_addr = sa->sa_ip;
2894 srvout->rank = sa->sa_iprank;
2895 *aoutSize += sizeof(struct spref);
2896 spout->num_servers++;
2899 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2900 ReleaseReadLock(&afs_xserver); /* no more room! */
2905 ReleaseReadLock(&afs_xserver);
2907 spout->next_offset = 0; /* start over from the beginning next time */
2911 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2912 int afs_NFSRootOnly = 1;
2913 /*static*/ PExportAfs(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
2916 struct vrequest *areq;
2919 afs_int32 *aoutSize; /* set this */
2920 struct AFS_UCRED *acred;
2922 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2923 extern struct afs_exporter *exporter_find();
2924 register struct afs_exporter *exporter;
2926 AFS_STATCNT(PExportAfs);
2927 bcopy(ain, (char *)&handleValue, sizeof(afs_int32));
2928 type = handleValue >> 24;
2933 exporter = exporter_find(type);
2935 export = handleValue & 3;
2936 changestate = handleValue & 0xff;
2937 smounts = (handleValue >> 2) & 3;
2938 pwsync = (handleValue >> 4) & 3;
2939 convmode = (handleValue >> 6) & 3;
2941 changestate = (handleValue >> 16) & 0x1;
2942 convmode = (handleValue >> 16) & 0x2;
2943 pwsync = (handleValue >> 16) & 0x4;
2944 smounts = (handleValue >> 16) & 0x8;
2945 export = handleValue & 0xff;
2948 /* Failed finding desired exporter; */
2952 handleValue = exporter->exp_states;
2953 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2954 *aoutSize = sizeof(afs_int32);
2956 if (!afs_osi_suser(acred))
2957 return EACCES; /* Only superuser can do this */
2961 exporter->exp_states |= EXP_EXPORTED;
2963 exporter->exp_states &= ~EXP_EXPORTED;
2967 exporter->exp_states |= EXP_UNIXMODE;
2969 exporter->exp_states &= ~EXP_UNIXMODE;
2973 exporter->exp_states |= EXP_PWSYNC;
2975 exporter->exp_states &= ~EXP_PWSYNC;
2979 afs_NFSRootOnly = 0;
2980 exporter->exp_states |= EXP_SUBMOUNTS;
2982 afs_NFSRootOnly = 1;
2983 exporter->exp_states &= ~EXP_SUBMOUNTS;
2986 handleValue = exporter->exp_states;
2987 bcopy((char *)&handleValue, aout, sizeof(afs_int32));
2988 *aoutSize = sizeof(afs_int32);
2991 exporter->exp_states |= EXP_EXPORTED;
2993 exporter->exp_states &= ~EXP_EXPORTED;
2995 exporter->exp_states |= EXP_UNIXMODE;
2997 exporter->exp_states &= ~EXP_UNIXMODE;
2999 exporter->exp_states |= EXP_PWSYNC;
3001 exporter->exp_states &= ~EXP_PWSYNC;
3003 afs_NFSRootOnly = 0;
3004 exporter->exp_states |= EXP_SUBMOUNTS;
3006 afs_NFSRootOnly = 1;
3007 exporter->exp_states &= ~EXP_SUBMOUNTS;
3016 PGag(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3019 struct vrequest *areq;
3022 struct AFS_UCRED *acred;
3023 afs_int32 *aoutSize; /* set this */
3025 struct gaginfo *gagflags;
3027 if (!afs_osi_suser(acred))
3030 gagflags = (struct gaginfo *) ain;
3031 afs_showflags = gagflags->showflags;
3038 PTwiddleRx(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3041 struct vrequest *areq;
3044 struct AFS_UCRED *acred;
3045 afs_int32 *aoutSize;
3047 struct rxparams *rxp;
3049 if (!afs_osi_suser(acred))
3052 rxp = (struct rxparams *) ain;
3054 if (rxp->rx_initReceiveWindow)
3055 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3056 if (rxp->rx_maxReceiveWindow)
3057 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3058 if (rxp->rx_initSendWindow)
3059 rx_initSendWindow = rxp->rx_initSendWindow;
3060 if (rxp->rx_maxSendWindow)
3061 rx_maxSendWindow = rxp->rx_maxSendWindow;
3062 if (rxp->rxi_nSendFrags)
3063 rxi_nSendFrags = rxp->rxi_nSendFrags;
3064 if (rxp->rxi_nRecvFrags)
3065 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3066 if (rxp->rxi_OrphanFragSize)
3067 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3068 if (rxp->rx_maxReceiveSize)
3070 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3071 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3073 if (rxp->rx_MyMaxSendSize)
3074 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3079 static int PGetInitParams(avc, afun, areq, ain, aout, ainSize, aoutSize)
3082 struct vrequest *areq;
3086 afs_int32 *aoutSize; /* set this */
3088 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3091 bcopy((char*)&cm_initParams, aout, sizeof(struct cm_initparams));
3092 *aoutSize = sizeof(struct cm_initparams);
3096 #ifdef AFS_SGI65_ENV
3097 /* They took crget() from us, so fake it. */
3098 static cred_t *crget(void)
3101 cr = crdup(get_current_cred());
3102 bzero((char*)cr, sizeof(cred_t));
3103 #if CELL || CELL_PREPARE
3110 * Create new credentials to correspond to a remote user with given
3111 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3112 * provide pioctl (and other) services to foreign clients (i.e. nfs
3113 * clients) by using this call to `become' the client.
3116 #define PIOCTL_HEADER 6
3117 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3120 afs_uint32 hostaddr;
3121 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3122 extern struct afs_exporter *exporter_find();
3123 struct afs_exporter *exporter, *outexporter;
3124 struct AFS_UCRED *newcred;
3125 struct unixuser *au;
3127 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3128 return EINVAL; /* NFS trans not supported for Ultrix */
3130 #if defined(AFS_SGIMP_ENV)
3131 osi_Assert(ISAFS_GLOCK());
3133 AFS_STATCNT(HandleClientContext);
3134 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3135 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3136 return EINVAL; /* Too small to be good */
3138 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3139 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3141 osi_FreeLargeSpace(inData);
3145 /* Extract information for remote user */
3146 hostaddr = *((afs_uint32 *)ain);
3147 ain += sizeof(hostaddr);
3148 uid = *((afs_uint32 *)ain);
3150 g0 = *((afs_uint32 *)ain);
3152 g1 = *((afs_uint32 *)ain);
3154 *com = *((afs_uint32 *)ain);
3155 ain += sizeof(afs_int32);
3156 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3159 * Of course, one must be root for most of these functions, but
3160 * we'll allow (for knfs) you to set things if the pag is 0 and
3161 * you're setting tokens or unlogging.
3164 if (!afs_osi_suser(credp)) {
3166 #ifndef AFS_SGI64_ENV
3167 /* Since SGI's suser() returns explicit failure after the call.. */
3171 /* check for acceptable opcodes for normal folks, which are, so far,
3172 * set tokens and unlog.
3174 if (i != 9 && i != 3 && i != 38 && i != 8) {
3175 osi_FreeLargeSpace(inData);
3180 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3181 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3182 osi_FreeLargeSpace(inData);
3185 * We map uid 0 to nobody to match the mapping that the nfs
3186 * server does and to ensure that the suser() calls in the afs
3187 * code fails for remote client roots.
3189 uid = afs_nobody; /* NFS_NOBODY == -2 */
3192 #ifdef AFS_AIX41_ENV
3195 newcred->cr_gid = RMTUSER_REQ;
3196 newcred->cr_groups[0] = g0;
3197 newcred->cr_groups[1] = g1;
3199 newcred->cr_ngrps = 2;
3201 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3202 newcred->cr_ngroups = 2;
3204 for (i=2; i<NGROUPS; i++)
3205 newcred->cr_groups[i] = NOGROUP;
3208 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3209 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3211 if (!(exporter = exporter_find(exporter_type))) {
3212 /* Exporter wasn't initialized or an invalid exporter type */
3216 if (exporter->exp_states & EXP_PWSYNC) {
3217 if (uid != credp->cr_uid) {
3219 return ENOEXEC; /* XXX Find a better errno XXX */
3222 newcred->cr_uid = uid; /* Only temporary */
3223 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3224 /* The client's pag is the only unique identifier for it */
3225 newcred->cr_uid = pag;
3227 if (!code && *com == PSETPAG) {
3228 /* Special case for 'setpag' */
3229 afs_uint32 pagvalue = genpag();
3231 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3233 * Note that we leave the 'outexporter' struct held so it won't
3236 au->exporter = outexporter;
3237 if (ablob->out_size >= 4) {
3238 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3240 afs_PutUser(au, WRITE_LOCK);
3241 if (code) return code;
3242 return PSETPAG; /* Special return for setpag */
3244 EXP_RELE(outexporter);
3247 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3250 /* get all interface addresses of this client */
3253 PGetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3256 struct vrequest *areq;
3259 afs_int32 *aoutSize;
3261 struct sprefrequest *spin; /* input */
3262 struct sprefinfo *spout; /* output */
3263 struct spref *srvout; /* one output component */
3267 AFS_STATCNT(PGetCPrefs);
3268 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3269 return EIO; /* Inappropriate ioctl for device */
3271 if ( ainSize < sizeof (struct sprefrequest ))
3274 spin = (struct sprefrequest *) ain;
3275 spout = (struct sprefinfo *) aout;
3277 maxNumber = spin->num_servers; /* max addrs this time */
3278 srvout = spout->servers;
3280 ObtainReadLock(&afs_xinterface);
3282 /* copy out the client interface information from the
3283 ** kernel data structure "interface" to the output buffer
3285 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3286 && ( j< maxNumber) ; i++, j++, srvout++)
3287 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3289 spout->num_servers = j;
3290 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3292 if ( i >= afs_cb_interface.numberOfInterfaces )
3293 spout->next_offset = 0; /* start from beginning again */
3295 spout->next_offset = spin->offset + j;
3297 ReleaseReadLock(&afs_xinterface);
3302 PSetCPrefs(avc, afun, areq, ain, aout, ainSize, aoutSize)
3305 struct vrequest *areq;
3308 afs_int32 *aoutSize;
3310 struct setspref *sin;
3313 AFS_STATCNT(PSetCPrefs);
3314 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3315 return EIO; /* Inappropriate ioctl for device */
3317 sin = (struct setspref *)ain;
3319 if ( ainSize < sizeof(struct setspref) )
3321 if ( sin->num_servers < 0 )
3323 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3326 ObtainWriteLock(&afs_xinterface, 412);
3327 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3328 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3329 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3331 ReleaseWriteLock(&afs_xinterface);
3335 static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3338 struct vrequest *areq;
3341 afs_int32 *aoutSize;
3342 struct AFS_UCRED *acred; {
3343 register afs_int32 code;
3344 register struct vcache *tvc;
3345 register struct dcache *tdc;
3346 struct VenusFid tfid;
3348 afs_int32 offset, len, hasatsys=0;
3350 AFS_STATCNT(PFlushMount);
3351 if (!avc) return EINVAL;
3352 code = afs_VerifyVCache(avc, areq);
3353 if (code) return code;
3354 if (vType(avc) != VDIR) {
3357 tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
3358 if (!tdc) return ENOENT;
3359 hasatsys = Check_AtSys(avc, ain, &bufp, areq);
3360 code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid);
3365 tfid.Cell = avc->fid.Cell;
3366 tfid.Fid.Volume = avc->fid.Fid.Volume;
3367 afs_PutDCache(tdc); /* we're done with the data */
3368 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3369 tvc = afs_LookupVCache(&tfid, areq, (afs_int32 *)0, WRITE_LOCK, avc, bufp);
3371 tvc = afs_GetVCache(&tfid, areq, (afs_int32 *)0, (struct vcache*)0,
3378 if (vType(tvc) != VLNK) {
3379 afs_PutVCache(tvc, WRITE_LOCK);
3383 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3384 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3386 ObtainWriteLock(&tvc->lock,645);
3387 ObtainWriteLock(&afs_xcbhash, 646);
3388 afs_DequeueCallback(tvc);
3389 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3390 ReleaseWriteLock(&afs_xcbhash);
3391 /* now find the disk cache entries */
3392 afs_TryToSmush(tvc, acred, 1);
3393 osi_dnlc_purgedp(tvc);
3394 afs_symhint_inval(tvc);
3395 if (tvc->linkData && !(tvc->states & CCore)) {
3396 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3397 tvc->linkData = (char *) 0;
3399 ReleaseWriteLock(&tvc->lock);
3400 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3401 afs_BozonUnlock(&tvc->pvnLock, tvc);
3403 afs_PutVCache(tvc, WRITE_LOCK);
3405 if (hasatsys) osi_FreeLargeSpace(bufp);
3409 static PRxStatProc(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3412 struct vrequest *areq;
3415 afs_int32 *aoutSize;
3416 struct AFS_UCRED *acred;
3421 if (!afs_osi_suser(acred)) {
3425 if (ainSize != sizeof(afs_int32)) {
3429 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3430 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3434 if (flags & AFSCALL_RXSTATS_ENABLE) {
3435 rx_enableProcessRPCStats();
3437 if (flags & AFSCALL_RXSTATS_DISABLE) {
3438 rx_disableProcessRPCStats();
3440 if (flags & AFSCALL_RXSTATS_CLEAR) {
3441 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3449 static PRxStatPeer(avc, afun, areq, ain, aout, ainSize, aoutSize, acred)
3452 struct vrequest *areq;
3455 afs_int32 *aoutSize;
3456 struct AFS_UCRED *acred;
3461 if (!afs_osi_suser(acred)) {
3465 if (ainSize != sizeof(afs_int32)) {
3469 bcopy(ain, (char *)&flags, sizeof(afs_int32));
3470 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3474 if (flags & AFSCALL_RXSTATS_ENABLE) {
3475 rx_enablePeerRPCStats();
3477 if (flags & AFSCALL_RXSTATS_DISABLE) {
3478 rx_disablePeerRPCStats();
3480 if (flags & AFSCALL_RXSTATS_CLEAR) {
3481 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);