2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
15 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "h/syscallargs.h"
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* afs statistics */
22 #include "rx/rx_globals.h"
24 struct VenusFid afs_rootFid;
25 afs_int32 afs_waitForever=0;
26 short afs_waitForeverCount = 0;
27 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
29 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
30 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
31 struct AFS_UCRED **acred)
33 /* Prototypes for pioctl routines */
36 DECL_PIOCTL(PStoreBehind);
41 DECL_PIOCTL(PGetFileCell);
42 DECL_PIOCTL(PGetWSCell);
43 DECL_PIOCTL(PGetUserCell);
44 DECL_PIOCTL(PSetTokens);
45 DECL_PIOCTL(PGetVolumeStatus);
46 DECL_PIOCTL(PSetVolumeStatus);
48 DECL_PIOCTL(PNewStatMount);
49 DECL_PIOCTL(PGetTokens);
51 DECL_PIOCTL(PMariner);
52 DECL_PIOCTL(PCheckServers);
53 DECL_PIOCTL(PCheckVolNames);
54 DECL_PIOCTL(PCheckAuth);
55 DECL_PIOCTL(PFindVolume);
56 DECL_PIOCTL(PViceAccess);
57 DECL_PIOCTL(PSetCacheSize);
58 DECL_PIOCTL(PGetCacheSize);
59 DECL_PIOCTL(PRemoveCallBack);
60 DECL_PIOCTL(PNewCell);
61 DECL_PIOCTL(PNewAlias);
62 DECL_PIOCTL(PListCells);
63 DECL_PIOCTL(PListAliases);
64 DECL_PIOCTL(PRemoveMount);
65 DECL_PIOCTL(PVenusLogging);
66 DECL_PIOCTL(PGetCellStatus);
67 DECL_PIOCTL(PSetCellStatus);
68 DECL_PIOCTL(PFlushVolumeData);
69 DECL_PIOCTL(PGetVnodeXStatus);
70 DECL_PIOCTL(PSetSysName);
71 DECL_PIOCTL(PSetSPrefs);
72 DECL_PIOCTL(PSetSPrefs33);
73 DECL_PIOCTL(PGetSPrefs);
74 DECL_PIOCTL(PExportAfs);
76 DECL_PIOCTL(PTwiddleRx);
77 DECL_PIOCTL(PGetInitParams);
78 DECL_PIOCTL(PGetRxkcrypt);
79 DECL_PIOCTL(PSetRxkcrypt);
80 DECL_PIOCTL(PGetCPrefs);
81 DECL_PIOCTL(PSetCPrefs);
82 DECL_PIOCTL(PFlushMount);
83 DECL_PIOCTL(PRxStatProc);
84 DECL_PIOCTL(PRxStatPeer);
85 DECL_PIOCTL(PPrefetchFromTape);
86 DECL_PIOCTL(PResidencyCmd);
88 /* Prototypes for private routines */
89 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
90 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
91 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
92 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
93 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
94 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
97 static int (*(VpioctlSw[]))() = {
102 PGetVolumeStatus, /* 4 */
103 PSetVolumeStatus, /* 5 */
108 PCheckServers, /* 10 */
109 PCheckVolNames, /* 11 */
111 PBogus, /* 13 -- used to be quick check time */
113 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
114 PBogus, /* 16 -- used to be testing code */
115 PNoop, /* 17 -- used to be enable group */
116 PNoop, /* 18 -- used to be disable group */
117 PBogus, /* 19 -- used to be list group */
118 PViceAccess, /* 20 */
119 PUnlog, /* 21 -- unlog *is* unpag in this system */
120 PGetFID, /* 22 -- get file ID */
121 PBogus, /* 23 -- used to be waitforever */
122 PSetCacheSize, /* 24 */
123 PRemoveCallBack, /* 25 -- flush only the callback */
126 PRemoveMount, /* 28 -- delete mount point */
127 PNewStatMount, /* 29 -- new style mount point stat */
128 PGetFileCell, /* 30 -- get cell name for input file */
129 PGetWSCell, /* 31 -- get cell name for workstation */
130 PMariner, /* 32 - set/get mariner host */
131 PGetUserCell, /* 33 -- get cell name for user */
132 PVenusLogging, /* 34 -- Enable/Disable logging */
133 PGetCellStatus, /* 35 */
134 PSetCellStatus, /* 36 */
135 PFlushVolumeData, /* 37 -- flush all data from a volume */
136 PSetSysName, /* 38 - Set system name */
137 PExportAfs, /* 39 - Export Afs to remote nfs clients */
138 PGetCacheSize, /* 40 - get cache size and usage */
139 PGetVnodeXStatus, /* 41 - get vcache's special status */
140 PSetSPrefs33, /* 42 - Set CM Server preferences... */
141 PGetSPrefs, /* 43 - Get CM Server preferences... */
142 PGag, /* 44 - turn off/on all CM messages */
143 PTwiddleRx, /* 45 - adjust some RX params */
144 PSetSPrefs, /* 46 - Set CM Server preferences... */
145 PStoreBehind, /* 47 - set degree of store behind to be done */
146 PGCPAGs, /* 48 - disable automatic pag gc-ing */
147 PGetInitParams, /* 49 - get initial cm params */
148 PGetCPrefs, /* 50 - get client interface addresses */
149 PSetCPrefs, /* 51 - set client interface addresses */
150 PFlushMount, /* 52 - flush mount symlink data */
151 PRxStatProc, /* 53 - control process RX statistics */
152 PRxStatPeer, /* 54 - control peer RX statistics */
153 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
154 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
155 PBogus, /* 57 -- arla: set file prio */
156 PBogus, /* 58 -- arla: fallback getfh */
157 PBogus, /* 59 -- arla: fallback fhopen */
158 PBogus, /* 60 -- arla: controls xfsdebug */
159 PBogus, /* 61 -- arla: controls arla debug */
160 PBogus, /* 62 -- arla: debug interface */
161 PBogus, /* 63 -- arla: print xfs status */
162 PBogus, /* 64 -- arla: force cache check */
163 PBogus, /* 65 -- arla: break callback */
164 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
165 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
166 PBogus, /* 68 -- arla: fetch stats */
169 static int (*(CpioctlSw[]))() = {
171 PNewAlias, /* 1 -- create new cell alias */
172 PListAliases, /* 2 -- list cell aliases */
175 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
176 int afs_nobody = NFS_NOBODY;
179 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
181 dst->in = (char *)(unsigned long)src->in;
182 dst->out = (char *)(unsigned long)src->out;
183 dst->in_size = src->in_size;
184 dst->out_size = src->out_size;
188 * If you need to change copyin_afs_ioctl(), you may also need to change
193 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
197 #if defined(AFS_HPUX_64BIT_ENV)
198 struct afs_ioctl32 dst32;
200 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
202 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
204 afs_ioctl32_to_afs_ioctl(&dst32, dst);
207 #endif /* defined(AFS_HPUX_64BIT_ENV) */
209 #if defined(AFS_SUN57_64BIT_ENV)
210 struct afs_ioctl32 dst32;
212 if (get_udatamodel() == DATAMODEL_ILP32) {
213 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
215 afs_ioctl32_to_afs_ioctl(&dst32, dst);
218 #endif /* defined(AFS_SUN57_64BIT_ENV) */
220 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
221 struct afs_ioctl32 dst32;
223 if (!ABI_IS_64BIT(get_current_abi()))
225 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
227 afs_ioctl32_to_afs_ioctl(&dst32, dst);
230 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
232 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
233 struct afs_ioctl32 dst32;
235 #ifdef AFS_SPARC64_LINUX24_ENV
236 if (current->thread.flags & SPARC_FLAG_32BIT)
237 #elif AFS_SPARC64_LINUX20_ENV
238 if (current->tss.flags & SPARC_FLAG_32BIT)
240 #error Not done for this linux type
241 #endif /* AFS_SPARC64_LINUX20_ENV */
243 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
245 afs_ioctl32_to_afs_ioctl(&dst32, dst);
248 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
250 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
254 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
256 register afs_int32 code;
259 AFS_STATCNT(HandleIoctl);
261 switch(acom & 0xff) {
263 avc->states |= CSafeStore;
267 /* case 2 used to be abort store, but this is no longer provided,
268 since it is impossible to implement under normal Unix.
272 /* return the name of the cell this file is open on */
273 register struct cell *tcell;
274 register afs_int32 i;
276 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
278 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
280 if (i > adata->out_size) {
281 /* 0 means we're not interested in the output */
282 if (adata->out_size != 0) code = EFAULT;
286 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
288 afs_PutCell(tcell, READ_LOCK);
294 case 49: /* VIOC_GETINITPARAMS */
295 if (adata->out_size < sizeof(struct cm_initparams)) {
299 AFS_COPYOUT(&cm_initParams, adata->out,
300 sizeof(struct cm_initparams), code);
312 return code; /* so far, none implemented */
317 /* For aix we don't temporarily bypass ioctl(2) but rather do our
318 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
319 * is now called from afs_gn_ioctl.
321 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
323 struct afs_ioctl data;
326 AFS_STATCNT(afs_ioctl);
327 if (((cmd >> 8) & 0xff) == 'V') {
328 /* This is a VICEIOCTL call */
329 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
332 error = HandleIoctl(tvc, cmd, &data);
335 /* No-op call; just return. */
339 #endif /* AFS_AIX_ENV */
341 #if defined(AFS_SGI_ENV)
342 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
348 struct afs_ioctl data;
354 AFS_STATCNT(afs_ioctl);
355 if (((cmd >> 8) & 0xff) == 'V') {
356 /* This is a VICEIOCTL call */
357 error = copyin_afs_ioctl(arg, &data);
360 locked = ISAFS_GLOCK();
363 error = HandleIoctl(tvc, cmd, &data);
368 /* No-op call; just return. */
372 #endif /* AFS_SGI_ENV */
375 /* unlike most calls here, this one uses u.u_error to return error conditions,
376 since this is really an intercepted chapter 2 call, rather than a vnode
379 /* AFS_HPUX102 and up uses VNODE ioctl instead */
380 #ifndef AFS_HPUX102_ENV
381 #if !defined(AFS_SGI_ENV)
384 kioctl(fdes, com, arg, ext, arg2, arg3)
387 kioctl(fdes, com, arg, ext)
398 } u_uap, *uap = &u_uap;
400 #if defined(AFS_SUN5_ENV)
402 struct afs_ioctl_sys {
408 afs_xioctl (uap, rvp)
409 struct afs_ioctl_sys *uap;
412 #elif defined(AFS_OSF_ENV)
413 afs_xioctl (p, args, retval)
422 } *uap = (struct a *)args;
423 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
431 afs_xioctl(p, uap, retval)
433 register struct ioctl_args *uap;
436 #elif defined(AFS_LINUX22_ENV)
437 struct afs_ioctl_sys {
441 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
442 unsigned int com, unsigned long arg)
444 struct afs_ioctl_sys ua, *uap = &ua;
446 int afs_xioctl (void)
452 } *uap = (struct a *)u.u_ap;
453 #endif /* AFS_SUN5_ENV */
455 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
457 #elif !defined(AFS_LINUX22_ENV)
458 register struct file *fd;
460 #if defined(AFS_XBSD_ENV)
461 register struct filedesc *fdp;
463 register struct vcache *tvc;
464 register int ioctlDone = 0, code = 0;
466 AFS_STATCNT(afs_xioctl);
467 #if defined(AFS_XBSD_ENV)
469 if ((u_int)uap->fd >= fdp->fd_nfiles ||
470 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
472 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
475 #if defined(AFS_DARWIN_ENV)
476 if ((code=fdgetf(p, uap->fd, &fd)))
479 #ifdef AFS_LINUX22_ENV
492 if (setuerror(getf(uap->fd, &fd))) {
498 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
500 #else /* AFS_OSF_ENV */
502 #if defined(AFS_SUN57_ENV)
504 if (!fd) return(EBADF);
505 #elif defined(AFS_SUN54_ENV)
507 if (!fd) return(EBADF);
509 if (code = getf(uap->fd, &fd)) {
515 if (!fd) return(EBADF);
522 /* first determine whether this is any sort of vnode */
523 #if defined(AFS_LINUX22_ENV)
528 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
530 if (fd->f_type == DTYPE_VNODE) {
532 /* good, this is a vnode; next see if it is an AFS vnode */
533 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
534 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
535 #elif defined(AFS_OBSD_ENV)
536 tvc = IsAfsVnode((struct vnode *) fd->f_data) ?
537 VTOAFS((struct vnode *) fd->f_data) : NULL;
539 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
541 #endif /* AFS_LINUX22_ENV */
542 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
544 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
545 if (!tvc) { /* shouldn't happen with held gnodes */
550 /* This is an AFS vnode */
551 if (((uap->com >> 8) & 0xff) == 'V') {
552 register struct afs_ioctl *datap;
554 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
555 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
557 osi_FreeSmallSpace(datap);
559 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
562 #if defined(AFS_SUN5_ENV)
577 #else /* AFS_OSF_ENV */
581 #ifdef AFS_LINUX22_ENV
591 code = HandleIoctl(tvc, uap->com, datap);
592 osi_FreeSmallSpace(datap);
606 #if defined(AFS_LINUX22_ENV)
617 code = okioctl(fdes, com, arg, ext, arg2, arg3);
619 code = okioctl(fdes, com, arg, ext);
624 okioctl(fdes, com, arg, ext);
625 #elif defined(AFS_SUN5_ENV)
626 #if defined(AFS_SUN57_ENV)
628 #elif defined(AFS_SUN54_ENV)
633 code = ioctl(uap, rvp);
634 #elif defined(AFS_FBSD_ENV)
635 return ioctl(p, uap);
636 #elif defined(AFS_OBSD_ENV)
637 code = sys_ioctl(p, uap, retval);
638 #elif defined(AFS_DARWIN_ENV)
639 return ioctl(p, uap, retval);
640 #elif defined(AFS_OSF_ENV)
641 code = ioctl(p, args, retval);
648 #elif !defined(AFS_LINUX22_ENV)
662 #ifdef AFS_LINUX22_ENV
665 #if defined(KERNEL_HAVE_UERROR)
668 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
669 return (getuerror() ? -1 : u.u_ioctlrv);
671 return getuerror() ? -1 : 0;
674 #endif /* AFS_LINUX22_ENV */
675 #endif /* AFS_SUN5_ENV */
676 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
680 #endif /* AFS_SGI_ENV */
681 #endif /* AFS_HPUX102_ENV */
683 #if defined(AFS_SGI_ENV)
684 /* "pioctl" system call entry point; just pass argument to the parameterized
693 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
697 AFS_STATCNT(afs_pioctl);
699 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
707 #endif /* AFS_SGI_ENV */
710 afs_pioctl(p, args, retval)
720 } *uap = (struct a *) args;
722 AFS_STATCNT(afs_pioctl);
723 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
726 #else /* AFS_OSF_ENV */
727 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
729 afs_pioctl(p, args, retval)
739 } *uap = (struct a *) args;
741 AFS_STATCNT(afs_pioctl);
742 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
745 #else /* AFS_OSF_ENV */
749 /* macro to avoid adding any more #ifdef's to pioctl code. */
750 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
751 #define PIOCTL_FREE_CRED() crfree(credp)
753 #define PIOCTL_FREE_CRED()
758 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
760 struct AFS_UCRED *credp;
762 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
763 afs_syscall_pioctl(path, com, cmarg, follow, credp)
764 struct AFS_UCRED *credp;
766 afs_syscall_pioctl(path, com, cmarg, follow)
774 struct afs_ioctl data;
775 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
776 register afs_int32 code = 0;
782 struct ucred *credp = crref(); /* don't free until done! */
784 #ifdef AFS_LINUX22_ENV
785 cred_t *credp = crref(); /* don't free until done! */
789 AFS_STATCNT(afs_syscall_pioctl);
790 if (follow) follow = 1; /* compat. with old venus */
791 code = copyin_afs_ioctl(cmarg, &data);
794 #if defined(KERNEL_HAVE_UERROR)
799 if ((com & 0xff) == PSetClientContext) {
800 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
801 return EINVAL; /* Not handling these yet. */
802 #elif defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
803 code = HandleClientContext(&data, &com, &foreigncreds, credp);
805 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
809 crfree(foreigncreds);
812 #if defined(KERNEL_HAVE_UERROR)
813 return (setuerror(code), code);
819 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
822 * We could have done without temporary setting the u.u_cred below
823 * (foreigncreds could be passed as param the pioctl modules)
824 * but calls such as afs_osi_suser() doesn't allow that since it
825 * references u.u_cred directly. We could, of course, do something
826 * like afs_osi_suser(cred) which, I think, is better since it
827 * generalizes and supports multi cred environments...
831 credp = foreigncreds;
834 tmpcred = crref(); /* XXX */
837 #if defined(AFS_HPUX101_ENV)
838 tmpcred = p_cred(u.u_procp);
839 set_p_cred(u.u_procp, foreigncreds);
842 tmpcred = OSI_GET_CURRENT_CRED();
843 OSI_SET_CURRENT_CRED(foreigncreds);
846 tmpcred = osi_curcred();
847 osi_curcred() = foreigncreds;
850 u.u_cred = foreigncreds;
851 #endif /* AFS_SGI64_ENV */
852 #endif /* AFS_HPUX101_ENV */
858 if ((com & 0xff) == 15) {
859 /* special case prefetch so entire pathname eval occurs in helper process.
860 otherwise, the pioctl call is essentially useless */
861 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
862 code = Prefetch(path, &data, follow,
863 foreigncreds ? foreigncreds : credp);
865 code = Prefetch(path, &data, follow, osi_curcred());
868 #if defined(KERNEL_HAVE_UERROR)
876 code = lookupname(path, USR, follow, NULL, &vp,
877 foreigncreds ? foreigncreds : credp);
879 #ifdef AFS_LINUX22_ENV
880 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
882 vp = (struct vnode *)dp->d_inode;
884 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
885 #endif /* AFS_LINUX22_ENV */
886 #endif /* AFS_AIX41_ENV */
890 #if defined(KERNEL_HAVE_UERROR)
898 /* now make the call if we were passed no file, or were passed an AFS file */
899 if (!vp || IsAfsVnode(vp)) {
901 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
902 * So, we must test in this part of the code. Also, must arrange to
903 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
904 * we hold gnodes, whose references hold our vcache entries.
907 gp = vp; /* remember for "put" */
908 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
913 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
917 struct ucred *cred1, *cred2;
920 cred1 = cred2 = foreigncreds;
922 cred1 = cred2 = credp;
924 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
925 if (cred1 != cred2) {
926 /* something changed the creds */
931 #if defined(AFS_HPUX101_ENV)
933 struct ucred *cred = p_cred(u.u_procp);
934 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
940 credp = OSI_GET_CURRENT_CRED();
941 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
944 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
945 code = afs_HandlePioctl(vp ? VTOAFS(vp) : NULL, com, &data, follow, &credp);
947 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
949 #endif /* AFS_SGI_ENV */
950 #endif /* AFS_HPUX101_ENV */
951 #endif /* AFS_AIX41_ENV */
952 #endif /* AFS_SUN5_ENV */
954 #if defined(KERNEL_HAVE_UERROR)
957 code = EINVAL; /* not in /afs */
968 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
971 crset(tmpcred); /* restore original credentials */
973 #if defined(AFS_HPUX101_ENV)
974 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
975 #elif defined(AFS_SGI_ENV)
976 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
977 #elif !defined(AFS_SUN5_ENV)
978 osi_curcred() = tmpcred; /* restore original credentials */
979 #endif /* AFS_HPUX101_ENV */
980 crfree(foreigncreds);
983 #endif /* LINUX, DARWIN, FBSD */
985 #ifdef AFS_LINUX22_ENV
988 AFS_RELE(vp); /* put vnode back */
992 #if defined(KERNEL_HAVE_UERROR)
995 return (getuerror());
1002 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1003 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1005 struct vrequest treq;
1006 register afs_int32 code;
1007 register afs_int32 function, device;
1008 afs_int32 inSize, outSize;
1009 char *inData, *outData;
1010 int (*(*pioctlSw))();
1012 struct afs_fakestat_state fakestate;
1014 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1015 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1016 AFS_STATCNT(HandlePioctl);
1017 if ((code = afs_InitReq(&treq, *acred))) return code;
1018 afs_InitFakeStat(&fakestate);
1020 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1022 afs_PutFakeStat(&fakestate);
1026 device = (acom & 0xff00) >> 8;
1028 case 'V': /* Original pioctl's */
1029 pioctlSw = VpioctlSw;
1030 pioctlSwSize = sizeof(VpioctlSw);
1032 case 'C': /* Coordinated/common pioctl's */
1033 pioctlSw = CpioctlSw;
1034 pioctlSwSize = sizeof(CpioctlSw);
1037 afs_PutFakeStat(&fakestate);
1040 function = acom & 0xff;
1041 if (function >= (pioctlSwSize / sizeof(char *))) {
1042 afs_PutFakeStat(&fakestate);
1043 return EINVAL; /* out of range */
1045 inSize = ablob->in_size;
1046 if (inSize >= PIGGYSIZE) return E2BIG;
1047 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1049 AFS_COPYIN(ablob->in, inData, inSize, code);
1050 inData[inSize]='\0';
1054 osi_FreeLargeSpace(inData);
1055 afs_PutFakeStat(&fakestate);
1058 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1060 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1061 osi_FreeLargeSpace(inData);
1062 if (code == 0 && ablob->out_size > 0) {
1063 if (outSize > ablob->out_size) outSize = ablob->out_size;
1064 if (outSize >= PIGGYSIZE) code = E2BIG;
1066 outData[outSize]='\0';
1067 AFS_COPYOUT(outData, ablob->out, outSize, code);
1070 osi_FreeLargeSpace(outData);
1071 afs_PutFakeStat(&fakestate);
1072 return afs_CheckCode(code, &treq, 41);
1075 DECL_PIOCTL(PGetFID)
1077 AFS_STATCNT(PGetFID);
1078 if (!avc) return EINVAL;
1079 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1080 *aoutSize = sizeof(struct VenusFid);
1084 DECL_PIOCTL(PSetAcl)
1086 register afs_int32 code;
1088 struct AFSOpaque acl;
1089 struct AFSVolSync tsync;
1090 struct AFSFetchStatus OutStatus;
1093 AFS_STATCNT(PSetAcl);
1096 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1099 acl.AFSOpaque_val = ain;
1101 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1103 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1105 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1106 &acl, &OutStatus, &tsync);
1112 (afs_Analyze(tconn, code, &avc->fid, areq,
1113 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1115 /* now we've forgotten all of the access info */
1116 ObtainWriteLock(&afs_xcbhash, 455);
1118 afs_DequeueCallback(avc);
1119 avc->states &= ~(CStatd | CUnique);
1120 ReleaseWriteLock(&afs_xcbhash);
1121 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1122 osi_dnlc_purgedp(avc);
1126 int afs_defaultAsynchrony = 0;
1128 DECL_PIOCTL(PStoreBehind)
1131 struct sbstruct *sbr;
1133 sbr = (struct sbstruct *)ain;
1134 if (sbr->sb_default != -1) {
1135 if (afs_osi_suser(*acred))
1136 afs_defaultAsynchrony = sbr->sb_default;
1140 if (avc && (sbr->sb_thisfile != -1)) {
1141 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1142 areq, DONT_CHECK_MODE_BITS))
1143 avc->asynchrony = sbr->sb_thisfile;
1147 *aoutSize = sizeof(struct sbstruct);
1148 sbr = (struct sbstruct *)aout;
1149 sbr->sb_default = afs_defaultAsynchrony;
1151 sbr->sb_thisfile = avc->asynchrony;
1157 DECL_PIOCTL(PGCPAGs)
1159 if (!afs_osi_suser(*acred)) {
1162 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1166 DECL_PIOCTL(PGetAcl)
1168 struct AFSOpaque acl;
1169 struct AFSVolSync tsync;
1170 struct AFSFetchStatus OutStatus;
1176 AFS_STATCNT(PGetAcl);
1177 if (!avc) return EINVAL;
1178 Fid.Volume = avc->fid.Fid.Volume;
1179 Fid.Vnode = avc->fid.Fid.Vnode;
1180 Fid.Unique = avc->fid.Fid.Unique;
1181 if (avc->states & CForeign) {
1183 * For a dfs xlator acl we have a special hack so that the
1184 * xlator will distinguish which type of acl will return. So
1185 * we currently use the top 2-bytes (vals 0-4) to tell which
1186 * type of acl to bring back. Horrible hack but this will
1187 * cause the least number of changes to code size and interfaces.
1189 if (Fid.Vnode & 0xc0000000)
1191 Fid.Vnode |= (ainSize << 30);
1193 acl.AFSOpaque_val = aout;
1195 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1198 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1200 code = RXAFS_FetchACL(tconn->id, &Fid,
1201 &acl, &OutStatus, &tsync);
1207 (afs_Analyze(tconn, code, &avc->fid, areq,
1208 AFS_STATS_FS_RPCIDX_FETCHACL,
1209 SHARED_LOCK, NULL));
1212 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1225 AFS_STATCNT(PBogus);
1229 DECL_PIOCTL(PGetFileCell)
1231 register struct cell *tcell;
1233 AFS_STATCNT(PGetFileCell);
1234 if (!avc) return EINVAL;
1235 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1236 if (!tcell) return ESRCH;
1237 strcpy(aout, tcell->cellName);
1238 afs_PutCell(tcell, READ_LOCK);
1239 *aoutSize = strlen(aout) + 1;
1243 DECL_PIOCTL(PGetWSCell)
1245 struct cell *tcell = NULL;
1247 AFS_STATCNT(PGetWSCell);
1248 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1249 return EIO; /* Inappropriate ioctl for device */
1251 tcell = afs_GetPrimaryCell(READ_LOCK);
1252 if (!tcell) /* no primary cell? */
1254 strcpy(aout, tcell->cellName);
1255 *aoutSize = strlen(aout) + 1;
1256 afs_PutCell(tcell, READ_LOCK);
1260 DECL_PIOCTL(PGetUserCell)
1262 register afs_int32 i;
1263 register struct unixuser *tu;
1264 register struct cell *tcell;
1266 AFS_STATCNT(PGetUserCell);
1267 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1268 return EIO; /* Inappropriate ioctl for device */
1270 /* return the cell name of the primary cell for this user */
1271 i = UHash(areq->uid);
1272 ObtainWriteLock(&afs_xuser,224);
1273 for(tu = afs_users[i]; tu; tu = tu->next) {
1274 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1276 ReleaseWriteLock(&afs_xuser);
1281 tcell = afs_GetCell(tu->cell, READ_LOCK);
1282 afs_PutUser(tu, WRITE_LOCK);
1283 if (!tcell) return ESRCH;
1285 strcpy(aout, tcell->cellName);
1286 afs_PutCell(tcell, READ_LOCK);
1287 *aoutSize = strlen(aout)+1; /* 1 for the null */
1291 ReleaseWriteLock(&afs_xuser);
1298 DECL_PIOCTL(PSetTokens)
1301 register struct unixuser *tu;
1302 struct ClearToken clear;
1303 register struct cell *tcell;
1306 struct vrequest treq;
1307 afs_int32 flag, set_parent_pag = 0;
1309 AFS_STATCNT(PSetTokens);
1310 if (!afs_resourceinit_flag) {
1313 memcpy((char *)&i, ain, sizeof(afs_int32));
1314 ain += sizeof(afs_int32);
1315 stp = ain; /* remember where the ticket is */
1316 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1317 if (i > MAXKTCTICKETLEN) return EINVAL;
1319 ain += i; /* skip over ticket */
1320 memcpy((char *)&i, ain, sizeof(afs_int32));
1321 ain += sizeof(afs_int32);
1322 if (i != sizeof(struct ClearToken)) {
1325 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1326 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1327 ain += sizeof(struct ClearToken);
1328 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1329 /* still stuff left? we've got primary flag and cell name. Set these */
1330 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1331 ain += sizeof(afs_int32); /* skip id field */
1332 /* rest is cell name, look it up */
1333 /* some versions of gcc appear to need != 0 in order to get this right */
1334 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1338 tcell = afs_GetCellByName(ain, READ_LOCK);
1339 if (!tcell) goto nocell;
1342 /* default to primary cell, primary id */
1343 flag = 1; /* primary id */
1344 tcell = afs_GetPrimaryCell(READ_LOCK);
1345 if (!tcell) goto nocell;
1348 afs_PutCell(tcell, READ_LOCK);
1349 if (set_parent_pag) {
1351 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1352 #if defined(AFS_DARWIN_ENV)
1353 struct proc *p = current_proc(); /* XXX */
1355 struct proc *p = curproc; /* XXX */
1357 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1358 p->p_pid, p->p_comm);
1359 if (!setpag(p, acred, -1, &pag, 1)) {
1362 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1364 if (!setpag(acred, -1, &pag, 1)) {
1367 afs_InitReq(&treq, *acred);
1371 /* now we just set the tokens */
1372 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1373 tu->vid = clear.ViceId;
1374 if (tu->stp != NULL) {
1375 afs_osi_Free(tu->stp, tu->stLen);
1377 tu->stp = (char *) afs_osi_Alloc(stLen);
1379 memcpy(tu->stp, stp, stLen);
1382 afs_stats_cmfullperf.authent.TicketUpdates++;
1383 afs_ComputePAGStats();
1384 #endif /* AFS_NOSTATS */
1385 tu->states |= UHasTokens;
1386 tu->states &= ~UTokensBad;
1387 afs_SetPrimary(tu, flag);
1388 tu->tokenTime =osi_Time();
1389 afs_ResetUserConns(tu);
1390 afs_PutUser(tu, WRITE_LOCK);
1405 DECL_PIOCTL(PGetVolumeStatus)
1408 char offLineMsg[256];
1410 register struct conn *tc;
1411 register afs_int32 code;
1412 struct VolumeStatus volstat;
1414 char *Name, *OfflineMsg, *MOTD;
1417 AFS_STATCNT(PGetVolumeStatus);
1418 if (!avc) return EINVAL;
1420 OfflineMsg = offLineMsg;
1423 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1425 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1427 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1428 &Name, &OfflineMsg, &MOTD);
1434 (afs_Analyze(tc, code, &avc->fid, areq,
1435 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1436 SHARED_LOCK, NULL));
1438 if (code) return code;
1439 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1441 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1442 cp += sizeof(VolumeStatus);
1443 strcpy(cp, volName);
1444 cp += strlen(volName)+1;
1445 strcpy(cp, offLineMsg);
1446 cp += strlen(offLineMsg)+1;
1448 cp += strlen(motd)+1;
1449 *aoutSize = (cp - aout);
1453 DECL_PIOCTL(PSetVolumeStatus)
1456 char offLineMsg[256];
1458 register struct conn *tc;
1459 register afs_int32 code;
1460 struct AFSFetchVolumeStatus volstat;
1461 struct AFSStoreVolumeStatus storeStat;
1462 register struct volume *tvp;
1466 AFS_STATCNT(PSetVolumeStatus);
1467 if (!avc) return EINVAL;
1469 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1471 if (tvp->states & (VRO | VBackup)) {
1472 afs_PutVolume(tvp, READ_LOCK);
1475 afs_PutVolume(tvp, READ_LOCK);
1478 /* Copy the junk out, using cp as a roving pointer. */
1480 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1481 cp += sizeof(AFSFetchVolumeStatus);
1482 if (strlen(cp) >= sizeof(volName))
1484 strcpy(volName, cp);
1485 cp += strlen(volName)+1;
1486 if (strlen(cp) >= sizeof(offLineMsg))
1488 strcpy(offLineMsg, cp);
1489 cp += strlen(offLineMsg)+1;
1490 if (strlen(cp) >= sizeof(motd))
1494 if (volstat.MinQuota != -1) {
1495 storeStat.MinQuota = volstat.MinQuota;
1496 storeStat.Mask |= AFS_SETMINQUOTA;
1498 if (volstat.MaxQuota != -1) {
1499 storeStat.MaxQuota = volstat.MaxQuota;
1500 storeStat.Mask |= AFS_SETMAXQUOTA;
1503 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1505 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1507 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1508 &storeStat, volName, offLineMsg, motd);
1514 (afs_Analyze(tc, code, &avc->fid, areq,
1515 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1516 SHARED_LOCK, NULL));
1518 if (code) return code;
1519 /* we are sending parms back to make compat. with prev system. should
1520 change interface later to not ask for current status, just set new status */
1522 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1523 cp += sizeof(VolumeStatus);
1524 strcpy(cp, volName);
1525 cp += strlen(volName)+1;
1526 strcpy(cp, offLineMsg);
1527 cp += strlen(offLineMsg)+1;
1529 cp += strlen(motd)+1;
1530 *aoutSize = cp - aout;
1536 AFS_STATCNT(PFlush);
1537 if (!avc) return EINVAL;
1538 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1539 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1541 ObtainWriteLock(&avc->lock,225);
1542 ObtainWriteLock(&afs_xcbhash, 456);
1543 afs_DequeueCallback(avc);
1544 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1545 ReleaseWriteLock(&afs_xcbhash);
1546 /* now find the disk cache entries */
1547 afs_TryToSmush(avc, *acred, 1);
1548 osi_dnlc_purgedp(avc);
1549 afs_symhint_inval(avc);
1550 if (avc->linkData && !(avc->states & CCore)) {
1551 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1552 avc->linkData = NULL;
1554 ReleaseWriteLock(&avc->lock);
1555 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1556 afs_BozonUnlock(&avc->pvnLock, avc);
1561 DECL_PIOCTL(PNewStatMount)
1563 register afs_int32 code;
1564 register struct vcache *tvc;
1565 register struct dcache *tdc;
1566 struct VenusFid tfid;
1568 struct sysname_info sysState;
1569 afs_size_t offset, len;
1571 AFS_STATCNT(PNewStatMount);
1572 if (!avc) return EINVAL;
1573 code = afs_VerifyVCache(avc, areq);
1574 if (code) return code;
1575 if (vType(avc) != VDIR) {
1578 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1579 if (!tdc) return ENOENT;
1580 Check_AtSys(avc, ain, &sysState, areq);
1581 ObtainReadLock(&tdc->lock);
1583 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1584 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1585 ReleaseReadLock(&tdc->lock);
1586 afs_PutDCache(tdc); /* we're done with the data */
1587 bufp = sysState.name;
1591 tfid.Cell = avc->fid.Cell;
1592 tfid.Fid.Volume = avc->fid.Fid.Volume;
1593 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1594 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1596 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1602 if (tvc->mvstat != 1) {
1607 ObtainWriteLock(&tvc->lock,226);
1608 code = afs_HandleLink(tvc, areq);
1610 if (tvc->linkData) {
1611 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1614 /* we have the data */
1615 strcpy(aout, tvc->linkData);
1616 *aoutSize = strlen(tvc->linkData)+1;
1621 ReleaseWriteLock(&tvc->lock);
1624 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1628 DECL_PIOCTL(PGetTokens)
1630 register struct cell *tcell;
1631 register afs_int32 i;
1632 register struct unixuser *tu;
1637 AFS_STATCNT(PGetTokens);
1638 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1639 return EIO; /* Inappropriate ioctl for device */
1641 /* weird interface. If input parameter is present, it is an integer and
1642 we're supposed to return the parm'th tokens for this unix uid.
1643 If not present, we just return tokens for cell 1.
1644 If counter out of bounds, return EDOM.
1645 If no tokens for the particular cell, return ENOTCONN.
1646 Also, if this mysterious parm is present, we return, along with the
1647 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1648 at the end, in that order.
1650 if ((newStyle = (ainSize > 0))) {
1651 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1653 i = UHash(areq->uid);
1654 ObtainReadLock(&afs_xuser);
1655 for(tu = afs_users[i]; tu; tu=tu->next) {
1657 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1658 if (iterator-- == 0) break; /* are we done yet? */
1662 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1667 * No need to hold a read lock on each user entry
1671 ReleaseReadLock(&afs_xuser);
1676 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1677 tu->states |= (UTokensBad | UNeedsReset);
1678 afs_PutUser(tu, READ_LOCK);
1681 /* use iterator for temp */
1683 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1684 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1685 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1686 cp += sizeof(afs_int32);
1687 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1689 iterator = sizeof(struct ClearToken);
1690 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1691 cp += sizeof(afs_int32);
1692 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1693 cp += sizeof(struct ClearToken);
1695 /* put out primary id and cell name, too */
1696 iterator = (tu->states & UPrimary ? 1 : 0);
1697 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1698 cp += sizeof(afs_int32);
1699 tcell = afs_GetCell(tu->cell, READ_LOCK);
1701 strcpy(cp, tcell->cellName);
1702 cp += strlen(tcell->cellName)+1;
1703 afs_PutCell(tcell, READ_LOCK);
1707 *aoutSize = cp - aout;
1708 afs_PutUser(tu, READ_LOCK);
1714 register afs_int32 i;
1715 register struct unixuser *tu;
1717 AFS_STATCNT(PUnlog);
1718 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1719 return EIO; /* Inappropriate ioctl for device */
1721 i = UHash(areq->uid);
1722 ObtainWriteLock(&afs_xuser,227);
1723 for(tu=afs_users[i]; tu; tu=tu->next) {
1724 if (tu->uid == areq->uid) {
1726 tu->states &= ~UHasTokens;
1727 /* security is not having to say you're sorry */
1728 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1730 ReleaseWriteLock(&afs_xuser);
1731 /* We have to drop the lock over the call to afs_ResetUserConns, since
1732 * it obtains the afs_xvcache lock. We could also keep the lock, and
1733 * modify ResetUserConns to take parm saying we obtained the lock
1734 * already, but that is overkill. By keeping the "tu" pointer
1735 * held over the released lock, we guarantee that we won't lose our
1736 * place, and that we'll pass over every user conn that existed when
1737 * we began this call.
1739 afs_ResetUserConns(tu);
1741 ObtainWriteLock(&afs_xuser,228);
1743 /* set the expire times to 0, causes
1744 * afs_GCUserData to remove this entry
1746 tu->ct.EndTimestamp = 0;
1748 #endif /* UKERNEL */
1751 ReleaseWriteLock(&afs_xuser);
1755 DECL_PIOCTL(PMariner)
1757 afs_int32 newHostAddr;
1758 afs_int32 oldHostAddr;
1760 AFS_STATCNT(PMariner);
1762 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1764 oldHostAddr = 0xffffffff; /* disabled */
1766 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1767 if (newHostAddr == 0xffffffff) {
1768 /* disable mariner operations */
1771 else if (newHostAddr) {
1773 afs_marinerHost = newHostAddr;
1775 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1776 *aoutSize = sizeof(afs_int32);
1780 DECL_PIOCTL(PCheckServers)
1782 register char *cp = 0;
1784 register struct server *ts;
1785 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1787 struct chservinfo *pcheck;
1789 AFS_STATCNT(PCheckServers);
1791 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1792 return EIO; /* Inappropriate ioctl for device */
1794 if (*lp == 0x12345678) { /* For afs3.3 version */
1795 pcheck=(struct chservinfo *)ain;
1796 if (pcheck->tinterval >= 0) {
1798 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1799 *aoutSize = sizeof(afs_int32);
1800 if (pcheck->tinterval > 0) {
1801 if (!afs_osi_suser(*acred))
1803 PROBE_INTERVAL=pcheck->tinterval;
1809 temp=pcheck->tflags;
1810 cp = pcheck->tbuffer;
1811 } else { /* For pre afs3.3 versions */
1812 memcpy((char *)&temp, ain, sizeof(afs_int32));
1813 cp = ain+sizeof(afs_int32);
1814 if (ainSize > sizeof(afs_int32))
1819 * 1: fast check, don't contact servers.
1820 * 2: local cell only.
1823 /* have cell name, too */
1824 cellp = afs_GetCellByName(cp, READ_LOCK);
1825 if (!cellp) return ENOENT;
1828 if (!cellp && (temp & 2)) {
1829 /* use local cell */
1830 cellp = afs_GetPrimaryCell(READ_LOCK);
1832 if (!(temp & 1)) { /* if not fast, call server checker routine */
1833 afs_CheckServers(1, cellp); /* check down servers */
1834 afs_CheckServers(0, cellp); /* check up servers */
1836 /* now return the current down server list */
1838 ObtainReadLock(&afs_xserver);
1839 for(i=0;i<NSERVERS;i++) {
1840 for(ts = afs_servers[i]; ts; ts=ts->next) {
1841 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1842 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1843 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1844 cp += sizeof(afs_int32);
1848 ReleaseReadLock(&afs_xserver);
1849 if (cellp) afs_PutCell(cellp, READ_LOCK);
1850 *aoutSize = cp - aout;
1854 DECL_PIOCTL(PCheckVolNames)
1856 AFS_STATCNT(PCheckVolNames);
1857 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1858 return EIO; /* Inappropriate ioctl for device */
1860 afs_CheckRootVolume();
1861 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1862 AFS_VOLCHECK_EXPIRED |
1864 AFS_VOLCHECK_MTPTS);
1868 DECL_PIOCTL(PCheckAuth)
1873 struct unixuser *tu;
1876 AFS_STATCNT(PCheckAuth);
1877 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1878 return EIO; /* Inappropriate ioctl for device */
1881 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1882 if (!tu) retValue = EACCES;
1884 /* we have a user */
1885 ObtainReadLock(&afs_xsrvAddr);
1886 ObtainReadLock(&afs_xconn);
1888 /* any tokens set? */
1889 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1890 /* all connections in cell 1 working? */
1891 for(i=0;i<NSERVERS;i++) {
1892 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1893 for (tc = sa->conns; tc; tc=tc->next) {
1894 if (tc->user == tu && (tu->states & UTokensBad))
1899 ReleaseReadLock(&afs_xsrvAddr);
1900 ReleaseReadLock(&afs_xconn);
1901 afs_PutUser(tu, READ_LOCK);
1903 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1904 *aoutSize = sizeof(afs_int32);
1908 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1911 register afs_int32 code;
1912 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1918 AFS_STATCNT(Prefetch);
1919 if (!apath) return EINVAL;
1920 tp = osi_AllocLargeSpace(1024);
1921 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1923 osi_FreeLargeSpace(tp);
1926 if (afs_BBusy()) { /* do this as late as possible */
1927 osi_FreeLargeSpace(tp);
1928 return EWOULDBLOCK; /* pretty close */
1930 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1931 (afs_size_t) 0, (afs_size_t) 0, tp);
1935 DECL_PIOCTL(PFindVolume)
1937 register struct volume *tvp;
1938 register struct server *ts;
1939 register afs_int32 i;
1942 AFS_STATCNT(PFindVolume);
1943 if (!avc) return EINVAL;
1944 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1947 for(i=0;i<MAXHOSTS;i++) {
1948 ts = tvp->serverHost[i];
1950 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1951 cp += sizeof(afs_int32);
1954 /* still room for terminating NULL, add it on */
1955 ainSize = 0; /* reuse vbl */
1956 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
1957 cp += sizeof(afs_int32);
1959 *aoutSize = cp - aout;
1960 afs_PutVolume(tvp, READ_LOCK);
1966 DECL_PIOCTL(PViceAccess)
1968 register afs_int32 code;
1971 AFS_STATCNT(PViceAccess);
1972 if (!avc) return EINVAL;
1973 code = afs_VerifyVCache(avc, areq);
1974 if (code) return code;
1975 memcpy((char *)&temp, ain, sizeof(afs_int32));
1976 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
1981 DECL_PIOCTL(PSetCacheSize)
1986 AFS_STATCNT(PSetCacheSize);
1987 if (!afs_osi_suser(*acred))
1989 /* too many things are setup initially in mem cache version */
1990 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
1991 memcpy((char *)&newValue, ain, sizeof(afs_int32));
1992 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
1994 if (newValue < afs_min_cache)
1995 afs_cacheBlocks = afs_min_cache;
1997 afs_cacheBlocks = newValue;
1999 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2000 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2001 afs_MaybeWakeupTruncateDaemon();
2002 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2003 afs_osi_Wait(1000, 0, 0);
2004 afs_MaybeWakeupTruncateDaemon();
2009 #define MAXGCSTATS 16
2010 DECL_PIOCTL(PGetCacheSize)
2012 afs_int32 results[MAXGCSTATS];
2014 AFS_STATCNT(PGetCacheSize);
2015 memset((char *)results, 0, sizeof(results));
2016 results[0] = afs_cacheBlocks;
2017 results[1] = afs_blocksUsed;
2018 memcpy(aout, (char *)results, sizeof(results));
2019 *aoutSize = sizeof(results);
2023 DECL_PIOCTL(PRemoveCallBack)
2025 register struct conn *tc;
2026 register afs_int32 code = 0;
2027 struct AFSCallBack CallBacks_Array[1];
2028 struct AFSCBFids theFids;
2029 struct AFSCBs theCBs;
2032 AFS_STATCNT(PRemoveCallBack);
2033 if (!avc) return EINVAL;
2034 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2035 ObtainWriteLock(&avc->lock,229);
2036 theFids.AFSCBFids_len = 1;
2037 theCBs.AFSCBs_len = 1;
2038 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2039 theCBs.AFSCBs_val = CallBacks_Array;
2040 CallBacks_Array[0].CallBackType = CB_DROPPED;
2041 if (avc->callback) {
2043 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2045 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2047 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2051 /* don't set code on failure since we wouldn't use it */
2053 (afs_Analyze(tc, code, &avc->fid, areq,
2054 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2055 SHARED_LOCK, NULL));
2057 ObtainWriteLock(&afs_xcbhash, 457);
2058 afs_DequeueCallback(avc);
2060 avc->states &= ~(CStatd | CUnique);
2061 ReleaseWriteLock(&afs_xcbhash);
2062 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2063 osi_dnlc_purgedp(avc);
2065 ReleaseWriteLock(&avc->lock);
2069 DECL_PIOCTL(PNewCell)
2071 /* create a new cell */
2072 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2073 char *newcell=0, *linkedcell=0, *tp= ain;
2074 register afs_int32 code, linkedstate=0, ls;
2075 u_short fsport = 0, vlport = 0;
2078 AFS_STATCNT(PNewCell);
2079 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2080 return EIO; /* Inappropriate ioctl for device */
2082 if (!afs_osi_suser(*acred))
2085 memcpy((char *)&magic, tp, sizeof(afs_int32));
2086 tp += sizeof(afs_int32);
2087 if (magic != 0x12345678)
2090 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2091 * server addresses while the 3.5 fs newcell command passes
2092 * MAXHOSTS. To figure out which is which, check if the cellname
2095 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2096 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2098 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2099 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2100 tp += (scount * sizeof(afs_int32));
2102 lp = (afs_int32 *)tp;
2105 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2106 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2107 tp += (3 * sizeof(afs_int32));
2109 if ((ls = *lp) & 1) {
2110 linkedcell = tp + strlen(newcell)+1;
2111 linkedstate |= CLinkedCell;
2114 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2115 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2120 DECL_PIOCTL(PNewAlias)
2122 /* create a new cell alias */
2124 register afs_int32 code;
2125 char *realName, *aliasName;
2127 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2128 return EIO; /* Inappropriate ioctl for device */
2130 if (!afs_osi_suser(*acred))
2134 tp += strlen(aliasName) + 1;
2137 code = afs_NewCellAlias(aliasName, realName);
2142 DECL_PIOCTL(PListCells)
2144 afs_int32 whichCell;
2145 register struct cell *tcell=0;
2146 register afs_int32 i;
2147 register char *cp, *tp = ain;
2149 AFS_STATCNT(PListCells);
2150 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2151 return EIO; /* Inappropriate ioctl for device */
2153 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2154 tp += sizeof(afs_int32);
2155 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2158 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2159 for(i=0;i<MAXCELLHOSTS;i++) {
2160 if (tcell->cellHosts[i] == 0) break;
2161 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2162 cp += sizeof(afs_int32);
2164 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2165 strcpy(cp, tcell->cellName);
2166 cp += strlen(tcell->cellName)+1;
2167 *aoutSize = cp - aout;
2168 afs_PutCell(tcell, READ_LOCK);
2170 if (tcell) return 0;
2174 DECL_PIOCTL(PListAliases)
2176 afs_int32 whichAlias;
2177 register struct cell_alias *tcalias=0;
2178 register char *cp, *tp = ain;
2180 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2181 return EIO; /* Inappropriate ioctl for device */
2182 if (ainSize < sizeof(afs_int32))
2185 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2186 tp += sizeof(afs_int32);
2188 tcalias = afs_GetCellAlias(whichAlias);
2191 strcpy(cp, tcalias->alias);
2192 cp += strlen(tcalias->alias)+1;
2193 strcpy(cp, tcalias->cell);
2194 cp += strlen(tcalias->cell)+1;
2195 *aoutSize = cp - aout;
2196 afs_PutCellAlias(tcalias);
2198 if (tcalias) return 0;
2202 DECL_PIOCTL(PRemoveMount)
2204 register afs_int32 code;
2206 struct sysname_info sysState;
2207 afs_size_t offset, len;
2208 register struct conn *tc;
2209 register struct dcache *tdc;
2210 register struct vcache *tvc;
2211 struct AFSFetchStatus OutDirStatus;
2212 struct VenusFid tfid;
2213 struct AFSVolSync tsync;
2217 /* "ain" is the name of the file in this dir to remove */
2219 AFS_STATCNT(PRemoveMount);
2220 if (!avc) return EINVAL;
2221 code = afs_VerifyVCache(avc, areq);
2222 if (code) return code;
2223 if (vType(avc) != VDIR) return ENOTDIR;
2225 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2226 if (!tdc) return ENOENT;
2227 Check_AtSys(avc, ain, &sysState, areq);
2228 ObtainReadLock(&tdc->lock);
2230 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2231 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2232 ReleaseReadLock(&tdc->lock);
2233 bufp = sysState.name;
2238 tfid.Cell = avc->fid.Cell;
2239 tfid.Fid.Volume = avc->fid.Fid.Volume;
2240 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2241 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2243 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2250 if (tvc->mvstat != 1) {
2256 ObtainWriteLock(&tvc->lock,230);
2257 code = afs_HandleLink(tvc, areq);
2259 if (tvc->linkData) {
2260 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2265 ReleaseWriteLock(&tvc->lock);
2266 osi_dnlc_purgedp(tvc);
2272 ObtainWriteLock(&avc->lock,231);
2273 osi_dnlc_remove(avc, bufp, tvc);
2275 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2277 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2279 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2280 bufp, &OutDirStatus, &tsync);
2286 (afs_Analyze(tc, code, &avc->fid, areq,
2287 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2288 SHARED_LOCK, NULL));
2291 if (tdc) afs_PutDCache(tdc);
2292 ReleaseWriteLock(&avc->lock);
2296 /* we have the thing in the cache */
2297 ObtainWriteLock(&tdc->lock, 661);
2298 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2299 /* we can do it locally */
2300 code = afs_dir_Delete(&tdc->f.inode, bufp);
2302 ZapDCE(tdc); /* surprise error -- invalid value */
2303 DZap(&tdc->f.inode);
2306 ReleaseWriteLock(&tdc->lock);
2307 afs_PutDCache(tdc); /* drop ref count */
2309 avc->states &= ~CUnique; /* For the dfs xlator */
2310 ReleaseWriteLock(&avc->lock);
2313 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2317 DECL_PIOCTL(PVenusLogging)
2319 return EINVAL; /* OBSOLETE */
2322 DECL_PIOCTL(PGetCellStatus)
2324 register struct cell *tcell;
2327 AFS_STATCNT(PGetCellStatus);
2328 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2329 return EIO; /* Inappropriate ioctl for device */
2331 tcell = afs_GetCellByName(ain, READ_LOCK);
2332 if (!tcell) return ENOENT;
2333 temp = tcell->states;
2334 afs_PutCell(tcell, READ_LOCK);
2335 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2336 *aoutSize = sizeof(afs_int32);
2340 DECL_PIOCTL(PSetCellStatus)
2342 register struct cell *tcell;
2345 if (!afs_osi_suser(*acred))
2347 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2348 return EIO; /* Inappropriate ioctl for device */
2350 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2351 if (!tcell) return ENOENT;
2352 memcpy((char *)&temp, ain, sizeof(afs_int32));
2354 tcell->states |= CNoSUID;
2356 tcell->states &= ~CNoSUID;
2357 afs_PutCell(tcell, WRITE_LOCK);
2361 DECL_PIOCTL(PFlushVolumeData)
2363 register afs_int32 i;
2364 register struct dcache *tdc;
2365 register struct vcache *tvc;
2366 register struct volume *tv;
2367 afs_int32 cell, volume;
2369 AFS_STATCNT(PFlushVolumeData);
2372 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2373 return EIO; /* Inappropriate ioctl for device */
2375 volume = avc->fid.Fid.Volume; /* who to zap */
2376 cell = avc->fid.Cell;
2379 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2380 * the vcaches associated with the volume.
2382 ObtainReadLock(&afs_xvcache);
2383 for(i = 0; i < VCSIZE; i++) {
2384 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2385 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2386 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2387 VN_HOLD(AFSTOV(tvc));
2389 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2395 ReleaseReadLock(&afs_xvcache);
2396 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2397 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2399 ObtainWriteLock(&tvc->lock,232);
2401 ObtainWriteLock(&afs_xcbhash, 458);
2402 afs_DequeueCallback(tvc);
2403 tvc->states &= ~(CStatd | CDirty);
2404 ReleaseWriteLock(&afs_xcbhash);
2405 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2406 osi_dnlc_purgedp(tvc);
2407 afs_TryToSmush(tvc, *acred, 1);
2408 ReleaseWriteLock(&tvc->lock);
2409 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2410 afs_BozonUnlock(&tvc->pvnLock, tvc);
2412 ObtainReadLock(&afs_xvcache);
2413 /* our tvc ptr is still good until now */
2418 ReleaseReadLock(&afs_xvcache);
2421 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2422 for(i=0;i<afs_cacheFiles;i++) {
2423 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2424 tdc = afs_GetDSlot(i, NULL);
2425 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2426 ReleaseReadLock(&tdc->tlock);
2427 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2428 if (! (afs_indexFlags[i] & IFDataMod)) {
2429 /* if the file is modified, but has a ref cnt of only 1, then
2430 someone probably has the file open and is writing into it.
2431 Better to skip flushing such a file, it will be brought back
2432 immediately on the next write anyway.
2434 If we *must* flush, then this code has to be rearranged to call
2435 afs_storeAllSegments() first */
2436 afs_FlushDCache(tdc);
2440 ReleaseReadLock(&tdc->tlock);
2442 afs_PutDCache(tdc); /* bumped by getdslot */
2444 MReleaseWriteLock(&afs_xdcache);
2446 ObtainReadLock(&afs_xvolume);
2447 for (i=0;i<NVOLS;i++) {
2448 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2449 if (tv->volume == volume) {
2450 afs_ResetVolumeInfo(tv);
2455 ReleaseReadLock(&afs_xvolume);
2457 /* probably, a user is doing this, probably, because things are screwed up.
2458 * maybe it's the dnlc's fault? */
2465 DECL_PIOCTL(PGetVnodeXStatus)
2467 register afs_int32 code;
2468 struct vcxstat stat;
2471 /* AFS_STATCNT(PGetVnodeXStatus); */
2472 if (!avc) return EINVAL;
2473 code = afs_VerifyVCache(avc, areq);
2474 if (code) return code;
2475 if (vType(avc) == VDIR)
2476 mode = PRSFS_LOOKUP;
2479 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2481 stat.fid = avc->fid;
2482 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2483 stat.lock = avc->lock;
2484 stat.parentVnode = avc->parentVnode;
2485 stat.parentUnique = avc->parentUnique;
2486 hset(stat.flushDV, avc->flushDV);
2487 hset(stat.mapDV, avc->mapDV);
2488 stat.truncPos = avc->truncPos;
2489 { /* just grab the first two - won't break anything... */
2490 struct axscache *ac;
2492 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2493 stat.randomUid[i] = ac->uid;
2494 stat.randomAccess[i] = ac->axess;
2497 stat.callback = afs_data_pointer_to_int32(avc->callback);
2498 stat.cbExpires = avc->cbExpires;
2499 stat.anyAccess = avc->anyAccess;
2500 stat.opens = avc->opens;
2501 stat.execsOrWriters = avc->execsOrWriters;
2502 stat.flockCount = avc->flockCount;
2503 stat.mvstat = avc->mvstat;
2504 stat.states = avc->states;
2505 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2506 *aoutSize = sizeof(struct vcxstat);
2511 /* We require root for local sysname changes, but not for remote */
2512 /* (since we don't really believe remote uids anyway) */
2513 /* outname[] shouldn't really be needed- this is left as an excercise */
2514 /* for the reader. */
2515 DECL_PIOCTL(PSetSysName)
2517 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2518 int setsysname, foundname=0;
2519 register struct afs_exporter *exporter;
2520 register struct unixuser *au;
2521 register afs_int32 pag, error;
2525 AFS_STATCNT(PSetSysName);
2526 if (!afs_globalVFS) {
2527 /* Afsd is NOT running; disable it */
2528 #if defined(KERNEL_HAVE_UERROR)
2529 return (setuerror(EINVAL), EINVAL);
2534 memset(inname, 0, MAXSYSNAME);
2535 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2536 ain += sizeof(afs_int32);
2540 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2542 for(cp = ain,count = 0;count < setsysname;count++) {
2543 /* won't go past end of ain since maxsysname*num < ain length */
2545 if (t >= MAXSYSNAME || t <= 0)
2547 /* check for names that can shoot us in the foot */
2548 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2554 /* inname gets first entry in case we're being a translater */
2556 memcpy(inname, ain, t+1); /* include terminating null */
2559 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2560 pag = PagInCred(*acred);
2562 return EINVAL; /* Better than panicing */
2564 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2565 return EINVAL; /* Better than panicing */
2567 if (!(exporter = au->exporter)) {
2568 afs_PutUser(au, READ_LOCK);
2569 return EINVAL; /* Better than panicing */
2571 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2573 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2575 afs_PutUser(au, READ_LOCK);
2580 afs_PutUser(au, READ_LOCK);
2583 /* Not xlating, so local case */
2584 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2585 if (!setsysname) { /* user just wants the info */
2586 strcpy(outname, afs_sysname);
2587 foundname = afs_sysnamecount;
2588 } else { /* Local guy; only root can change sysname */
2589 if (!afs_osi_suser(*acred))
2592 /* clear @sys entries from the dnlc, once afs_lookup can
2593 do lookups of @sys entries and thinks it can trust them */
2594 /* privs ok, store the entry, ... */
2595 strcpy(afs_sysname, inname);
2596 if (setsysname > 1) { /* ... or list */
2598 for(count=1; count < setsysname;++count) {
2599 if (!afs_sysnamelist[count])
2600 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2602 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2606 afs_sysnamecount = setsysname;
2610 cp = aout; /* not changing so report back the count and ... */
2611 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2612 cp += sizeof(afs_int32);
2614 strcpy(cp, outname); /* ... the entry, ... */
2615 cp += strlen(outname)+1;
2616 for(count=1; count < foundname; ++count) { /* ... or list. */
2617 /* Note: we don't support @sys lists for exporters */
2618 if (!afs_sysnamelist[count])
2619 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2620 t = strlen(afs_sysnamelist[count]);
2621 if (t >= MAXSYSNAME)
2622 osi_Panic("PSetSysName: sysname entry garbled\n");
2623 strcpy(cp, afs_sysnamelist[count]);
2627 *aoutSize = cp - aout;
2632 /* sequential search through the list of touched cells is not a good
2633 * long-term solution here. For small n, though, it should be just
2634 * fine. Should consider special-casing the local cell for large n.
2635 * Likewise for PSetSPrefs.
2637 * s - number of ids in array l[] -- NOT index of last id
2638 * l - array of cell ids which have volumes that need to be sorted
2639 * vlonly - sort vl servers or file servers?
2641 static void *ReSortCells_cb(struct cell *cell, void *arg)
2643 afs_int32 *p = (afs_int32 *) arg;
2644 afs_int32 *l = p + 1;
2647 for (i=0; i<s; i++) {
2648 if (l[i] == cell->cellNum) {
2649 ObtainWriteLock(&cell->lock, 690);
2650 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2651 ReleaseWriteLock(&cell->lock);
2658 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2666 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2668 memcpy(p+1, l, s * sizeof(afs_int32));
2669 afs_TraverseCells(&ReSortCells_cb, p);
2670 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2674 ObtainReadLock(&afs_xvolume);
2675 for (i= 0; i< NVOLS; i++) {
2676 for (j=afs_volumes[i];j;j=j->next) {
2678 if (j->cell == l[k]) {
2679 ObtainWriteLock(&j->lock,233);
2680 afs_SortServers(j->serverHost, MAXHOSTS);
2681 ReleaseWriteLock(&j->lock);
2686 ReleaseReadLock(&afs_xvolume);
2690 static int debugsetsp = 0;
2691 static int afs_setsprefs(sp, num, vlonly)
2694 unsigned int vlonly;
2697 int i,j,k,matches,touchedSize;
2698 struct server *srvr = NULL;
2699 afs_int32 touched[34];
2703 for (k=0; k < num; sp++, k++) {
2705 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2708 ObtainReadLock(&afs_xserver);
2710 i = SHash(sp->host.s_addr);
2711 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2712 if (sa->sa_ip == sp->host.s_addr) {
2714 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2715 || (sa->sa_portal == AFS_FSPORT);
2716 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2723 if (sa && matches) { /* found one! */
2725 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2727 sa->sa_iprank = sp->rank + afs_randomMod15();
2728 afs_SortOneServer(sa->server);
2731 /* if we don't know yet what cell it's in, this is moot */
2732 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2733 /* is it in our list of touched cells ? */ ;
2734 if (j < 0) { /* no, it's not */
2735 touched[touchedSize++] = srvr->cell->cellNum;
2736 if (touchedSize >= 32) { /* watch for ovrflow */
2737 ReleaseReadLock(&afs_xserver);
2738 ReSortCells(touchedSize, touched, vlonly);
2740 ObtainReadLock(&afs_xserver);
2746 ReleaseReadLock(&afs_xserver);
2747 /* if we didn't find one, start to create one. */
2748 /* Note that it doesn't have a cell yet... */
2750 afs_uint32 temp = sp->host.s_addr;
2751 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2752 WRITE_LOCK, (afsUUID *)0,0);
2753 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2754 afs_PutServer(srvr, WRITE_LOCK);
2756 } /* for all cited preferences */
2758 ReSortCells(touchedSize, touched, vlonly);
2762 /* Note that this may only be performed by the local root user.
2764 DECL_PIOCTL(PSetSPrefs)
2766 struct setspref *ssp;
2767 AFS_STATCNT(PSetSPrefs);
2769 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2770 return EIO; /* Inappropriate ioctl for device */
2772 if (!afs_osi_suser(*acred))
2775 if (ainSize < sizeof(struct setspref))
2778 ssp = (struct setspref *)ain;
2779 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2782 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2783 (ssp->flags & DBservers));
2787 DECL_PIOCTL(PSetSPrefs33)
2790 AFS_STATCNT(PSetSPrefs);
2791 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2792 return EIO; /* Inappropriate ioctl for device */
2795 if (!afs_osi_suser(*acred))
2798 sp = (struct spref *)ain;
2799 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2803 /* some notes on the following code...
2804 * in the hash table of server structs, all servers with the same IP address
2805 * will be on the same overflow chain.
2806 * This could be sped slightly in some circumstances by having it cache the
2807 * immediately previous slot in the hash table and some supporting information
2808 * Only reports file servers now.
2810 DECL_PIOCTL(PGetSPrefs)
2812 struct sprefrequest *spin; /* input */
2813 struct sprefinfo *spout; /* output */
2814 struct spref *srvout; /* one output component */
2815 int i,j; /* counters for hash table traversal */
2816 struct server *srvr; /* one of CM's server structs */
2818 int vlonly; /* just return vlservers ? */
2821 AFS_STATCNT(PGetSPrefs);
2822 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2823 return EIO; /* Inappropriate ioctl for device */
2826 if (ainSize < sizeof (struct sprefrequest_33)) {
2830 spin = ((struct sprefrequest *) ain);
2833 if (ainSize > sizeof (struct sprefrequest_33)) {
2834 vlonly = (spin->flags & DBservers);
2838 /* struct sprefinfo includes 1 server struct... that size gets added
2839 * in during the loop that follows.
2841 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2842 spout = (struct sprefinfo *) aout;
2843 spout->next_offset = spin->offset;
2844 spout->num_servers = 0;
2845 srvout = spout->servers;
2847 ObtainReadLock(&afs_xserver);
2848 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2849 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2850 if (spin->offset > (unsigned short)i) {
2851 continue; /* catch up to where we left off */
2853 spout->next_offset++;
2856 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2857 || (sa->sa_portal == AFS_FSPORT);
2859 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2860 /* only report ranks for vl servers */
2864 srvout->host.s_addr = sa->sa_ip;
2865 srvout->rank = sa->sa_iprank;
2866 *aoutSize += sizeof(struct spref);
2867 spout->num_servers++;
2870 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2871 ReleaseReadLock(&afs_xserver); /* no more room! */
2876 ReleaseReadLock(&afs_xserver);
2878 spout->next_offset = 0; /* start over from the beginning next time */
2882 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2883 int afs_NFSRootOnly = 1;
2884 DECL_PIOCTL(PExportAfs)
2886 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2887 register struct afs_exporter *exporter;
2889 AFS_STATCNT(PExportAfs);
2890 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2891 type = handleValue >> 24;
2896 exporter = exporter_find(type);
2898 export = handleValue & 3;
2899 changestate = handleValue & 0xff;
2900 smounts = (handleValue >> 2) & 3;
2901 pwsync = (handleValue >> 4) & 3;
2902 convmode = (handleValue >> 6) & 3;
2904 changestate = (handleValue >> 16) & 0x1;
2905 convmode = (handleValue >> 16) & 0x2;
2906 pwsync = (handleValue >> 16) & 0x4;
2907 smounts = (handleValue >> 16) & 0x8;
2908 export = handleValue & 0xff;
2911 /* Failed finding desired exporter; */
2915 handleValue = exporter->exp_states;
2916 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2917 *aoutSize = sizeof(afs_int32);
2919 if (!afs_osi_suser(*acred))
2920 return EACCES; /* Only superuser can do this */
2924 exporter->exp_states |= EXP_EXPORTED;
2926 exporter->exp_states &= ~EXP_EXPORTED;
2930 exporter->exp_states |= EXP_UNIXMODE;
2932 exporter->exp_states &= ~EXP_UNIXMODE;
2936 exporter->exp_states |= EXP_PWSYNC;
2938 exporter->exp_states &= ~EXP_PWSYNC;
2942 afs_NFSRootOnly = 0;
2943 exporter->exp_states |= EXP_SUBMOUNTS;
2945 afs_NFSRootOnly = 1;
2946 exporter->exp_states &= ~EXP_SUBMOUNTS;
2949 handleValue = exporter->exp_states;
2950 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2951 *aoutSize = sizeof(afs_int32);
2954 exporter->exp_states |= EXP_EXPORTED;
2956 exporter->exp_states &= ~EXP_EXPORTED;
2958 exporter->exp_states |= EXP_UNIXMODE;
2960 exporter->exp_states &= ~EXP_UNIXMODE;
2962 exporter->exp_states |= EXP_PWSYNC;
2964 exporter->exp_states &= ~EXP_PWSYNC;
2966 afs_NFSRootOnly = 0;
2967 exporter->exp_states |= EXP_SUBMOUNTS;
2969 afs_NFSRootOnly = 1;
2970 exporter->exp_states &= ~EXP_SUBMOUNTS;
2980 struct gaginfo *gagflags;
2982 if (!afs_osi_suser(*acred))
2985 gagflags = (struct gaginfo *) ain;
2986 afs_showflags = gagflags->showflags;
2992 DECL_PIOCTL(PTwiddleRx)
2994 struct rxparams *rxp;
2996 if (!afs_osi_suser(*acred))
2999 rxp = (struct rxparams *) ain;
3001 if (rxp->rx_initReceiveWindow)
3002 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3003 if (rxp->rx_maxReceiveWindow)
3004 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3005 if (rxp->rx_initSendWindow)
3006 rx_initSendWindow = rxp->rx_initSendWindow;
3007 if (rxp->rx_maxSendWindow)
3008 rx_maxSendWindow = rxp->rx_maxSendWindow;
3009 if (rxp->rxi_nSendFrags)
3010 rxi_nSendFrags = rxp->rxi_nSendFrags;
3011 if (rxp->rxi_nRecvFrags)
3012 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3013 if (rxp->rxi_OrphanFragSize)
3014 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3015 if (rxp->rx_maxReceiveSize)
3017 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3018 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3020 if (rxp->rx_MyMaxSendSize)
3021 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3026 DECL_PIOCTL(PGetInitParams)
3028 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3031 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3032 *aoutSize = sizeof(struct cm_initparams);
3036 #ifdef AFS_SGI65_ENV
3037 /* They took crget() from us, so fake it. */
3038 static cred_t *crget(void)
3041 cr = crdup(get_current_cred());
3042 memset((char*)cr, 0, sizeof(cred_t));
3043 #if CELL || CELL_PREPARE
3050 DECL_PIOCTL(PGetRxkcrypt)
3052 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3053 *aoutSize=sizeof(afs_int32);
3057 DECL_PIOCTL(PSetRxkcrypt)
3061 if (!afs_osi_suser(*acred))
3063 if (ainSize != sizeof(afs_int32) || ain == NULL)
3065 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3066 /* if new mappings added later this will need to be changed */
3067 if (tmpval != 0 && tmpval != 1)
3074 * Create new credentials to correspond to a remote user with given
3075 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3076 * provide pioctl (and other) services to foreign clients (i.e. nfs
3077 * clients) by using this call to `become' the client.
3080 #define PIOCTL_HEADER 6
3081 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3083 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3084 return EINVAL; /* NFS trans not supported for Ultrix */
3087 afs_uint32 hostaddr;
3088 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3089 struct afs_exporter *exporter, *outexporter;
3090 struct AFS_UCRED *newcred;
3091 struct unixuser *au;
3093 #if defined(AFS_SGIMP_ENV)
3094 osi_Assert(ISAFS_GLOCK());
3096 AFS_STATCNT(HandleClientContext);
3097 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3098 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3099 return EINVAL; /* Too small to be good */
3101 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3102 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3104 osi_FreeLargeSpace(inData);
3108 /* Extract information for remote user */
3109 hostaddr = *((afs_uint32 *)ain);
3110 ain += sizeof(hostaddr);
3111 uid = *((afs_uint32 *)ain);
3113 g0 = *((afs_uint32 *)ain);
3115 g1 = *((afs_uint32 *)ain);
3117 *com = *((afs_uint32 *)ain);
3118 ain += sizeof(afs_int32);
3119 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3122 * Of course, one must be root for most of these functions, but
3123 * we'll allow (for knfs) you to set things if the pag is 0 and
3124 * you're setting tokens or unlogging.
3127 if (!afs_osi_suser(credp)) {
3129 #ifndef AFS_SGI64_ENV
3130 /* Since SGI's suser() returns explicit failure after the call.. */
3134 /* check for acceptable opcodes for normal folks, which are, so far,
3135 * set tokens and unlog.
3137 if (i != 9 && i != 3 && i != 38 && i != 8) {
3138 osi_FreeLargeSpace(inData);
3143 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3144 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3145 osi_FreeLargeSpace(inData);
3148 * We map uid 0 to nobody to match the mapping that the nfs
3149 * server does and to ensure that the suser() calls in the afs
3150 * code fails for remote client roots.
3152 uid = afs_nobody; /* NFS_NOBODY == -2 */
3155 #ifdef AFS_AIX41_ENV
3158 newcred->cr_gid = RMTUSER_REQ;
3159 #ifdef AFS_AIX51_ENV
3160 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3161 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3163 newcred->cr_groups[0] = g0;
3164 newcred->cr_groups[1] = g1;
3167 newcred->cr_ngrps = 2;
3169 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3170 newcred->cr_ngroups = 2;
3172 for (i=2; i<NGROUPS; i++)
3173 newcred->cr_groups[i] = NOGROUP;
3176 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3177 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3179 if (!(exporter = exporter_find(exporter_type))) {
3180 /* Exporter wasn't initialized or an invalid exporter type */
3184 if (exporter->exp_states & EXP_PWSYNC) {
3185 if (uid != credp->cr_uid) {
3187 return ENOEXEC; /* XXX Find a better errno XXX */
3190 newcred->cr_uid = uid; /* Only temporary */
3191 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3192 /* The client's pag is the only unique identifier for it */
3193 newcred->cr_uid = pag;
3195 if (!code && *com == PSETPAG) {
3196 /* Special case for 'setpag' */
3197 afs_uint32 pagvalue = genpag();
3199 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3201 * Note that we leave the 'outexporter' struct held so it won't
3204 au->exporter = outexporter;
3205 if (ablob->out_size >= 4) {
3206 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3208 afs_PutUser(au, WRITE_LOCK);
3209 if (code) return code;
3210 return PSETPAG; /* Special return for setpag */
3212 EXP_RELE(outexporter);
3215 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3218 /* get all interface addresses of this client */
3220 DECL_PIOCTL(PGetCPrefs)
3222 struct sprefrequest *spin; /* input */
3223 struct sprefinfo *spout; /* output */
3224 struct spref *srvout; /* one output component */
3228 AFS_STATCNT(PGetCPrefs);
3229 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3230 return EIO; /* Inappropriate ioctl for device */
3232 if ( ainSize < sizeof (struct sprefrequest ))
3235 spin = (struct sprefrequest *) ain;
3236 spout = (struct sprefinfo *) aout;
3238 maxNumber = spin->num_servers; /* max addrs this time */
3239 srvout = spout->servers;
3241 ObtainReadLock(&afs_xinterface);
3243 /* copy out the client interface information from the
3244 ** kernel data structure "interface" to the output buffer
3246 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3247 && ( j< maxNumber) ; i++, j++, srvout++)
3248 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3250 spout->num_servers = j;
3251 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3253 if ( i >= afs_cb_interface.numberOfInterfaces )
3254 spout->next_offset = 0; /* start from beginning again */
3256 spout->next_offset = spin->offset + j;
3258 ReleaseReadLock(&afs_xinterface);
3262 DECL_PIOCTL(PSetCPrefs)
3264 struct setspref *sin;
3267 AFS_STATCNT(PSetCPrefs);
3268 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3269 return EIO; /* Inappropriate ioctl for device */
3271 sin = (struct setspref *)ain;
3273 if ( ainSize < sizeof(struct setspref) )
3275 #if 0 /* num_servers is unsigned */
3276 if ( sin->num_servers < 0 )
3279 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3282 ObtainWriteLock(&afs_xinterface, 412);
3283 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3284 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3285 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3287 ReleaseWriteLock(&afs_xinterface);
3291 DECL_PIOCTL(PFlushMount)
3293 register afs_int32 code;
3294 register struct vcache *tvc;
3295 register struct dcache *tdc;
3296 struct VenusFid tfid;
3298 struct sysname_info sysState;
3299 afs_size_t offset, len;
3301 AFS_STATCNT(PFlushMount);
3302 if (!avc) return EINVAL;
3303 code = afs_VerifyVCache(avc, areq);
3304 if (code) return code;
3305 if (vType(avc) != VDIR) {
3308 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3309 if (!tdc) return ENOENT;
3310 Check_AtSys(avc, ain, &sysState, areq);
3311 ObtainReadLock(&tdc->lock);
3313 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3314 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3315 ReleaseReadLock(&tdc->lock);
3316 afs_PutDCache(tdc); /* we're done with the data */
3317 bufp = sysState.name;
3321 tfid.Cell = avc->fid.Cell;
3322 tfid.Fid.Volume = avc->fid.Fid.Volume;
3323 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3324 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3326 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3332 if (tvc->mvstat != 1) {
3337 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3338 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3340 ObtainWriteLock(&tvc->lock,649);
3341 ObtainWriteLock(&afs_xcbhash, 650);
3342 afs_DequeueCallback(tvc);
3343 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3344 ReleaseWriteLock(&afs_xcbhash);
3345 /* now find the disk cache entries */
3346 afs_TryToSmush(tvc, *acred, 1);
3347 osi_dnlc_purgedp(tvc);
3348 afs_symhint_inval(tvc);
3349 if (tvc->linkData && !(tvc->states & CCore)) {
3350 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3351 tvc->linkData = NULL;
3353 ReleaseWriteLock(&tvc->lock);
3354 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3355 afs_BozonUnlock(&tvc->pvnLock, tvc);
3359 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3363 DECL_PIOCTL(PRxStatProc)
3368 if (!afs_osi_suser(*acred)) {
3372 if (ainSize != sizeof(afs_int32)) {
3376 memcpy((char *)&flags, ain, sizeof(afs_int32));
3377 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3381 if (flags & AFSCALL_RXSTATS_ENABLE) {
3382 rx_enableProcessRPCStats();
3384 if (flags & AFSCALL_RXSTATS_DISABLE) {
3385 rx_disableProcessRPCStats();
3387 if (flags & AFSCALL_RXSTATS_CLEAR) {
3388 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3396 DECL_PIOCTL(PRxStatPeer)
3401 if (!afs_osi_suser(*acred)) {
3405 if (ainSize != sizeof(afs_int32)) {
3409 memcpy((char *)&flags, ain, sizeof(afs_int32));
3410 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3414 if (flags & AFSCALL_RXSTATS_ENABLE) {
3415 rx_enablePeerRPCStats();
3417 if (flags & AFSCALL_RXSTATS_DISABLE) {
3418 rx_disablePeerRPCStats();
3420 if (flags & AFSCALL_RXSTATS_CLEAR) {
3421 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3428 DECL_PIOCTL(PPrefetchFromTape)
3430 register afs_int32 code, code1;
3433 struct rx_call *tcall;
3434 struct AFSVolSync tsync;
3435 struct AFSFetchStatus OutStatus;
3436 struct AFSCallBack CallBack;
3437 struct VenusFid tfid;
3441 AFS_STATCNT(PSetAcl);
3445 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3446 Fid = (struct AFSFid *) ain;
3448 Fid = &avc->fid.Fid;
3449 tfid.Cell = avc->fid.Cell;
3450 tfid.Fid.Volume = Fid->Volume;
3451 tfid.Fid.Vnode = Fid->Vnode;
3452 tfid.Fid.Unique = Fid->Unique;
3454 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3456 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3457 ICL_TYPE_POINTER, tvc,
3458 ICL_TYPE_FID, &tfid,
3459 ICL_TYPE_FID, &avc->fid);
3462 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3463 ICL_TYPE_POINTER, tvc,
3464 ICL_TYPE_FID, &tfid,
3465 ICL_TYPE_FID, &tvc->fid);
3468 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3472 tcall = rx_NewCall(tc->id);
3473 code = StartRXAFS_FetchData(tcall,
3474 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3476 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3477 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3479 code1 = rx_EndCall(tcall, code);
3484 (afs_Analyze(tc, code, &tvc->fid, areq,
3485 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3487 /* This call is done only to have the callback things handled correctly */
3488 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3492 *aoutSize = sizeof(afs_int32);
3497 DECL_PIOCTL(PResidencyCmd)
3499 register afs_int32 code;
3502 struct ResidencyCmdInputs *Inputs;
3503 struct ResidencyCmdOutputs *Outputs;
3504 struct VenusFid tfid;
3507 Inputs = (struct ResidencyCmdInputs *) ain;
3508 Outputs = (struct ResidencyCmdOutputs *) aout;
3509 if (!avc) return EINVAL;
3510 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3514 Fid = &avc->fid.Fid;
3516 tfid.Cell = avc->fid.Cell;
3517 tfid.Fid.Volume = Fid->Volume;
3518 tfid.Fid.Vnode = Fid->Vnode;
3519 tfid.Fid.Unique = Fid->Unique;
3521 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3522 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3523 ICL_TYPE_POINTER, tvc,
3524 ICL_TYPE_INT32, Inputs->command,
3525 ICL_TYPE_FID, &tfid);
3529 if (Inputs->command) {
3531 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3534 code = RXAFS_ResidencyCmd(tc->id, Fid,
3536 (struct ResidencyCmdOutputs *) aout);
3541 (afs_Analyze(tc, code, &tvc->fid, areq,
3542 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3544 /* This call is done to have the callback things handled correctly */
3545 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3546 } else { /* just a status request, return also link data */
3548 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3549 Outputs->chars[0] = 0;
3550 if (vType(tvc) == VLNK) {
3551 ObtainWriteLock(&tvc->lock,555);
3552 if (afs_HandleLink(tvc, areq) == 0)
3553 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3554 ReleaseWriteLock(&tvc->lock);
3561 *aoutSize = sizeof(struct ResidencyCmdOutputs);