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 vnode *avp, 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, 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 vnode *avp, afs_int32 acom,
1003 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1006 struct vrequest treq;
1007 register afs_int32 code;
1008 register afs_int32 function, device;
1009 afs_int32 inSize, outSize;
1010 char *inData, *outData;
1011 int (*(*pioctlSw))();
1013 struct afs_fakestat_state fakestate;
1015 avc = avp ? VTOAFS(avp) : NULL;
1016 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1017 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1018 AFS_STATCNT(HandlePioctl);
1019 if ((code = afs_InitReq(&treq, *acred))) return code;
1020 afs_InitFakeStat(&fakestate);
1022 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1024 afs_PutFakeStat(&fakestate);
1028 device = (acom & 0xff00) >> 8;
1030 case 'V': /* Original pioctls */
1031 pioctlSw = VpioctlSw;
1032 pioctlSwSize = sizeof(VpioctlSw);
1034 case 'C': /* Coordinated/common pioctls */
1035 pioctlSw = CpioctlSw;
1036 pioctlSwSize = sizeof(CpioctlSw);
1039 afs_PutFakeStat(&fakestate);
1042 function = acom & 0xff;
1043 if (function >= (pioctlSwSize / sizeof(char *))) {
1044 afs_PutFakeStat(&fakestate);
1045 return EINVAL; /* out of range */
1047 inSize = ablob->in_size;
1048 if (inSize >= PIGGYSIZE) return E2BIG;
1049 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1051 AFS_COPYIN(ablob->in, inData, inSize, code);
1052 inData[inSize]='\0';
1056 osi_FreeLargeSpace(inData);
1057 afs_PutFakeStat(&fakestate);
1060 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1062 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1063 osi_FreeLargeSpace(inData);
1064 if (code == 0 && ablob->out_size > 0) {
1065 if (outSize > ablob->out_size) outSize = ablob->out_size;
1066 if (outSize >= PIGGYSIZE) code = E2BIG;
1068 outData[outSize]='\0';
1069 AFS_COPYOUT(outData, ablob->out, outSize, code);
1072 osi_FreeLargeSpace(outData);
1073 afs_PutFakeStat(&fakestate);
1074 return afs_CheckCode(code, &treq, 41);
1077 DECL_PIOCTL(PGetFID)
1079 AFS_STATCNT(PGetFID);
1080 if (!avc) return EINVAL;
1081 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1082 *aoutSize = sizeof(struct VenusFid);
1086 DECL_PIOCTL(PSetAcl)
1088 register afs_int32 code;
1090 struct AFSOpaque acl;
1091 struct AFSVolSync tsync;
1092 struct AFSFetchStatus OutStatus;
1095 AFS_STATCNT(PSetAcl);
1098 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1101 acl.AFSOpaque_val = ain;
1103 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1105 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1107 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1108 &acl, &OutStatus, &tsync);
1114 (afs_Analyze(tconn, code, &avc->fid, areq,
1115 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1117 /* now we've forgotten all of the access info */
1118 ObtainWriteLock(&afs_xcbhash, 455);
1120 afs_DequeueCallback(avc);
1121 avc->states &= ~(CStatd | CUnique);
1122 ReleaseWriteLock(&afs_xcbhash);
1123 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1124 osi_dnlc_purgedp(avc);
1128 int afs_defaultAsynchrony = 0;
1130 DECL_PIOCTL(PStoreBehind)
1133 struct sbstruct *sbr;
1135 sbr = (struct sbstruct *)ain;
1136 if (sbr->sb_default != -1) {
1137 if (afs_osi_suser(*acred))
1138 afs_defaultAsynchrony = sbr->sb_default;
1142 if (avc && (sbr->sb_thisfile != -1)) {
1143 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1144 areq, DONT_CHECK_MODE_BITS))
1145 avc->asynchrony = sbr->sb_thisfile;
1149 *aoutSize = sizeof(struct sbstruct);
1150 sbr = (struct sbstruct *)aout;
1151 sbr->sb_default = afs_defaultAsynchrony;
1153 sbr->sb_thisfile = avc->asynchrony;
1159 DECL_PIOCTL(PGCPAGs)
1161 if (!afs_osi_suser(*acred)) {
1164 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1168 DECL_PIOCTL(PGetAcl)
1170 struct AFSOpaque acl;
1171 struct AFSVolSync tsync;
1172 struct AFSFetchStatus OutStatus;
1178 AFS_STATCNT(PGetAcl);
1179 if (!avc) return EINVAL;
1180 Fid.Volume = avc->fid.Fid.Volume;
1181 Fid.Vnode = avc->fid.Fid.Vnode;
1182 Fid.Unique = avc->fid.Fid.Unique;
1183 if (avc->states & CForeign) {
1185 * For a dfs xlator acl we have a special hack so that the
1186 * xlator will distinguish which type of acl will return. So
1187 * we currently use the top 2-bytes (vals 0-4) to tell which
1188 * type of acl to bring back. Horrible hack but this will
1189 * cause the least number of changes to code size and interfaces.
1191 if (Fid.Vnode & 0xc0000000)
1193 Fid.Vnode |= (ainSize << 30);
1195 acl.AFSOpaque_val = aout;
1197 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1200 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1202 code = RXAFS_FetchACL(tconn->id, &Fid,
1203 &acl, &OutStatus, &tsync);
1209 (afs_Analyze(tconn, code, &avc->fid, areq,
1210 AFS_STATS_FS_RPCIDX_FETCHACL,
1211 SHARED_LOCK, NULL));
1214 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1227 AFS_STATCNT(PBogus);
1231 DECL_PIOCTL(PGetFileCell)
1233 register struct cell *tcell;
1235 AFS_STATCNT(PGetFileCell);
1236 if (!avc) return EINVAL;
1237 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1238 if (!tcell) return ESRCH;
1239 strcpy(aout, tcell->cellName);
1240 afs_PutCell(tcell, READ_LOCK);
1241 *aoutSize = strlen(aout) + 1;
1245 DECL_PIOCTL(PGetWSCell)
1247 struct cell *tcell = NULL;
1249 AFS_STATCNT(PGetWSCell);
1250 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1251 return EIO; /* Inappropriate ioctl for device */
1253 tcell = afs_GetPrimaryCell(READ_LOCK);
1254 if (!tcell) /* no primary cell? */
1256 strcpy(aout, tcell->cellName);
1257 *aoutSize = strlen(aout) + 1;
1258 afs_PutCell(tcell, READ_LOCK);
1262 DECL_PIOCTL(PGetUserCell)
1264 register afs_int32 i;
1265 register struct unixuser *tu;
1266 register struct cell *tcell;
1268 AFS_STATCNT(PGetUserCell);
1269 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1270 return EIO; /* Inappropriate ioctl for device */
1272 /* return the cell name of the primary cell for this user */
1273 i = UHash(areq->uid);
1274 ObtainWriteLock(&afs_xuser,224);
1275 for(tu = afs_users[i]; tu; tu = tu->next) {
1276 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1278 ReleaseWriteLock(&afs_xuser);
1283 tcell = afs_GetCell(tu->cell, READ_LOCK);
1284 afs_PutUser(tu, WRITE_LOCK);
1285 if (!tcell) return ESRCH;
1287 strcpy(aout, tcell->cellName);
1288 afs_PutCell(tcell, READ_LOCK);
1289 *aoutSize = strlen(aout)+1; /* 1 for the null */
1293 ReleaseWriteLock(&afs_xuser);
1300 DECL_PIOCTL(PSetTokens)
1303 register struct unixuser *tu;
1304 struct ClearToken clear;
1305 register struct cell *tcell;
1308 struct vrequest treq;
1309 afs_int32 flag, set_parent_pag = 0;
1311 AFS_STATCNT(PSetTokens);
1312 if (!afs_resourceinit_flag) {
1315 memcpy((char *)&i, ain, sizeof(afs_int32));
1316 ain += sizeof(afs_int32);
1317 stp = ain; /* remember where the ticket is */
1318 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1319 if (i > MAXKTCTICKETLEN) return EINVAL;
1321 ain += i; /* skip over ticket */
1322 memcpy((char *)&i, ain, sizeof(afs_int32));
1323 ain += sizeof(afs_int32);
1324 if (i != sizeof(struct ClearToken)) {
1327 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1328 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1329 ain += sizeof(struct ClearToken);
1330 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1331 /* still stuff left? we've got primary flag and cell name. Set these */
1332 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1333 ain += sizeof(afs_int32); /* skip id field */
1334 /* rest is cell name, look it up */
1335 /* some versions of gcc appear to need != 0 in order to get this right */
1336 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1340 tcell = afs_GetCellByName(ain, READ_LOCK);
1341 if (!tcell) goto nocell;
1344 /* default to primary cell, primary id */
1345 flag = 1; /* primary id */
1346 tcell = afs_GetPrimaryCell(READ_LOCK);
1347 if (!tcell) goto nocell;
1350 afs_PutCell(tcell, READ_LOCK);
1351 if (set_parent_pag) {
1353 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1354 #if defined(AFS_DARWIN_ENV)
1355 struct proc *p = current_proc(); /* XXX */
1357 struct proc *p = curproc; /* XXX */
1359 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1360 p->p_pid, p->p_comm);
1361 if (!setpag(p, acred, -1, &pag, 1)) {
1364 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1366 if (!setpag(acred, -1, &pag, 1)) {
1369 afs_InitReq(&treq, *acred);
1373 /* now we just set the tokens */
1374 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1375 tu->vid = clear.ViceId;
1376 if (tu->stp != NULL) {
1377 afs_osi_Free(tu->stp, tu->stLen);
1379 tu->stp = (char *) afs_osi_Alloc(stLen);
1381 memcpy(tu->stp, stp, stLen);
1384 afs_stats_cmfullperf.authent.TicketUpdates++;
1385 afs_ComputePAGStats();
1386 #endif /* AFS_NOSTATS */
1387 tu->states |= UHasTokens;
1388 tu->states &= ~UTokensBad;
1389 afs_SetPrimary(tu, flag);
1390 tu->tokenTime =osi_Time();
1391 afs_ResetUserConns(tu);
1392 afs_PutUser(tu, WRITE_LOCK);
1407 DECL_PIOCTL(PGetVolumeStatus)
1410 char offLineMsg[256];
1412 register struct conn *tc;
1413 register afs_int32 code;
1414 struct VolumeStatus volstat;
1416 char *Name, *OfflineMsg, *MOTD;
1419 AFS_STATCNT(PGetVolumeStatus);
1420 if (!avc) return EINVAL;
1422 OfflineMsg = offLineMsg;
1425 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1427 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1429 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1430 &Name, &OfflineMsg, &MOTD);
1436 (afs_Analyze(tc, code, &avc->fid, areq,
1437 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1438 SHARED_LOCK, NULL));
1440 if (code) return code;
1441 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1443 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1444 cp += sizeof(VolumeStatus);
1445 strcpy(cp, volName);
1446 cp += strlen(volName)+1;
1447 strcpy(cp, offLineMsg);
1448 cp += strlen(offLineMsg)+1;
1450 cp += strlen(motd)+1;
1451 *aoutSize = (cp - aout);
1455 DECL_PIOCTL(PSetVolumeStatus)
1458 char offLineMsg[256];
1460 register struct conn *tc;
1461 register afs_int32 code;
1462 struct AFSFetchVolumeStatus volstat;
1463 struct AFSStoreVolumeStatus storeStat;
1464 register struct volume *tvp;
1468 AFS_STATCNT(PSetVolumeStatus);
1469 if (!avc) return EINVAL;
1471 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1473 if (tvp->states & (VRO | VBackup)) {
1474 afs_PutVolume(tvp, READ_LOCK);
1477 afs_PutVolume(tvp, READ_LOCK);
1480 /* Copy the junk out, using cp as a roving pointer. */
1482 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1483 cp += sizeof(AFSFetchVolumeStatus);
1484 if (strlen(cp) >= sizeof(volName))
1486 strcpy(volName, cp);
1487 cp += strlen(volName)+1;
1488 if (strlen(cp) >= sizeof(offLineMsg))
1490 strcpy(offLineMsg, cp);
1491 cp += strlen(offLineMsg)+1;
1492 if (strlen(cp) >= sizeof(motd))
1496 if (volstat.MinQuota != -1) {
1497 storeStat.MinQuota = volstat.MinQuota;
1498 storeStat.Mask |= AFS_SETMINQUOTA;
1500 if (volstat.MaxQuota != -1) {
1501 storeStat.MaxQuota = volstat.MaxQuota;
1502 storeStat.Mask |= AFS_SETMAXQUOTA;
1505 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1507 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1509 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1510 &storeStat, volName, offLineMsg, motd);
1516 (afs_Analyze(tc, code, &avc->fid, areq,
1517 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1518 SHARED_LOCK, NULL));
1520 if (code) return code;
1521 /* we are sending parms back to make compat. with prev system. should
1522 change interface later to not ask for current status, just set new status */
1524 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1525 cp += sizeof(VolumeStatus);
1526 strcpy(cp, volName);
1527 cp += strlen(volName)+1;
1528 strcpy(cp, offLineMsg);
1529 cp += strlen(offLineMsg)+1;
1531 cp += strlen(motd)+1;
1532 *aoutSize = cp - aout;
1538 AFS_STATCNT(PFlush);
1539 if (!avc) return EINVAL;
1540 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1541 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1543 ObtainWriteLock(&avc->lock,225);
1544 ObtainWriteLock(&afs_xcbhash, 456);
1545 afs_DequeueCallback(avc);
1546 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1547 ReleaseWriteLock(&afs_xcbhash);
1548 /* now find the disk cache entries */
1549 afs_TryToSmush(avc, *acred, 1);
1550 osi_dnlc_purgedp(avc);
1551 afs_symhint_inval(avc);
1552 if (avc->linkData && !(avc->states & CCore)) {
1553 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1554 avc->linkData = NULL;
1556 ReleaseWriteLock(&avc->lock);
1557 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1558 afs_BozonUnlock(&avc->pvnLock, avc);
1563 DECL_PIOCTL(PNewStatMount)
1565 register afs_int32 code;
1566 register struct vcache *tvc;
1567 register struct dcache *tdc;
1568 struct VenusFid tfid;
1570 struct sysname_info sysState;
1571 afs_size_t offset, len;
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, (afs_size_t) 0, areq, &offset, &len, 1);
1581 if (!tdc) return ENOENT;
1582 Check_AtSys(avc, ain, &sysState, areq);
1583 ObtainReadLock(&tdc->lock);
1585 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1586 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1587 ReleaseReadLock(&tdc->lock);
1588 afs_PutDCache(tdc); /* we're done with the data */
1589 bufp = sysState.name;
1593 tfid.Cell = avc->fid.Cell;
1594 tfid.Fid.Volume = avc->fid.Fid.Volume;
1595 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1596 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1598 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1604 if (tvc->mvstat != 1) {
1609 ObtainWriteLock(&tvc->lock,226);
1610 code = afs_HandleLink(tvc, areq);
1612 if (tvc->linkData) {
1613 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1616 /* we have the data */
1617 strcpy(aout, tvc->linkData);
1618 *aoutSize = strlen(tvc->linkData)+1;
1623 ReleaseWriteLock(&tvc->lock);
1626 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1630 DECL_PIOCTL(PGetTokens)
1632 register struct cell *tcell;
1633 register afs_int32 i;
1634 register struct unixuser *tu;
1639 AFS_STATCNT(PGetTokens);
1640 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1641 return EIO; /* Inappropriate ioctl for device */
1643 /* weird interface. If input parameter is present, it is an integer and
1644 we're supposed to return the parm'th tokens for this unix uid.
1645 If not present, we just return tokens for cell 1.
1646 If counter out of bounds, return EDOM.
1647 If no tokens for the particular cell, return ENOTCONN.
1648 Also, if this mysterious parm is present, we return, along with the
1649 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1650 at the end, in that order.
1652 if ((newStyle = (ainSize > 0))) {
1653 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1655 i = UHash(areq->uid);
1656 ObtainReadLock(&afs_xuser);
1657 for(tu = afs_users[i]; tu; tu=tu->next) {
1659 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1660 if (iterator-- == 0) break; /* are we done yet? */
1664 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1669 * No need to hold a read lock on each user entry
1673 ReleaseReadLock(&afs_xuser);
1678 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1679 tu->states |= (UTokensBad | UNeedsReset);
1680 afs_PutUser(tu, READ_LOCK);
1683 /* use iterator for temp */
1685 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1686 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1687 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1688 cp += sizeof(afs_int32);
1689 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1691 iterator = sizeof(struct ClearToken);
1692 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1693 cp += sizeof(afs_int32);
1694 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1695 cp += sizeof(struct ClearToken);
1697 /* put out primary id and cell name, too */
1698 iterator = (tu->states & UPrimary ? 1 : 0);
1699 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1700 cp += sizeof(afs_int32);
1701 tcell = afs_GetCell(tu->cell, READ_LOCK);
1703 strcpy(cp, tcell->cellName);
1704 cp += strlen(tcell->cellName)+1;
1705 afs_PutCell(tcell, READ_LOCK);
1709 *aoutSize = cp - aout;
1710 afs_PutUser(tu, READ_LOCK);
1716 register afs_int32 i;
1717 register struct unixuser *tu;
1719 AFS_STATCNT(PUnlog);
1720 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1721 return EIO; /* Inappropriate ioctl for device */
1723 i = UHash(areq->uid);
1724 ObtainWriteLock(&afs_xuser,227);
1725 for(tu=afs_users[i]; tu; tu=tu->next) {
1726 if (tu->uid == areq->uid) {
1728 tu->states &= ~UHasTokens;
1729 /* security is not having to say you're sorry */
1730 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1732 ReleaseWriteLock(&afs_xuser);
1733 /* We have to drop the lock over the call to afs_ResetUserConns, since
1734 * it obtains the afs_xvcache lock. We could also keep the lock, and
1735 * modify ResetUserConns to take parm saying we obtained the lock
1736 * already, but that is overkill. By keeping the "tu" pointer
1737 * held over the released lock, we guarantee that we won't lose our
1738 * place, and that we'll pass over every user conn that existed when
1739 * we began this call.
1741 afs_ResetUserConns(tu);
1743 ObtainWriteLock(&afs_xuser,228);
1745 /* set the expire times to 0, causes
1746 * afs_GCUserData to remove this entry
1748 tu->ct.EndTimestamp = 0;
1750 #endif /* UKERNEL */
1753 ReleaseWriteLock(&afs_xuser);
1757 DECL_PIOCTL(PMariner)
1759 afs_int32 newHostAddr;
1760 afs_int32 oldHostAddr;
1762 AFS_STATCNT(PMariner);
1764 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1766 oldHostAddr = 0xffffffff; /* disabled */
1768 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1769 if (newHostAddr == 0xffffffff) {
1770 /* disable mariner operations */
1773 else if (newHostAddr) {
1775 afs_marinerHost = newHostAddr;
1777 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1778 *aoutSize = sizeof(afs_int32);
1782 DECL_PIOCTL(PCheckServers)
1784 register char *cp = 0;
1786 register struct server *ts;
1787 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1789 struct chservinfo *pcheck;
1791 AFS_STATCNT(PCheckServers);
1793 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1794 return EIO; /* Inappropriate ioctl for device */
1796 if (*lp == 0x12345678) { /* For afs3.3 version */
1797 pcheck=(struct chservinfo *)ain;
1798 if (pcheck->tinterval >= 0) {
1800 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1801 *aoutSize = sizeof(afs_int32);
1802 if (pcheck->tinterval > 0) {
1803 if (!afs_osi_suser(*acred))
1805 PROBE_INTERVAL=pcheck->tinterval;
1811 temp=pcheck->tflags;
1812 cp = pcheck->tbuffer;
1813 } else { /* For pre afs3.3 versions */
1814 memcpy((char *)&temp, ain, sizeof(afs_int32));
1815 cp = ain+sizeof(afs_int32);
1816 if (ainSize > sizeof(afs_int32))
1821 * 1: fast check, don't contact servers.
1822 * 2: local cell only.
1825 /* have cell name, too */
1826 cellp = afs_GetCellByName(cp, READ_LOCK);
1827 if (!cellp) return ENOENT;
1830 if (!cellp && (temp & 2)) {
1831 /* use local cell */
1832 cellp = afs_GetPrimaryCell(READ_LOCK);
1834 if (!(temp & 1)) { /* if not fast, call server checker routine */
1835 afs_CheckServers(1, cellp); /* check down servers */
1836 afs_CheckServers(0, cellp); /* check up servers */
1838 /* now return the current down server list */
1840 ObtainReadLock(&afs_xserver);
1841 for(i=0;i<NSERVERS;i++) {
1842 for(ts = afs_servers[i]; ts; ts=ts->next) {
1843 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1844 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1845 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1846 cp += sizeof(afs_int32);
1850 ReleaseReadLock(&afs_xserver);
1851 if (cellp) afs_PutCell(cellp, READ_LOCK);
1852 *aoutSize = cp - aout;
1856 DECL_PIOCTL(PCheckVolNames)
1858 AFS_STATCNT(PCheckVolNames);
1859 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1860 return EIO; /* Inappropriate ioctl for device */
1862 afs_CheckRootVolume();
1863 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1864 AFS_VOLCHECK_EXPIRED |
1866 AFS_VOLCHECK_MTPTS);
1870 DECL_PIOCTL(PCheckAuth)
1875 struct unixuser *tu;
1878 AFS_STATCNT(PCheckAuth);
1879 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1880 return EIO; /* Inappropriate ioctl for device */
1883 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1884 if (!tu) retValue = EACCES;
1886 /* we have a user */
1887 ObtainReadLock(&afs_xsrvAddr);
1888 ObtainReadLock(&afs_xconn);
1890 /* any tokens set? */
1891 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1892 /* all connections in cell 1 working? */
1893 for(i=0;i<NSERVERS;i++) {
1894 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1895 for (tc = sa->conns; tc; tc=tc->next) {
1896 if (tc->user == tu && (tu->states & UTokensBad))
1901 ReleaseReadLock(&afs_xsrvAddr);
1902 ReleaseReadLock(&afs_xconn);
1903 afs_PutUser(tu, READ_LOCK);
1905 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1906 *aoutSize = sizeof(afs_int32);
1910 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1913 register afs_int32 code;
1914 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1920 AFS_STATCNT(Prefetch);
1921 if (!apath) return EINVAL;
1922 tp = osi_AllocLargeSpace(1024);
1923 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1925 osi_FreeLargeSpace(tp);
1928 if (afs_BBusy()) { /* do this as late as possible */
1929 osi_FreeLargeSpace(tp);
1930 return EWOULDBLOCK; /* pretty close */
1932 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1933 (afs_size_t) 0, (afs_size_t) 0, tp);
1937 DECL_PIOCTL(PFindVolume)
1939 register struct volume *tvp;
1940 register struct server *ts;
1941 register afs_int32 i;
1944 AFS_STATCNT(PFindVolume);
1945 if (!avc) return EINVAL;
1946 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1949 for(i=0;i<MAXHOSTS;i++) {
1950 ts = tvp->serverHost[i];
1952 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1953 cp += sizeof(afs_int32);
1956 /* still room for terminating NULL, add it on */
1957 ainSize = 0; /* reuse vbl */
1958 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
1959 cp += sizeof(afs_int32);
1961 *aoutSize = cp - aout;
1962 afs_PutVolume(tvp, READ_LOCK);
1968 DECL_PIOCTL(PViceAccess)
1970 register afs_int32 code;
1973 AFS_STATCNT(PViceAccess);
1974 if (!avc) return EINVAL;
1975 code = afs_VerifyVCache(avc, areq);
1976 if (code) return code;
1977 memcpy((char *)&temp, ain, sizeof(afs_int32));
1978 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
1983 DECL_PIOCTL(PSetCacheSize)
1988 AFS_STATCNT(PSetCacheSize);
1989 if (!afs_osi_suser(*acred))
1991 /* too many things are setup initially in mem cache version */
1992 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
1993 memcpy((char *)&newValue, ain, sizeof(afs_int32));
1994 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
1996 if (newValue < afs_min_cache)
1997 afs_cacheBlocks = afs_min_cache;
1999 afs_cacheBlocks = newValue;
2001 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2002 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2003 afs_MaybeWakeupTruncateDaemon();
2004 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2005 afs_osi_Wait(1000, 0, 0);
2006 afs_MaybeWakeupTruncateDaemon();
2011 #define MAXGCSTATS 16
2012 DECL_PIOCTL(PGetCacheSize)
2014 afs_int32 results[MAXGCSTATS];
2016 AFS_STATCNT(PGetCacheSize);
2017 memset((char *)results, 0, sizeof(results));
2018 results[0] = afs_cacheBlocks;
2019 results[1] = afs_blocksUsed;
2020 memcpy(aout, (char *)results, sizeof(results));
2021 *aoutSize = sizeof(results);
2025 DECL_PIOCTL(PRemoveCallBack)
2027 register struct conn *tc;
2028 register afs_int32 code = 0;
2029 struct AFSCallBack CallBacks_Array[1];
2030 struct AFSCBFids theFids;
2031 struct AFSCBs theCBs;
2034 AFS_STATCNT(PRemoveCallBack);
2035 if (!avc) return EINVAL;
2036 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2037 ObtainWriteLock(&avc->lock,229);
2038 theFids.AFSCBFids_len = 1;
2039 theCBs.AFSCBs_len = 1;
2040 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2041 theCBs.AFSCBs_val = CallBacks_Array;
2042 CallBacks_Array[0].CallBackType = CB_DROPPED;
2043 if (avc->callback) {
2045 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2047 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2049 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2053 /* don't set code on failure since we wouldn't use it */
2055 (afs_Analyze(tc, code, &avc->fid, areq,
2056 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2057 SHARED_LOCK, NULL));
2059 ObtainWriteLock(&afs_xcbhash, 457);
2060 afs_DequeueCallback(avc);
2062 avc->states &= ~(CStatd | CUnique);
2063 ReleaseWriteLock(&afs_xcbhash);
2064 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2065 osi_dnlc_purgedp(avc);
2067 ReleaseWriteLock(&avc->lock);
2071 DECL_PIOCTL(PNewCell)
2073 /* create a new cell */
2074 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2075 char *newcell=0, *linkedcell=0, *tp= ain;
2076 register afs_int32 code, linkedstate=0, ls;
2077 u_short fsport = 0, vlport = 0;
2080 AFS_STATCNT(PNewCell);
2081 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2082 return EIO; /* Inappropriate ioctl for device */
2084 if (!afs_osi_suser(*acred))
2087 memcpy((char *)&magic, tp, sizeof(afs_int32));
2088 tp += sizeof(afs_int32);
2089 if (magic != 0x12345678)
2092 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2093 * server addresses while the 3.5 fs newcell command passes
2094 * MAXHOSTS. To figure out which is which, check if the cellname
2097 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2098 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2100 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2101 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2102 tp += (scount * sizeof(afs_int32));
2104 lp = (afs_int32 *)tp;
2107 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2108 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2109 tp += (3 * sizeof(afs_int32));
2111 if ((ls = *lp) & 1) {
2112 linkedcell = tp + strlen(newcell)+1;
2113 linkedstate |= CLinkedCell;
2116 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2117 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2122 DECL_PIOCTL(PNewAlias)
2124 /* create a new cell alias */
2126 register afs_int32 code;
2127 char *realName, *aliasName;
2129 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2130 return EIO; /* Inappropriate ioctl for device */
2132 if (!afs_osi_suser(*acred))
2136 tp += strlen(aliasName) + 1;
2139 code = afs_NewCellAlias(aliasName, realName);
2144 DECL_PIOCTL(PListCells)
2146 afs_int32 whichCell;
2147 register struct cell *tcell=0;
2148 register afs_int32 i;
2149 register char *cp, *tp = ain;
2151 AFS_STATCNT(PListCells);
2152 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2153 return EIO; /* Inappropriate ioctl for device */
2155 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2156 tp += sizeof(afs_int32);
2157 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2160 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2161 for(i=0;i<MAXCELLHOSTS;i++) {
2162 if (tcell->cellHosts[i] == 0) break;
2163 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2164 cp += sizeof(afs_int32);
2166 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2167 strcpy(cp, tcell->cellName);
2168 cp += strlen(tcell->cellName)+1;
2169 *aoutSize = cp - aout;
2170 afs_PutCell(tcell, READ_LOCK);
2172 if (tcell) return 0;
2176 DECL_PIOCTL(PListAliases)
2178 afs_int32 whichAlias;
2179 register struct cell_alias *tcalias=0;
2180 register char *cp, *tp = ain;
2182 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2183 return EIO; /* Inappropriate ioctl for device */
2184 if (ainSize < sizeof(afs_int32))
2187 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2188 tp += sizeof(afs_int32);
2190 tcalias = afs_GetCellAlias(whichAlias);
2193 strcpy(cp, tcalias->alias);
2194 cp += strlen(tcalias->alias)+1;
2195 strcpy(cp, tcalias->cell);
2196 cp += strlen(tcalias->cell)+1;
2197 *aoutSize = cp - aout;
2198 afs_PutCellAlias(tcalias);
2200 if (tcalias) return 0;
2204 DECL_PIOCTL(PRemoveMount)
2206 register afs_int32 code;
2208 struct sysname_info sysState;
2209 afs_size_t offset, len;
2210 register struct conn *tc;
2211 register struct dcache *tdc;
2212 register struct vcache *tvc;
2213 struct AFSFetchStatus OutDirStatus;
2214 struct VenusFid tfid;
2215 struct AFSVolSync tsync;
2219 /* "ain" is the name of the file in this dir to remove */
2221 AFS_STATCNT(PRemoveMount);
2222 if (!avc) return EINVAL;
2223 code = afs_VerifyVCache(avc, areq);
2224 if (code) return code;
2225 if (vType(avc) != VDIR) return ENOTDIR;
2227 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2228 if (!tdc) return ENOENT;
2229 Check_AtSys(avc, ain, &sysState, areq);
2230 ObtainReadLock(&tdc->lock);
2232 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2233 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2234 ReleaseReadLock(&tdc->lock);
2235 bufp = sysState.name;
2240 tfid.Cell = avc->fid.Cell;
2241 tfid.Fid.Volume = avc->fid.Fid.Volume;
2242 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2243 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2245 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2252 if (tvc->mvstat != 1) {
2258 ObtainWriteLock(&tvc->lock,230);
2259 code = afs_HandleLink(tvc, areq);
2261 if (tvc->linkData) {
2262 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2267 ReleaseWriteLock(&tvc->lock);
2268 osi_dnlc_purgedp(tvc);
2274 ObtainWriteLock(&avc->lock,231);
2275 osi_dnlc_remove(avc, bufp, tvc);
2277 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2279 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2281 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2282 bufp, &OutDirStatus, &tsync);
2288 (afs_Analyze(tc, code, &avc->fid, areq,
2289 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2290 SHARED_LOCK, NULL));
2293 if (tdc) afs_PutDCache(tdc);
2294 ReleaseWriteLock(&avc->lock);
2298 /* we have the thing in the cache */
2299 ObtainWriteLock(&tdc->lock, 661);
2300 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2301 /* we can do it locally */
2302 code = afs_dir_Delete(&tdc->f.inode, bufp);
2304 ZapDCE(tdc); /* surprise error -- invalid value */
2305 DZap(&tdc->f.inode);
2308 ReleaseWriteLock(&tdc->lock);
2309 afs_PutDCache(tdc); /* drop ref count */
2311 avc->states &= ~CUnique; /* For the dfs xlator */
2312 ReleaseWriteLock(&avc->lock);
2315 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2319 DECL_PIOCTL(PVenusLogging)
2321 return EINVAL; /* OBSOLETE */
2324 DECL_PIOCTL(PGetCellStatus)
2326 register struct cell *tcell;
2329 AFS_STATCNT(PGetCellStatus);
2330 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2331 return EIO; /* Inappropriate ioctl for device */
2333 tcell = afs_GetCellByName(ain, READ_LOCK);
2334 if (!tcell) return ENOENT;
2335 temp = tcell->states;
2336 afs_PutCell(tcell, READ_LOCK);
2337 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2338 *aoutSize = sizeof(afs_int32);
2342 DECL_PIOCTL(PSetCellStatus)
2344 register struct cell *tcell;
2347 if (!afs_osi_suser(*acred))
2349 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2350 return EIO; /* Inappropriate ioctl for device */
2352 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2353 if (!tcell) return ENOENT;
2354 memcpy((char *)&temp, ain, sizeof(afs_int32));
2356 tcell->states |= CNoSUID;
2358 tcell->states &= ~CNoSUID;
2359 afs_PutCell(tcell, WRITE_LOCK);
2363 DECL_PIOCTL(PFlushVolumeData)
2365 register afs_int32 i;
2366 register struct dcache *tdc;
2367 register struct vcache *tvc;
2368 register struct volume *tv;
2369 afs_int32 cell, volume;
2371 AFS_STATCNT(PFlushVolumeData);
2374 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2375 return EIO; /* Inappropriate ioctl for device */
2377 volume = avc->fid.Fid.Volume; /* who to zap */
2378 cell = avc->fid.Cell;
2381 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2382 * the vcaches associated with the volume.
2384 ObtainReadLock(&afs_xvcache);
2385 for(i = 0; i < VCSIZE; i++) {
2386 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2387 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2388 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2389 VN_HOLD(AFSTOV(tvc));
2391 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2397 ReleaseReadLock(&afs_xvcache);
2398 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2399 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2401 ObtainWriteLock(&tvc->lock,232);
2403 ObtainWriteLock(&afs_xcbhash, 458);
2404 afs_DequeueCallback(tvc);
2405 tvc->states &= ~(CStatd | CDirty);
2406 ReleaseWriteLock(&afs_xcbhash);
2407 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2408 osi_dnlc_purgedp(tvc);
2409 afs_TryToSmush(tvc, *acred, 1);
2410 ReleaseWriteLock(&tvc->lock);
2411 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2412 afs_BozonUnlock(&tvc->pvnLock, tvc);
2414 ObtainReadLock(&afs_xvcache);
2415 /* our tvc ptr is still good until now */
2420 ReleaseReadLock(&afs_xvcache);
2423 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2424 for(i=0;i<afs_cacheFiles;i++) {
2425 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2426 tdc = afs_GetDSlot(i, NULL);
2427 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2428 ReleaseReadLock(&tdc->tlock);
2429 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2430 if (! (afs_indexFlags[i] & IFDataMod)) {
2431 /* if the file is modified, but has a ref cnt of only 1, then
2432 someone probably has the file open and is writing into it.
2433 Better to skip flushing such a file, it will be brought back
2434 immediately on the next write anyway.
2436 If we *must* flush, then this code has to be rearranged to call
2437 afs_storeAllSegments() first */
2438 afs_FlushDCache(tdc);
2442 ReleaseReadLock(&tdc->tlock);
2444 afs_PutDCache(tdc); /* bumped by getdslot */
2446 MReleaseWriteLock(&afs_xdcache);
2448 ObtainReadLock(&afs_xvolume);
2449 for (i=0;i<NVOLS;i++) {
2450 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2451 if (tv->volume == volume) {
2452 afs_ResetVolumeInfo(tv);
2457 ReleaseReadLock(&afs_xvolume);
2459 /* probably, a user is doing this, probably, because things are screwed up.
2460 * maybe it's the dnlc's fault? */
2467 DECL_PIOCTL(PGetVnodeXStatus)
2469 register afs_int32 code;
2470 struct vcxstat stat;
2473 /* AFS_STATCNT(PGetVnodeXStatus); */
2474 if (!avc) return EINVAL;
2475 code = afs_VerifyVCache(avc, areq);
2476 if (code) return code;
2477 if (vType(avc) == VDIR)
2478 mode = PRSFS_LOOKUP;
2481 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2483 stat.fid = avc->fid;
2484 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2485 stat.lock = avc->lock;
2486 stat.parentVnode = avc->parentVnode;
2487 stat.parentUnique = avc->parentUnique;
2488 hset(stat.flushDV, avc->flushDV);
2489 hset(stat.mapDV, avc->mapDV);
2490 stat.truncPos = avc->truncPos;
2491 { /* just grab the first two - won't break anything... */
2492 struct axscache *ac;
2494 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2495 stat.randomUid[i] = ac->uid;
2496 stat.randomAccess[i] = ac->axess;
2499 stat.callback = afs_data_pointer_to_int32(avc->callback);
2500 stat.cbExpires = avc->cbExpires;
2501 stat.anyAccess = avc->anyAccess;
2502 stat.opens = avc->opens;
2503 stat.execsOrWriters = avc->execsOrWriters;
2504 stat.flockCount = avc->flockCount;
2505 stat.mvstat = avc->mvstat;
2506 stat.states = avc->states;
2507 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2508 *aoutSize = sizeof(struct vcxstat);
2513 /* We require root for local sysname changes, but not for remote */
2514 /* (since we don't really believe remote uids anyway) */
2515 /* outname[] shouldn't really be needed- this is left as an excercise */
2516 /* for the reader. */
2517 DECL_PIOCTL(PSetSysName)
2519 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2520 int setsysname, foundname=0;
2521 register struct afs_exporter *exporter;
2522 register struct unixuser *au;
2523 register afs_int32 pag, error;
2527 AFS_STATCNT(PSetSysName);
2528 if (!afs_globalVFS) {
2529 /* Afsd is NOT running; disable it */
2530 #if defined(KERNEL_HAVE_UERROR)
2531 return (setuerror(EINVAL), EINVAL);
2536 memset(inname, 0, MAXSYSNAME);
2537 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2538 ain += sizeof(afs_int32);
2542 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2544 for(cp = ain,count = 0;count < setsysname;count++) {
2545 /* won't go past end of ain since maxsysname*num < ain length */
2547 if (t >= MAXSYSNAME || t <= 0)
2549 /* check for names that can shoot us in the foot */
2550 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2556 /* inname gets first entry in case we're being a translater */
2558 memcpy(inname, ain, t+1); /* include terminating null */
2561 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2562 pag = PagInCred(*acred);
2564 return EINVAL; /* Better than panicing */
2566 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2567 return EINVAL; /* Better than panicing */
2569 if (!(exporter = au->exporter)) {
2570 afs_PutUser(au, READ_LOCK);
2571 return EINVAL; /* Better than panicing */
2573 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2575 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2577 afs_PutUser(au, READ_LOCK);
2582 afs_PutUser(au, READ_LOCK);
2585 /* Not xlating, so local case */
2586 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2587 if (!setsysname) { /* user just wants the info */
2588 strcpy(outname, afs_sysname);
2589 foundname = afs_sysnamecount;
2590 } else { /* Local guy; only root can change sysname */
2591 if (!afs_osi_suser(*acred))
2594 /* clear @sys entries from the dnlc, once afs_lookup can
2595 do lookups of @sys entries and thinks it can trust them */
2596 /* privs ok, store the entry, ... */
2597 strcpy(afs_sysname, inname);
2598 if (setsysname > 1) { /* ... or list */
2600 for(count=1; count < setsysname;++count) {
2601 if (!afs_sysnamelist[count])
2602 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2604 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2608 afs_sysnamecount = setsysname;
2612 cp = aout; /* not changing so report back the count and ... */
2613 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2614 cp += sizeof(afs_int32);
2616 strcpy(cp, outname); /* ... the entry, ... */
2617 cp += strlen(outname)+1;
2618 for(count=1; count < foundname; ++count) { /* ... or list. */
2619 /* Note: we don't support @sys lists for exporters */
2620 if (!afs_sysnamelist[count])
2621 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2622 t = strlen(afs_sysnamelist[count]);
2623 if (t >= MAXSYSNAME)
2624 osi_Panic("PSetSysName: sysname entry garbled\n");
2625 strcpy(cp, afs_sysnamelist[count]);
2629 *aoutSize = cp - aout;
2634 /* sequential search through the list of touched cells is not a good
2635 * long-term solution here. For small n, though, it should be just
2636 * fine. Should consider special-casing the local cell for large n.
2637 * Likewise for PSetSPrefs.
2639 * s - number of ids in array l[] -- NOT index of last id
2640 * l - array of cell ids which have volumes that need to be sorted
2641 * vlonly - sort vl servers or file servers?
2643 static void *ReSortCells_cb(struct cell *cell, void *arg)
2645 afs_int32 *p = (afs_int32 *) arg;
2646 afs_int32 *l = p + 1;
2649 for (i=0; i<s; i++) {
2650 if (l[i] == cell->cellNum) {
2651 ObtainWriteLock(&cell->lock, 690);
2652 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2653 ReleaseWriteLock(&cell->lock);
2660 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2668 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2670 memcpy(p+1, l, s * sizeof(afs_int32));
2671 afs_TraverseCells(&ReSortCells_cb, p);
2672 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2676 ObtainReadLock(&afs_xvolume);
2677 for (i= 0; i< NVOLS; i++) {
2678 for (j=afs_volumes[i];j;j=j->next) {
2680 if (j->cell == l[k]) {
2681 ObtainWriteLock(&j->lock,233);
2682 afs_SortServers(j->serverHost, MAXHOSTS);
2683 ReleaseWriteLock(&j->lock);
2688 ReleaseReadLock(&afs_xvolume);
2692 static int debugsetsp = 0;
2693 static int afs_setsprefs(sp, num, vlonly)
2696 unsigned int vlonly;
2699 int i,j,k,matches,touchedSize;
2700 struct server *srvr = NULL;
2701 afs_int32 touched[34];
2705 for (k=0; k < num; sp++, k++) {
2707 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2710 ObtainReadLock(&afs_xserver);
2712 i = SHash(sp->host.s_addr);
2713 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2714 if (sa->sa_ip == sp->host.s_addr) {
2716 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2717 || (sa->sa_portal == AFS_FSPORT);
2718 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2725 if (sa && matches) { /* found one! */
2727 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2729 sa->sa_iprank = sp->rank + afs_randomMod15();
2730 afs_SortOneServer(sa->server);
2733 /* if we don't know yet what cell it's in, this is moot */
2734 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2735 /* is it in our list of touched cells ? */ ;
2736 if (j < 0) { /* no, it's not */
2737 touched[touchedSize++] = srvr->cell->cellNum;
2738 if (touchedSize >= 32) { /* watch for ovrflow */
2739 ReleaseReadLock(&afs_xserver);
2740 ReSortCells(touchedSize, touched, vlonly);
2742 ObtainReadLock(&afs_xserver);
2748 ReleaseReadLock(&afs_xserver);
2749 /* if we didn't find one, start to create one. */
2750 /* Note that it doesn't have a cell yet... */
2752 afs_uint32 temp = sp->host.s_addr;
2753 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2754 WRITE_LOCK, (afsUUID *)0,0);
2755 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2756 afs_PutServer(srvr, WRITE_LOCK);
2758 } /* for all cited preferences */
2760 ReSortCells(touchedSize, touched, vlonly);
2764 /* Note that this may only be performed by the local root user.
2766 DECL_PIOCTL(PSetSPrefs)
2768 struct setspref *ssp;
2769 AFS_STATCNT(PSetSPrefs);
2771 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2772 return EIO; /* Inappropriate ioctl for device */
2774 if (!afs_osi_suser(*acred))
2777 if (ainSize < sizeof(struct setspref))
2780 ssp = (struct setspref *)ain;
2781 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2784 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2785 (ssp->flags & DBservers));
2789 DECL_PIOCTL(PSetSPrefs33)
2792 AFS_STATCNT(PSetSPrefs);
2793 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2794 return EIO; /* Inappropriate ioctl for device */
2797 if (!afs_osi_suser(*acred))
2800 sp = (struct spref *)ain;
2801 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2805 /* some notes on the following code...
2806 * in the hash table of server structs, all servers with the same IP address
2807 * will be on the same overflow chain.
2808 * This could be sped slightly in some circumstances by having it cache the
2809 * immediately previous slot in the hash table and some supporting information
2810 * Only reports file servers now.
2812 DECL_PIOCTL(PGetSPrefs)
2814 struct sprefrequest *spin; /* input */
2815 struct sprefinfo *spout; /* output */
2816 struct spref *srvout; /* one output component */
2817 int i,j; /* counters for hash table traversal */
2818 struct server *srvr; /* one of CM's server structs */
2820 int vlonly; /* just return vlservers ? */
2823 AFS_STATCNT(PGetSPrefs);
2824 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2825 return EIO; /* Inappropriate ioctl for device */
2828 if (ainSize < sizeof (struct sprefrequest_33)) {
2832 spin = ((struct sprefrequest *) ain);
2835 if (ainSize > sizeof (struct sprefrequest_33)) {
2836 vlonly = (spin->flags & DBservers);
2840 /* struct sprefinfo includes 1 server struct... that size gets added
2841 * in during the loop that follows.
2843 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2844 spout = (struct sprefinfo *) aout;
2845 spout->next_offset = spin->offset;
2846 spout->num_servers = 0;
2847 srvout = spout->servers;
2849 ObtainReadLock(&afs_xserver);
2850 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2851 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2852 if (spin->offset > (unsigned short)i) {
2853 continue; /* catch up to where we left off */
2855 spout->next_offset++;
2858 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2859 || (sa->sa_portal == AFS_FSPORT);
2861 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2862 /* only report ranks for vl servers */
2866 srvout->host.s_addr = sa->sa_ip;
2867 srvout->rank = sa->sa_iprank;
2868 *aoutSize += sizeof(struct spref);
2869 spout->num_servers++;
2872 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2873 ReleaseReadLock(&afs_xserver); /* no more room! */
2878 ReleaseReadLock(&afs_xserver);
2880 spout->next_offset = 0; /* start over from the beginning next time */
2884 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2885 int afs_NFSRootOnly = 1;
2886 DECL_PIOCTL(PExportAfs)
2888 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2889 register struct afs_exporter *exporter;
2891 AFS_STATCNT(PExportAfs);
2892 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2893 type = handleValue >> 24;
2898 exporter = exporter_find(type);
2900 export = handleValue & 3;
2901 changestate = handleValue & 0xff;
2902 smounts = (handleValue >> 2) & 3;
2903 pwsync = (handleValue >> 4) & 3;
2904 convmode = (handleValue >> 6) & 3;
2906 changestate = (handleValue >> 16) & 0x1;
2907 convmode = (handleValue >> 16) & 0x2;
2908 pwsync = (handleValue >> 16) & 0x4;
2909 smounts = (handleValue >> 16) & 0x8;
2910 export = handleValue & 0xff;
2913 /* Failed finding desired exporter; */
2917 handleValue = exporter->exp_states;
2918 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2919 *aoutSize = sizeof(afs_int32);
2921 if (!afs_osi_suser(*acred))
2922 return EACCES; /* Only superuser can do this */
2926 exporter->exp_states |= EXP_EXPORTED;
2928 exporter->exp_states &= ~EXP_EXPORTED;
2932 exporter->exp_states |= EXP_UNIXMODE;
2934 exporter->exp_states &= ~EXP_UNIXMODE;
2938 exporter->exp_states |= EXP_PWSYNC;
2940 exporter->exp_states &= ~EXP_PWSYNC;
2944 afs_NFSRootOnly = 0;
2945 exporter->exp_states |= EXP_SUBMOUNTS;
2947 afs_NFSRootOnly = 1;
2948 exporter->exp_states &= ~EXP_SUBMOUNTS;
2951 handleValue = exporter->exp_states;
2952 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2953 *aoutSize = sizeof(afs_int32);
2956 exporter->exp_states |= EXP_EXPORTED;
2958 exporter->exp_states &= ~EXP_EXPORTED;
2960 exporter->exp_states |= EXP_UNIXMODE;
2962 exporter->exp_states &= ~EXP_UNIXMODE;
2964 exporter->exp_states |= EXP_PWSYNC;
2966 exporter->exp_states &= ~EXP_PWSYNC;
2968 afs_NFSRootOnly = 0;
2969 exporter->exp_states |= EXP_SUBMOUNTS;
2971 afs_NFSRootOnly = 1;
2972 exporter->exp_states &= ~EXP_SUBMOUNTS;
2982 struct gaginfo *gagflags;
2984 if (!afs_osi_suser(*acred))
2987 gagflags = (struct gaginfo *) ain;
2988 afs_showflags = gagflags->showflags;
2994 DECL_PIOCTL(PTwiddleRx)
2996 struct rxparams *rxp;
2998 if (!afs_osi_suser(*acred))
3001 rxp = (struct rxparams *) ain;
3003 if (rxp->rx_initReceiveWindow)
3004 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3005 if (rxp->rx_maxReceiveWindow)
3006 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3007 if (rxp->rx_initSendWindow)
3008 rx_initSendWindow = rxp->rx_initSendWindow;
3009 if (rxp->rx_maxSendWindow)
3010 rx_maxSendWindow = rxp->rx_maxSendWindow;
3011 if (rxp->rxi_nSendFrags)
3012 rxi_nSendFrags = rxp->rxi_nSendFrags;
3013 if (rxp->rxi_nRecvFrags)
3014 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3015 if (rxp->rxi_OrphanFragSize)
3016 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3017 if (rxp->rx_maxReceiveSize)
3019 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3020 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3022 if (rxp->rx_MyMaxSendSize)
3023 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3028 DECL_PIOCTL(PGetInitParams)
3030 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3033 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3034 *aoutSize = sizeof(struct cm_initparams);
3038 #ifdef AFS_SGI65_ENV
3039 /* They took crget() from us, so fake it. */
3040 static cred_t *crget(void)
3043 cr = crdup(get_current_cred());
3044 memset((char*)cr, 0, sizeof(cred_t));
3045 #if CELL || CELL_PREPARE
3052 DECL_PIOCTL(PGetRxkcrypt)
3054 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3055 *aoutSize=sizeof(afs_int32);
3059 DECL_PIOCTL(PSetRxkcrypt)
3063 if (!afs_osi_suser(*acred))
3065 if (ainSize != sizeof(afs_int32) || ain == NULL)
3067 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3068 /* if new mappings added later this will need to be changed */
3069 if (tmpval != 0 && tmpval != 1)
3076 * Create new credentials to correspond to a remote user with given
3077 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3078 * provide pioctl (and other) services to foreign clients (i.e. nfs
3079 * clients) by using this call to `become' the client.
3082 #define PIOCTL_HEADER 6
3083 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3085 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3086 return EINVAL; /* NFS trans not supported for Ultrix */
3089 afs_uint32 hostaddr;
3090 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3091 struct afs_exporter *exporter, *outexporter;
3092 struct AFS_UCRED *newcred;
3093 struct unixuser *au;
3095 #if defined(AFS_SGIMP_ENV)
3096 osi_Assert(ISAFS_GLOCK());
3098 AFS_STATCNT(HandleClientContext);
3099 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3100 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3101 return EINVAL; /* Too small to be good */
3103 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3104 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3106 osi_FreeLargeSpace(inData);
3110 /* Extract information for remote user */
3111 hostaddr = *((afs_uint32 *)ain);
3112 ain += sizeof(hostaddr);
3113 uid = *((afs_uint32 *)ain);
3115 g0 = *((afs_uint32 *)ain);
3117 g1 = *((afs_uint32 *)ain);
3119 *com = *((afs_uint32 *)ain);
3120 ain += sizeof(afs_int32);
3121 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3124 * Of course, one must be root for most of these functions, but
3125 * we'll allow (for knfs) you to set things if the pag is 0 and
3126 * you're setting tokens or unlogging.
3129 if (!afs_osi_suser(credp)) {
3131 #ifndef AFS_SGI64_ENV
3132 /* Since SGI's suser() returns explicit failure after the call.. */
3136 /* check for acceptable opcodes for normal folks, which are, so far,
3137 * set tokens and unlog.
3139 if (i != 9 && i != 3 && i != 38 && i != 8) {
3140 osi_FreeLargeSpace(inData);
3145 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3146 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3147 osi_FreeLargeSpace(inData);
3150 * We map uid 0 to nobody to match the mapping that the nfs
3151 * server does and to ensure that the suser() calls in the afs
3152 * code fails for remote client roots.
3154 uid = afs_nobody; /* NFS_NOBODY == -2 */
3157 #ifdef AFS_AIX41_ENV
3160 newcred->cr_gid = RMTUSER_REQ;
3161 #ifdef AFS_AIX51_ENV
3162 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3163 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3165 newcred->cr_groups[0] = g0;
3166 newcred->cr_groups[1] = g1;
3169 newcred->cr_ngrps = 2;
3171 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3172 newcred->cr_ngroups = 2;
3174 for (i=2; i<NGROUPS; i++)
3175 newcred->cr_groups[i] = NOGROUP;
3178 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3179 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3181 if (!(exporter = exporter_find(exporter_type))) {
3182 /* Exporter wasn't initialized or an invalid exporter type */
3186 if (exporter->exp_states & EXP_PWSYNC) {
3187 if (uid != credp->cr_uid) {
3189 return ENOEXEC; /* XXX Find a better errno XXX */
3192 newcred->cr_uid = uid; /* Only temporary */
3193 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3194 /* The client's pag is the only unique identifier for it */
3195 newcred->cr_uid = pag;
3197 if (!code && *com == PSETPAG) {
3198 /* Special case for 'setpag' */
3199 afs_uint32 pagvalue = genpag();
3201 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3203 * Note that we leave the 'outexporter' struct held so it won't
3206 au->exporter = outexporter;
3207 if (ablob->out_size >= 4) {
3208 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3210 afs_PutUser(au, WRITE_LOCK);
3211 if (code) return code;
3212 return PSETPAG; /* Special return for setpag */
3214 EXP_RELE(outexporter);
3217 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3220 /* get all interface addresses of this client */
3222 DECL_PIOCTL(PGetCPrefs)
3224 struct sprefrequest *spin; /* input */
3225 struct sprefinfo *spout; /* output */
3226 struct spref *srvout; /* one output component */
3230 AFS_STATCNT(PGetCPrefs);
3231 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3232 return EIO; /* Inappropriate ioctl for device */
3234 if ( ainSize < sizeof (struct sprefrequest ))
3237 spin = (struct sprefrequest *) ain;
3238 spout = (struct sprefinfo *) aout;
3240 maxNumber = spin->num_servers; /* max addrs this time */
3241 srvout = spout->servers;
3243 ObtainReadLock(&afs_xinterface);
3245 /* copy out the client interface information from the
3246 ** kernel data structure "interface" to the output buffer
3248 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3249 && ( j< maxNumber) ; i++, j++, srvout++)
3250 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3252 spout->num_servers = j;
3253 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3255 if ( i >= afs_cb_interface.numberOfInterfaces )
3256 spout->next_offset = 0; /* start from beginning again */
3258 spout->next_offset = spin->offset + j;
3260 ReleaseReadLock(&afs_xinterface);
3264 DECL_PIOCTL(PSetCPrefs)
3266 struct setspref *sin;
3269 AFS_STATCNT(PSetCPrefs);
3270 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3271 return EIO; /* Inappropriate ioctl for device */
3273 sin = (struct setspref *)ain;
3275 if ( ainSize < sizeof(struct setspref) )
3277 #if 0 /* num_servers is unsigned */
3278 if ( sin->num_servers < 0 )
3281 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3284 ObtainWriteLock(&afs_xinterface, 412);
3285 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3286 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3287 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3289 ReleaseWriteLock(&afs_xinterface);
3293 DECL_PIOCTL(PFlushMount)
3295 register afs_int32 code;
3296 register struct vcache *tvc;
3297 register struct dcache *tdc;
3298 struct VenusFid tfid;
3300 struct sysname_info sysState;
3301 afs_size_t offset, len;
3303 AFS_STATCNT(PFlushMount);
3304 if (!avc) return EINVAL;
3305 code = afs_VerifyVCache(avc, areq);
3306 if (code) return code;
3307 if (vType(avc) != VDIR) {
3310 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3311 if (!tdc) return ENOENT;
3312 Check_AtSys(avc, ain, &sysState, areq);
3313 ObtainReadLock(&tdc->lock);
3315 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3316 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3317 ReleaseReadLock(&tdc->lock);
3318 afs_PutDCache(tdc); /* we're done with the data */
3319 bufp = sysState.name;
3323 tfid.Cell = avc->fid.Cell;
3324 tfid.Fid.Volume = avc->fid.Fid.Volume;
3325 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3326 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3328 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3334 if (tvc->mvstat != 1) {
3339 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3340 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3342 ObtainWriteLock(&tvc->lock,649);
3343 ObtainWriteLock(&afs_xcbhash, 650);
3344 afs_DequeueCallback(tvc);
3345 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3346 ReleaseWriteLock(&afs_xcbhash);
3347 /* now find the disk cache entries */
3348 afs_TryToSmush(tvc, *acred, 1);
3349 osi_dnlc_purgedp(tvc);
3350 afs_symhint_inval(tvc);
3351 if (tvc->linkData && !(tvc->states & CCore)) {
3352 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3353 tvc->linkData = NULL;
3355 ReleaseWriteLock(&tvc->lock);
3356 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3357 afs_BozonUnlock(&tvc->pvnLock, tvc);
3361 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3365 DECL_PIOCTL(PRxStatProc)
3370 if (!afs_osi_suser(*acred)) {
3374 if (ainSize != sizeof(afs_int32)) {
3378 memcpy((char *)&flags, ain, sizeof(afs_int32));
3379 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3383 if (flags & AFSCALL_RXSTATS_ENABLE) {
3384 rx_enableProcessRPCStats();
3386 if (flags & AFSCALL_RXSTATS_DISABLE) {
3387 rx_disableProcessRPCStats();
3389 if (flags & AFSCALL_RXSTATS_CLEAR) {
3390 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3398 DECL_PIOCTL(PRxStatPeer)
3403 if (!afs_osi_suser(*acred)) {
3407 if (ainSize != sizeof(afs_int32)) {
3411 memcpy((char *)&flags, ain, sizeof(afs_int32));
3412 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3416 if (flags & AFSCALL_RXSTATS_ENABLE) {
3417 rx_enablePeerRPCStats();
3419 if (flags & AFSCALL_RXSTATS_DISABLE) {
3420 rx_disablePeerRPCStats();
3422 if (flags & AFSCALL_RXSTATS_CLEAR) {
3423 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3430 DECL_PIOCTL(PPrefetchFromTape)
3432 register afs_int32 code, code1;
3435 struct rx_call *tcall;
3436 struct AFSVolSync tsync;
3437 struct AFSFetchStatus OutStatus;
3438 struct AFSCallBack CallBack;
3439 struct VenusFid tfid;
3443 AFS_STATCNT(PSetAcl);
3447 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3448 Fid = (struct AFSFid *) ain;
3450 Fid = &avc->fid.Fid;
3451 tfid.Cell = avc->fid.Cell;
3452 tfid.Fid.Volume = Fid->Volume;
3453 tfid.Fid.Vnode = Fid->Vnode;
3454 tfid.Fid.Unique = Fid->Unique;
3456 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3458 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3459 ICL_TYPE_POINTER, tvc,
3460 ICL_TYPE_FID, &tfid,
3461 ICL_TYPE_FID, &avc->fid);
3464 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3465 ICL_TYPE_POINTER, tvc,
3466 ICL_TYPE_FID, &tfid,
3467 ICL_TYPE_FID, &tvc->fid);
3470 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3474 tcall = rx_NewCall(tc->id);
3475 code = StartRXAFS_FetchData(tcall,
3476 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3478 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3479 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3481 code1 = rx_EndCall(tcall, code);
3486 (afs_Analyze(tc, code, &tvc->fid, areq,
3487 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3489 /* This call is done only to have the callback things handled correctly */
3490 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3494 *aoutSize = sizeof(afs_int32);
3499 DECL_PIOCTL(PResidencyCmd)
3501 register afs_int32 code;
3504 struct ResidencyCmdInputs *Inputs;
3505 struct ResidencyCmdOutputs *Outputs;
3506 struct VenusFid tfid;
3509 Inputs = (struct ResidencyCmdInputs *) ain;
3510 Outputs = (struct ResidencyCmdOutputs *) aout;
3511 if (!avc) return EINVAL;
3512 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3516 Fid = &avc->fid.Fid;
3518 tfid.Cell = avc->fid.Cell;
3519 tfid.Fid.Volume = Fid->Volume;
3520 tfid.Fid.Vnode = Fid->Vnode;
3521 tfid.Fid.Unique = Fid->Unique;
3523 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3524 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3525 ICL_TYPE_POINTER, tvc,
3526 ICL_TYPE_INT32, Inputs->command,
3527 ICL_TYPE_FID, &tfid);
3531 if (Inputs->command) {
3533 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3536 code = RXAFS_ResidencyCmd(tc->id, Fid,
3538 (struct ResidencyCmdOutputs *) aout);
3543 (afs_Analyze(tc, code, &tvc->fid, areq,
3544 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3546 /* This call is done to have the callback things handled correctly */
3547 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3548 } else { /* just a status request, return also link data */
3550 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3551 Outputs->chars[0] = 0;
3552 if (vType(tvc) == VLNK) {
3553 ObtainWriteLock(&tvc->lock,555);
3554 if (afs_HandleLink(tvc, areq) == 0)
3555 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3556 ReleaseWriteLock(&tvc->lock);
3563 *aoutSize = sizeof(struct ResidencyCmdOutputs);