2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "../afs/param.h"
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* afs statistics */
18 #include "../afs/vice.h"
19 #include "../rx/rx_globals.h"
21 struct VenusFid afs_rootFid;
22 afs_int32 afs_waitForever=0;
23 short afs_waitForeverCount = 0;
24 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
26 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
27 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
28 struct AFS_UCRED **acred)
30 /* Prototypes for pioctl routines */
33 DECL_PIOCTL(PStoreBehind);
38 DECL_PIOCTL(PGetFileCell);
39 DECL_PIOCTL(PGetWSCell);
40 DECL_PIOCTL(PGetUserCell);
41 DECL_PIOCTL(PSetTokens);
42 DECL_PIOCTL(PGetVolumeStatus);
43 DECL_PIOCTL(PSetVolumeStatus);
45 DECL_PIOCTL(PNewStatMount);
46 DECL_PIOCTL(PGetTokens);
48 DECL_PIOCTL(PMariner);
49 DECL_PIOCTL(PCheckServers);
50 DECL_PIOCTL(PCheckVolNames);
51 DECL_PIOCTL(PCheckAuth);
52 DECL_PIOCTL(PFindVolume);
53 DECL_PIOCTL(PViceAccess);
54 DECL_PIOCTL(PSetCacheSize);
55 DECL_PIOCTL(PGetCacheSize);
56 DECL_PIOCTL(PRemoveCallBack);
57 DECL_PIOCTL(PNewCell);
58 DECL_PIOCTL(PNewAlias);
59 DECL_PIOCTL(PListCells);
60 DECL_PIOCTL(PListAliases);
61 DECL_PIOCTL(PRemoveMount);
62 DECL_PIOCTL(PVenusLogging);
63 DECL_PIOCTL(PGetCellStatus);
64 DECL_PIOCTL(PSetCellStatus);
65 DECL_PIOCTL(PFlushVolumeData);
66 DECL_PIOCTL(PGetVnodeXStatus);
67 DECL_PIOCTL(PSetSysName);
68 DECL_PIOCTL(PSetSPrefs);
69 DECL_PIOCTL(PSetSPrefs33);
70 DECL_PIOCTL(PGetSPrefs);
71 DECL_PIOCTL(PExportAfs);
73 DECL_PIOCTL(PTwiddleRx);
74 DECL_PIOCTL(PGetInitParams);
75 DECL_PIOCTL(PGetRxkcrypt);
76 DECL_PIOCTL(PSetRxkcrypt);
77 DECL_PIOCTL(PGetCPrefs);
78 DECL_PIOCTL(PSetCPrefs);
79 DECL_PIOCTL(PFlushMount);
80 DECL_PIOCTL(PRxStatProc);
81 DECL_PIOCTL(PRxStatPeer);
82 DECL_PIOCTL(PPrefetchFromTape);
83 DECL_PIOCTL(PResidencyCmd);
85 /* Prototypes for private routines */
86 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
87 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
88 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
89 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
90 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
91 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
94 static int (*(VpioctlSw[]))() = {
99 PGetVolumeStatus, /* 4 */
100 PSetVolumeStatus, /* 5 */
105 PCheckServers, /* 10 */
106 PCheckVolNames, /* 11 */
108 PBogus, /* 13 -- used to be quick check time */
110 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
111 PBogus, /* 16 -- used to be testing code */
112 PNoop, /* 17 -- used to be enable group */
113 PNoop, /* 18 -- used to be disable group */
114 PBogus, /* 19 -- used to be list group */
115 PViceAccess, /* 20 */
116 PUnlog, /* 21 -- unlog *is* unpag in this system */
117 PGetFID, /* 22 -- get file ID */
118 PBogus, /* 23 -- used to be waitforever */
119 PSetCacheSize, /* 24 */
120 PRemoveCallBack, /* 25 -- flush only the callback */
123 PRemoveMount, /* 28 -- delete mount point */
124 PNewStatMount, /* 29 -- new style mount point stat */
125 PGetFileCell, /* 30 -- get cell name for input file */
126 PGetWSCell, /* 31 -- get cell name for workstation */
127 PMariner, /* 32 - set/get mariner host */
128 PGetUserCell, /* 33 -- get cell name for user */
129 PVenusLogging, /* 34 -- Enable/Disable logging */
130 PGetCellStatus, /* 35 */
131 PSetCellStatus, /* 36 */
132 PFlushVolumeData, /* 37 -- flush all data from a volume */
133 PSetSysName, /* 38 - Set system name */
134 PExportAfs, /* 39 - Export Afs to remote nfs clients */
135 PGetCacheSize, /* 40 - get cache size and usage */
136 PGetVnodeXStatus, /* 41 - get vcache's special status */
137 PSetSPrefs33, /* 42 - Set CM Server preferences... */
138 PGetSPrefs, /* 43 - Get CM Server preferences... */
139 PGag, /* 44 - turn off/on all CM messages */
140 PTwiddleRx, /* 45 - adjust some RX params */
141 PSetSPrefs, /* 46 - Set CM Server preferences... */
142 PStoreBehind, /* 47 - set degree of store behind to be done */
143 PGCPAGs, /* 48 - disable automatic pag gc-ing */
144 PGetInitParams, /* 49 - get initial cm params */
145 PGetCPrefs, /* 50 - get client interface addresses */
146 PSetCPrefs, /* 51 - set client interface addresses */
147 PFlushMount, /* 52 - flush mount symlink data */
148 PRxStatProc, /* 53 - control process RX statistics */
149 PRxStatPeer, /* 54 - control peer RX statistics */
150 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
151 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
152 PBogus, /* 57 -- arla: set file prio */
153 PBogus, /* 58 -- arla: fallback getfh */
154 PBogus, /* 59 -- arla: fallback fhopen */
155 PBogus, /* 60 -- arla: controls xfsdebug */
156 PBogus, /* 61 -- arla: controls arla debug */
157 PBogus, /* 62 -- arla: debug interface */
158 PBogus, /* 63 -- arla: print xfs status */
159 PBogus, /* 64 -- arla: force cache check */
160 PBogus, /* 65 -- arla: break callback */
161 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
162 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
163 PBogus, /* 68 -- arla: fetch stats */
166 static int (*(CpioctlSw[]))() = {
168 PNewAlias, /* 1 -- create new cell alias */
169 PListAliases, /* 2 -- list cell aliases */
172 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
173 int afs_nobody = NFS_NOBODY;
176 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
178 dst->in = (char *)(unsigned long)src->in;
179 dst->out = (char *)(unsigned long)src->out;
180 dst->in_size = src->in_size;
181 dst->out_size = src->out_size;
185 * If you need to change copyin_afs_ioctl(), you may also need to change
190 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
194 #if defined(AFS_HPUX_64BIT_ENV)
195 struct afs_ioctl32 dst32;
197 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
199 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
201 afs_ioctl32_to_afs_ioctl(&dst32, dst);
204 #endif /* defined(AFS_HPUX_64BIT_ENV) */
206 #if defined(AFS_SUN57_64BIT_ENV)
207 struct afs_ioctl32 dst32;
209 if (get_udatamodel() == DATAMODEL_ILP32) {
210 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
212 afs_ioctl32_to_afs_ioctl(&dst32, dst);
215 #endif /* defined(AFS_SUN57_64BIT_ENV) */
217 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
218 struct afs_ioctl32 dst32;
220 if (!ABI_IS_64BIT(get_current_abi()))
222 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
224 afs_ioctl32_to_afs_ioctl(&dst32, dst);
227 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
229 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
230 struct afs_ioctl32 dst32;
232 #ifdef AFS_SPARC64_LINUX24_ENV
233 if (current->thread.flags & SPARC_FLAG_32BIT)
234 #elif AFS_SPARC64_LINUX20_ENV
235 if (current->tss.flags & SPARC_FLAG_32BIT)
237 #error Not done for this linux type
238 #endif /* AFS_SPARC64_LINUX20_ENV */
240 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
242 afs_ioctl32_to_afs_ioctl(&dst32, dst);
245 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
247 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
251 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
253 register afs_int32 code;
256 AFS_STATCNT(HandleIoctl);
258 switch(acom & 0xff) {
260 avc->states |= CSafeStore;
264 /* case 2 used to be abort store, but this is no longer provided,
265 since it is impossible to implement under normal Unix.
269 /* return the name of the cell this file is open on */
270 register struct cell *tcell;
271 register afs_int32 i;
273 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
275 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
277 if (i > adata->out_size) {
278 /* 0 means we're not interested in the output */
279 if (adata->out_size != 0) code = EFAULT;
283 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
285 afs_PutCell(tcell, READ_LOCK);
291 case 49: /* VIOC_GETINITPARAMS */
292 if (adata->out_size < sizeof(struct cm_initparams)) {
296 AFS_COPYOUT(&cm_initParams, adata->out,
297 sizeof(struct cm_initparams), code);
306 return code; /* so far, none implemented */
311 /* For aix we don't temporarily bypass ioctl(2) but rather do our
312 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
313 * is now called from afs_gn_ioctl.
315 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
317 struct afs_ioctl data;
320 AFS_STATCNT(afs_ioctl);
321 if (((cmd >> 8) & 0xff) == 'V') {
322 /* This is a VICEIOCTL call */
323 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
326 error = HandleIoctl(tvc, cmd, &data);
329 /* No-op call; just return. */
333 #endif /* AFS_AIX_ENV */
335 #if defined(AFS_SGI_ENV)
336 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
342 struct afs_ioctl data;
348 AFS_STATCNT(afs_ioctl);
349 if (((cmd >> 8) & 0xff) == 'V') {
350 /* This is a VICEIOCTL call */
351 error = copyin_afs_ioctl(arg, &data);
354 locked = ISAFS_GLOCK();
357 error = HandleIoctl(tvc, cmd, &data);
362 /* No-op call; just return. */
366 #endif /* AFS_SGI_ENV */
369 /* unlike most calls here, this one uses u.u_error to return error conditions,
370 since this is really an intercepted chapter 2 call, rather than a vnode
373 /* AFS_HPUX102 and up uses VNODE ioctl instead */
374 #ifndef AFS_HPUX102_ENV
375 #if !defined(AFS_SGI_ENV)
377 kioctl(fdes, com, arg, ext)
384 } u_uap, *uap = &u_uap;
388 struct afs_ioctl_sys {
394 afs_xioctl (uap, rvp)
395 struct afs_ioctl_sys *uap;
400 afs_xioctl (p, args, retval)
409 } *uap = (struct a *)args;
410 #else /* AFS_OSF_ENV */
411 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
417 afs_xioctl(p, uap, retval)
419 register struct ioctl_args *uap;
423 #ifdef AFS_LINUX22_ENV
424 struct afs_ioctl_sys {
428 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
429 unsigned int com, unsigned long arg)
431 struct afs_ioctl_sys ua, *uap = &ua;
433 int afs_xioctl (void)
439 } *uap = (struct a *)u.u_ap;
440 #endif /* AFS_LINUX22_ENV */
441 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
442 #endif /* AFS_OSF_ENV */
443 #endif /* AFS_SUN5_ENV */
445 #ifndef AFS_LINUX22_ENV
446 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
449 register struct file *fd;
452 #if defined(AFS_FBSD_ENV)
453 register struct filedesc *fdp;
455 register struct vcache *tvc;
456 register int ioctlDone = 0, code = 0;
458 AFS_STATCNT(afs_xioctl);
459 #if defined(AFS_FBSD_ENV)
461 if ((u_int)uap->fd >= fdp->fd_nfiles ||
462 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
464 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
467 #if defined(AFS_DARWIN_ENV)
468 if ((code=fdgetf(p, uap->fd, &fd)))
471 #ifdef AFS_LINUX22_ENV
479 if (setuerror(getf(uap->fd, &fd))) {
485 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
487 #else /* AFS_OSF_ENV */
489 #if defined(AFS_SUN57_ENV)
491 if (!fd) return(EBADF);
492 #elif defined(AFS_SUN54_ENV)
494 if (!fd) return(EBADF);
496 if (code = getf(uap->fd, &fd)) {
509 /* first determine whether this is any sort of vnode */
510 #ifdef AFS_LINUX22_ENV
515 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
517 if (fd->f_type == DTYPE_VNODE) {
519 /* good, this is a vnode; next see if it is an AFS vnode */
520 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
521 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
523 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
525 #endif /* AFS_LINUX22_ENV */
526 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
528 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
529 if (!tvc) { /* shouldn't happen with held gnodes */
534 /* This is an AFS vnode */
535 if (((uap->com >> 8) & 0xff) == 'V') {
536 register struct afs_ioctl *datap;
538 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
539 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
541 osi_FreeSmallSpace(datap);
543 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
546 #if defined(AFS_SUN5_ENV)
561 #else /* AFS_OSF_ENV */
565 #ifdef AFS_LINUX22_ENV
575 code = HandleIoctl(tvc, uap->com, datap);
576 osi_FreeSmallSpace(datap);
590 #if defined(AFS_LINUX22_ENV)
600 code = okioctl(fdes, com, arg, ext);
604 okioctl(fdes, com, arg, ext);
606 #if defined(AFS_SUN5_ENV)
607 #if defined(AFS_SUN57_ENV)
609 #elif defined(AFS_SUN54_ENV)
614 code = ioctl(uap, rvp);
616 #if defined(AFS_FBSD_ENV)
617 return ioctl(p, uap);
619 #if defined(AFS_DARWIN_ENV)
620 return ioctl(p, uap, retval);
623 code = ioctl(p, args, retval);
630 #else /* AFS_OSF_ENV */
631 #ifndef AFS_LINUX22_ENV
650 #ifdef AFS_LINUX22_ENV
653 #if defined(KERNEL_HAVE_SETUERROR)
656 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
657 return (getuerror() ? -1 : u.u_ioctlrv);
659 return getuerror() ? -1 : 0;
662 #endif /* AFS_LINUX22_ENV */
663 #endif /* AFS_SUN5_ENV */
664 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
668 #endif /* AFS_SGI_ENV */
669 #endif /* AFS_HPUX102_ENV */
671 #if defined(AFS_SGI_ENV)
672 /* "pioctl" system call entry point; just pass argument to the parameterized
681 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
685 AFS_STATCNT(afs_pioctl);
687 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
695 #endif /* AFS_SGI_ENV */
698 afs_pioctl(p, args, retval)
708 } *uap = (struct a *) args;
710 AFS_STATCNT(afs_pioctl);
711 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
714 #else /* AFS_OSF_ENV */
715 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
716 afs_pioctl(p, args, retval)
726 } *uap = (struct a *) args;
728 AFS_STATCNT(afs_pioctl);
729 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
732 #else /* AFS_OSF_ENV */
736 /* macro to avoid adding any more #ifdef's to pioctl code. */
737 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
738 #define PIOCTL_FREE_CRED() crfree(credp)
740 #define PIOCTL_FREE_CRED()
744 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
746 struct AFS_UCRED *credp;
748 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
749 afs_syscall_pioctl(path, com, cmarg, follow, credp)
750 struct AFS_UCRED *credp;
752 afs_syscall_pioctl(path, com, cmarg, follow)
760 struct afs_ioctl data;
761 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
762 register afs_int32 code = 0;
768 struct ucred *credp = crref(); /* don't free until done! */
770 #ifdef AFS_LINUX22_ENV
771 cred_t *credp = crref(); /* don't free until done! */
775 AFS_STATCNT(afs_syscall_pioctl);
776 if (follow) follow = 1; /* compat. with old venus */
777 code = copyin_afs_ioctl(cmarg, &data);
780 #if defined(KERNEL_HAVE_SETUERROR)
785 if ((com & 0xff) == PSetClientContext) {
786 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
787 return EINVAL; /* Not handling these yet. */
789 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
790 code = HandleClientContext(&data, &com, &foreigncreds, credp);
792 #if defined(AFS_HPUX101_ENV)
793 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
796 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
798 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
799 #endif /* AFS_SGI_ENV */
805 crfree(foreigncreds);
808 #if defined(KERNEL_HAVE_SETUERROR)
809 return (setuerror(code), code);
815 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
818 * We could have done without temporary setting the u.u_cred below
819 * (foreigncreds could be passed as param the pioctl modules)
820 * but calls such as afs_osi_suser() doesn't allow that since it
821 * references u.u_cred directly. We could, of course, do something
822 * like afs_osi_suser(cred) which, I think, is better since it
823 * generalizes and supports multi cred environments...
827 credp = foreigncreds;
830 tmpcred = crref(); /* XXX */
833 #if defined(AFS_HPUX101_ENV)
834 tmpcred = p_cred(u.u_procp);
835 set_p_cred(u.u_procp, foreigncreds);
838 tmpcred = OSI_GET_CURRENT_CRED();
839 OSI_SET_CURRENT_CRED(foreigncreds);
842 u.u_cred = foreigncreds;
843 #endif /* AFS_SGI64_ENV */
844 #endif /* AFS_HPUX101_ENV */
849 if ((com & 0xff) == 15) {
850 /* special case prefetch so entire pathname eval occurs in helper process.
851 otherwise, the pioctl call is essentially useless */
852 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
853 code = Prefetch(path, &data, follow,
854 foreigncreds ? foreigncreds : credp);
856 #if defined(AFS_HPUX101_ENV)
857 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
860 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
862 code = Prefetch(path, &data, follow, u.u_cred);
863 #endif /* AFS_SGI64_ENV */
864 #endif /* AFS_HPUX101_ENV */
866 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
869 crset(tmpcred); /* restore original credentials */
871 #if defined(AFS_HPUX101_ENV)
872 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
876 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
878 u.u_cred = tmpcred; /* restore original credentials */
881 #endif /* AFS_HPUX101_ENV */
882 crfree(foreigncreds);
885 #endif /* AFS_LINUX22_ENV */
887 #if defined(KERNEL_HAVE_SETUERROR)
888 return (setuerror(code), code);
896 code = lookupname(path, USR, follow, NULL, &vp,
897 foreigncreds ? foreigncreds : credp);
899 #ifdef AFS_LINUX22_ENV
900 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
902 vp = (struct vnode *)dp->d_inode;
904 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
905 #endif /* AFS_LINUX22_ENV */
906 #endif /* AFS_AIX41_ENV */
909 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
912 crset(tmpcred); /* restore original credentials */
914 #if defined(AFS_HPUX101_ENV)
915 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
917 #if !defined(AFS_SUN5_ENV)
919 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
921 u.u_cred = tmpcred; /* restore original credentials */
922 #endif /* AFS_SGI64_ENV */
924 #endif /* AFS_HPUX101_ENV */
925 crfree(foreigncreds);
928 #endif /* AFS_LINUX22_ENV */
930 #if defined(KERNEL_HAVE_SETUERROR)
931 return(setuerror(code), code);
939 /* now make the call if we were passed no file, or were passed an AFS file */
940 if (!vp || IsAfsVnode(vp)) {
942 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
943 * So, we must test in this part of the code. Also, must arrange to
944 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
945 * we hold gnodes, whose references hold our vcache entries.
948 gp = vp; /* remember for "put" */
949 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
954 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
958 struct ucred *cred1, *cred2;
961 cred1 = cred2 = foreigncreds;
963 cred1 = cred2 = credp;
965 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
966 if (cred1 != cred2) {
967 /* something changed the creds */
972 #if defined(AFS_HPUX101_ENV)
974 struct ucred *cred = p_cred(u.u_procp);
975 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
981 credp = OSI_GET_CURRENT_CRED();
982 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
985 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
986 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
988 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
990 #endif /* AFS_SGI_ENV */
991 #endif /* AFS_HPUX101_ENV */
992 #endif /* AFS_AIX41_ENV */
993 #endif /* AFS_SUN5_ENV */
995 #if defined(KERNEL_HAVE_SETUERROR)
998 code = EINVAL; /* not in /afs */
1008 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
1010 #ifdef AFS_AIX41_ENV
1013 #if defined(AFS_HPUX101_ENV)
1014 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1016 #ifndef AFS_SUN5_ENV
1018 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1020 u.u_cred = tmpcred; /* restore original credentials */
1021 #endif /* ASF_SGI64_ENV */
1023 #endif /* AFS_HPUX101_ENV */
1024 crfree(foreigncreds);
1027 #endif /* AFS_LINUX22_ENV */
1029 #ifdef AFS_LINUX22_ENV
1032 AFS_RELE(vp); /* put vnode back */
1036 #if defined(KERNEL_HAVE_SETUERROR)
1039 return (getuerror());
1046 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1047 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1049 struct vrequest treq;
1050 register afs_int32 code;
1051 register afs_int32 function, device;
1052 afs_int32 inSize, outSize;
1053 char *inData, *outData;
1054 int (*(*pioctlSw))();
1056 struct afs_fakestat_state fakestate;
1058 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1059 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1060 AFS_STATCNT(HandlePioctl);
1061 if ((code = afs_InitReq(&treq, *acred))) return code;
1062 afs_InitFakeStat(&fakestate);
1064 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1066 afs_PutFakeStat(&fakestate);
1070 device = (acom & 0xff00) >> 8;
1072 case 'V': /* Original pioctl's */
1073 pioctlSw = VpioctlSw;
1074 pioctlSwSize = sizeof(VpioctlSw);
1076 case 'C': /* Coordinated/common pioctl's */
1077 pioctlSw = CpioctlSw;
1078 pioctlSwSize = sizeof(CpioctlSw);
1081 afs_PutFakeStat(&fakestate);
1084 function = acom & 0xff;
1085 if (function >= (pioctlSwSize / sizeof(char *))) {
1086 afs_PutFakeStat(&fakestate);
1087 return EINVAL; /* out of range */
1089 inSize = ablob->in_size;
1090 if (inSize >= PIGGYSIZE) return E2BIG;
1091 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1093 AFS_COPYIN(ablob->in, inData, inSize, code);
1094 inData[inSize]='\0';
1098 osi_FreeLargeSpace(inData);
1099 afs_PutFakeStat(&fakestate);
1102 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1104 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1105 osi_FreeLargeSpace(inData);
1106 if (code == 0 && ablob->out_size > 0) {
1107 if (outSize > ablob->out_size) outSize = ablob->out_size;
1108 if (outSize >= PIGGYSIZE) code = E2BIG;
1110 outData[outSize]='\0';
1111 AFS_COPYOUT(outData, ablob->out, outSize, code);
1114 osi_FreeLargeSpace(outData);
1115 afs_PutFakeStat(&fakestate);
1116 return afs_CheckCode(code, &treq, 41);
1119 DECL_PIOCTL(PGetFID)
1121 register afs_int32 code;
1123 AFS_STATCNT(PGetFID);
1124 if (!avc) return EINVAL;
1125 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1126 *aoutSize = sizeof(struct VenusFid);
1130 DECL_PIOCTL(PSetAcl)
1132 register afs_int32 code;
1134 struct AFSOpaque acl;
1135 struct AFSVolSync tsync;
1136 struct AFSFetchStatus OutStatus;
1139 AFS_STATCNT(PSetAcl);
1142 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1145 acl.AFSOpaque_val = ain;
1147 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1149 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1151 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1152 &acl, &OutStatus, &tsync);
1158 (afs_Analyze(tconn, code, &avc->fid, areq,
1159 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1161 /* now we've forgotten all of the access info */
1162 ObtainWriteLock(&afs_xcbhash, 455);
1164 afs_DequeueCallback(avc);
1165 avc->states &= ~(CStatd | CUnique);
1166 ReleaseWriteLock(&afs_xcbhash);
1167 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1168 osi_dnlc_purgedp(avc);
1172 int afs_defaultAsynchrony = 0;
1174 DECL_PIOCTL(PStoreBehind)
1177 struct sbstruct *sbr;
1179 sbr = (struct sbstruct *)ain;
1180 if (sbr->sb_default != -1) {
1181 if (afs_osi_suser(*acred))
1182 afs_defaultAsynchrony = sbr->sb_default;
1186 if (avc && (sbr->sb_thisfile != -1)) {
1187 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1188 areq, DONT_CHECK_MODE_BITS))
1189 avc->asynchrony = sbr->sb_thisfile;
1193 *aoutSize = sizeof(struct sbstruct);
1194 sbr = (struct sbstruct *)aout;
1195 sbr->sb_default = afs_defaultAsynchrony;
1197 sbr->sb_thisfile = avc->asynchrony;
1203 DECL_PIOCTL(PGCPAGs)
1205 if (!afs_osi_suser(*acred)) {
1208 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1212 DECL_PIOCTL(PGetAcl)
1214 struct AFSOpaque acl;
1215 struct AFSVolSync tsync;
1216 struct AFSFetchStatus OutStatus;
1222 AFS_STATCNT(PGetAcl);
1223 if (!avc) return EINVAL;
1224 Fid.Volume = avc->fid.Fid.Volume;
1225 Fid.Vnode = avc->fid.Fid.Vnode;
1226 Fid.Unique = avc->fid.Fid.Unique;
1227 if (avc->states & CForeign) {
1229 * For a dfs xlator acl we have a special hack so that the
1230 * xlator will distinguish which type of acl will return. So
1231 * we currently use the top 2-bytes (vals 0-4) to tell which
1232 * type of acl to bring back. Horrible hack but this will
1233 * cause the least number of changes to code size and interfaces.
1235 if (Fid.Vnode & 0xc0000000)
1237 Fid.Vnode |= (ainSize << 30);
1239 acl.AFSOpaque_val = aout;
1241 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1244 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1246 code = RXAFS_FetchACL(tconn->id, &Fid,
1247 &acl, &OutStatus, &tsync);
1253 (afs_Analyze(tconn, code, &avc->fid, areq,
1254 AFS_STATS_FS_RPCIDX_FETCHACL,
1255 SHARED_LOCK, NULL));
1258 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1271 AFS_STATCNT(PBogus);
1275 DECL_PIOCTL(PGetFileCell)
1277 register struct cell *tcell;
1279 AFS_STATCNT(PGetFileCell);
1280 if (!avc) return EINVAL;
1281 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1282 if (!tcell) return ESRCH;
1283 strcpy(aout, tcell->cellName);
1284 afs_PutCell(tcell, READ_LOCK);
1285 *aoutSize = strlen(aout) + 1;
1289 DECL_PIOCTL(PGetWSCell)
1291 struct cell *tcell = NULL;
1293 AFS_STATCNT(PGetWSCell);
1294 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1295 return EIO; /* Inappropriate ioctl for device */
1297 tcell = afs_GetPrimaryCell(READ_LOCK);
1298 if (!tcell) /* no primary cell? */
1300 strcpy(aout, tcell->cellName);
1301 *aoutSize = strlen(aout) + 1;
1302 afs_PutCell(tcell, READ_LOCK);
1306 DECL_PIOCTL(PGetUserCell)
1308 register afs_int32 i;
1309 register struct unixuser *tu;
1310 register struct cell *tcell;
1312 AFS_STATCNT(PGetUserCell);
1313 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1314 return EIO; /* Inappropriate ioctl for device */
1316 /* return the cell name of the primary cell for this user */
1317 i = UHash(areq->uid);
1318 ObtainWriteLock(&afs_xuser,224);
1319 for(tu = afs_users[i]; tu; tu = tu->next) {
1320 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1322 ReleaseWriteLock(&afs_xuser);
1327 tcell = afs_GetCell(tu->cell, READ_LOCK);
1328 afs_PutUser(tu, WRITE_LOCK);
1329 if (!tcell) return ESRCH;
1331 strcpy(aout, tcell->cellName);
1332 afs_PutCell(tcell, READ_LOCK);
1333 *aoutSize = strlen(aout)+1; /* 1 for the null */
1337 ReleaseWriteLock(&afs_xuser);
1344 DECL_PIOCTL(PSetTokens)
1347 register struct unixuser *tu;
1348 struct ClearToken clear;
1349 register struct cell *tcell;
1352 struct vrequest treq;
1353 afs_int32 flag, set_parent_pag = 0;
1355 AFS_STATCNT(PSetTokens);
1356 if (!afs_resourceinit_flag) {
1359 memcpy((char *)&i, ain, sizeof(afs_int32));
1360 ain += sizeof(afs_int32);
1361 stp = ain; /* remember where the ticket is */
1362 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1364 ain += i; /* skip over ticket */
1365 memcpy((char *)&i, ain, sizeof(afs_int32));
1366 ain += sizeof(afs_int32);
1367 if (i != sizeof(struct ClearToken)) {
1370 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1371 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1372 ain += sizeof(struct ClearToken);
1373 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1374 /* still stuff left? we've got primary flag and cell name. Set these */
1375 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1376 ain += sizeof(afs_int32); /* skip id field */
1377 /* rest is cell name, look it up */
1378 /* some versions of gcc appear to need != 0 in order to get this right */
1379 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1383 tcell = afs_GetCellByName(ain, READ_LOCK);
1384 if (!tcell) goto nocell;
1387 /* default to primary cell, primary id */
1388 flag = 1; /* primary id */
1389 tcell = afs_GetPrimaryCell(READ_LOCK);
1390 if (!tcell) goto nocell;
1393 afs_PutCell(tcell, READ_LOCK);
1394 if (set_parent_pag) {
1396 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1397 #if defined(AFS_DARWIN_ENV)
1398 struct proc *p=current_proc(); /* XXX */
1400 struct proc *p=curproc; /* XXX */
1402 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1403 p->p_pid, p->p_comm);
1404 if (!setpag(p, acred, -1, &pag, 1)) {
1407 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1409 if (!setpag(acred, -1, &pag, 1)) {
1412 afs_InitReq(&treq, *acred);
1416 /* now we just set the tokens */
1417 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1418 tu->vid = clear.ViceId;
1419 if (tu->stp != NULL) {
1420 afs_osi_Free(tu->stp, tu->stLen);
1422 tu->stp = (char *) afs_osi_Alloc(stLen);
1424 memcpy(tu->stp, stp, stLen);
1427 afs_stats_cmfullperf.authent.TicketUpdates++;
1428 afs_ComputePAGStats();
1429 #endif /* AFS_NOSTATS */
1430 tu->states |= UHasTokens;
1431 tu->states &= ~UTokensBad;
1432 afs_SetPrimary(tu, flag);
1433 tu->tokenTime =osi_Time();
1434 afs_ResetUserConns(tu);
1435 afs_PutUser(tu, WRITE_LOCK);
1450 DECL_PIOCTL(PGetVolumeStatus)
1453 char offLineMsg[256];
1455 register struct conn *tc;
1456 register afs_int32 code;
1457 struct VolumeStatus volstat;
1459 char *Name, *OfflineMsg, *MOTD;
1462 AFS_STATCNT(PGetVolumeStatus);
1463 if (!avc) return EINVAL;
1465 OfflineMsg = offLineMsg;
1468 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1470 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1472 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1473 &Name, &OfflineMsg, &MOTD);
1479 (afs_Analyze(tc, code, &avc->fid, areq,
1480 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1481 SHARED_LOCK, NULL));
1483 if (code) return code;
1484 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1486 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1487 cp += sizeof(VolumeStatus);
1488 strcpy(cp, volName);
1489 cp += strlen(volName)+1;
1490 strcpy(cp, offLineMsg);
1491 cp += strlen(offLineMsg)+1;
1493 cp += strlen(motd)+1;
1494 *aoutSize = (cp - aout);
1498 DECL_PIOCTL(PSetVolumeStatus)
1501 char offLineMsg[256];
1503 register struct conn *tc;
1504 register afs_int32 code;
1505 struct AFSFetchVolumeStatus volstat;
1506 struct AFSStoreVolumeStatus storeStat;
1507 register struct volume *tvp;
1511 AFS_STATCNT(PSetVolumeStatus);
1512 if (!avc) return EINVAL;
1514 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1516 if (tvp->states & (VRO | VBackup)) {
1517 afs_PutVolume(tvp, READ_LOCK);
1520 afs_PutVolume(tvp, READ_LOCK);
1523 /* Copy the junk out, using cp as a roving pointer. */
1525 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1526 cp += sizeof(AFSFetchVolumeStatus);
1527 if (strlen(cp) >= sizeof(volName))
1529 strcpy(volName, cp);
1530 cp += strlen(volName)+1;
1531 if (strlen(cp) >= sizeof(offLineMsg))
1533 strcpy(offLineMsg, cp);
1534 cp += strlen(offLineMsg)+1;
1535 if (strlen(cp) >= sizeof(motd))
1539 if (volstat.MinQuota != -1) {
1540 storeStat.MinQuota = volstat.MinQuota;
1541 storeStat.Mask |= AFS_SETMINQUOTA;
1543 if (volstat.MaxQuota != -1) {
1544 storeStat.MaxQuota = volstat.MaxQuota;
1545 storeStat.Mask |= AFS_SETMAXQUOTA;
1548 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1550 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1552 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1553 &storeStat, volName, offLineMsg, motd);
1559 (afs_Analyze(tc, code, &avc->fid, areq,
1560 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1561 SHARED_LOCK, NULL));
1563 if (code) return code;
1564 /* we are sending parms back to make compat. with prev system. should
1565 change interface later to not ask for current status, just set new status */
1567 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1568 cp += sizeof(VolumeStatus);
1569 strcpy(cp, volName);
1570 cp += strlen(volName)+1;
1571 strcpy(cp, offLineMsg);
1572 cp += strlen(offLineMsg)+1;
1574 cp += strlen(motd)+1;
1575 *aoutSize = cp - aout;
1581 AFS_STATCNT(PFlush);
1582 if (!avc) return EINVAL;
1583 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1584 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1586 ObtainWriteLock(&avc->lock,225);
1587 ObtainWriteLock(&afs_xcbhash, 456);
1588 afs_DequeueCallback(avc);
1589 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1590 ReleaseWriteLock(&afs_xcbhash);
1591 /* now find the disk cache entries */
1592 afs_TryToSmush(avc, *acred, 1);
1593 osi_dnlc_purgedp(avc);
1594 afs_symhint_inval(avc);
1595 if (avc->linkData && !(avc->states & CCore)) {
1596 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1597 avc->linkData = NULL;
1599 ReleaseWriteLock(&avc->lock);
1600 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1601 afs_BozonUnlock(&avc->pvnLock, avc);
1606 DECL_PIOCTL(PNewStatMount)
1608 register afs_int32 code;
1609 register struct vcache *tvc;
1610 register struct dcache *tdc;
1611 struct VenusFid tfid;
1613 struct sysname_info sysState;
1614 afs_size_t offset, len;
1616 AFS_STATCNT(PNewStatMount);
1617 if (!avc) return EINVAL;
1618 code = afs_VerifyVCache(avc, areq);
1619 if (code) return code;
1620 if (vType(avc) != VDIR) {
1623 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1624 if (!tdc) return ENOENT;
1625 Check_AtSys(avc, ain, &sysState, areq);
1626 ObtainReadLock(&tdc->lock);
1628 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1629 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1630 ReleaseReadLock(&tdc->lock);
1631 afs_PutDCache(tdc); /* we're done with the data */
1632 bufp = sysState.name;
1636 tfid.Cell = avc->fid.Cell;
1637 tfid.Fid.Volume = avc->fid.Fid.Volume;
1638 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1639 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1641 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1647 if (tvc->mvstat != 1) {
1652 ObtainWriteLock(&tvc->lock,226);
1653 code = afs_HandleLink(tvc, areq);
1655 if (tvc->linkData) {
1656 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1659 /* we have the data */
1660 strcpy(aout, tvc->linkData);
1661 *aoutSize = strlen(tvc->linkData)+1;
1666 ReleaseWriteLock(&tvc->lock);
1669 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1673 DECL_PIOCTL(PGetTokens)
1675 register struct cell *tcell;
1676 register afs_int32 i;
1677 register struct unixuser *tu;
1682 AFS_STATCNT(PGetTokens);
1683 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1684 return EIO; /* Inappropriate ioctl for device */
1686 /* weird interface. If input parameter is present, it is an integer and
1687 we're supposed to return the parm'th tokens for this unix uid.
1688 If not present, we just return tokens for cell 1.
1689 If counter out of bounds, return EDOM.
1690 If no tokens for the particular cell, return ENOTCONN.
1691 Also, if this mysterious parm is present, we return, along with the
1692 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1693 at the end, in that order.
1695 if ((newStyle = (ainSize > 0))) {
1696 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1698 i = UHash(areq->uid);
1699 ObtainReadLock(&afs_xuser);
1700 for(tu = afs_users[i]; tu; tu=tu->next) {
1702 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1703 if (iterator-- == 0) break; /* are we done yet? */
1707 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1712 * No need to hold a read lock on each user entry
1716 ReleaseReadLock(&afs_xuser);
1721 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1722 tu->states |= (UTokensBad | UNeedsReset);
1723 afs_PutUser(tu, READ_LOCK);
1726 /* use iterator for temp */
1728 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1729 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1730 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1731 cp += sizeof(afs_int32);
1732 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1734 iterator = sizeof(struct ClearToken);
1735 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1736 cp += sizeof(afs_int32);
1737 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1738 cp += sizeof(struct ClearToken);
1740 /* put out primary id and cell name, too */
1741 iterator = (tu->states & UPrimary ? 1 : 0);
1742 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1743 cp += sizeof(afs_int32);
1744 tcell = afs_GetCell(tu->cell, READ_LOCK);
1746 strcpy(cp, tcell->cellName);
1747 cp += strlen(tcell->cellName)+1;
1748 afs_PutCell(tcell, READ_LOCK);
1752 *aoutSize = cp - aout;
1753 afs_PutUser(tu, READ_LOCK);
1759 register afs_int32 i;
1760 register struct unixuser *tu;
1762 AFS_STATCNT(PUnlog);
1763 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1764 return EIO; /* Inappropriate ioctl for device */
1766 i = UHash(areq->uid);
1767 ObtainWriteLock(&afs_xuser,227);
1768 for(tu=afs_users[i]; tu; tu=tu->next) {
1769 if (tu->uid == areq->uid) {
1771 tu->states &= ~UHasTokens;
1772 /* security is not having to say you're sorry */
1773 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1775 ReleaseWriteLock(&afs_xuser);
1776 /* We have to drop the lock over the call to afs_ResetUserConns, since
1777 * it obtains the afs_xvcache lock. We could also keep the lock, and
1778 * modify ResetUserConns to take parm saying we obtained the lock
1779 * already, but that is overkill. By keeping the "tu" pointer
1780 * held over the released lock, we guarantee that we won't lose our
1781 * place, and that we'll pass over every user conn that existed when
1782 * we began this call.
1784 afs_ResetUserConns(tu);
1786 ObtainWriteLock(&afs_xuser,228);
1788 /* set the expire times to 0, causes
1789 * afs_GCUserData to remove this entry
1791 tu->ct.EndTimestamp = 0;
1793 #endif /* UKERNEL */
1796 ReleaseWriteLock(&afs_xuser);
1800 DECL_PIOCTL(PMariner)
1802 afs_int32 newHostAddr;
1803 afs_int32 oldHostAddr;
1805 AFS_STATCNT(PMariner);
1807 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1809 oldHostAddr = 0xffffffff; /* disabled */
1811 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1812 if (newHostAddr == 0xffffffff) {
1813 /* disable mariner operations */
1816 else if (newHostAddr) {
1818 afs_marinerHost = newHostAddr;
1820 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1821 *aoutSize = sizeof(afs_int32);
1825 DECL_PIOCTL(PCheckServers)
1827 register char *cp = 0;
1829 register struct server *ts;
1830 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1832 struct chservinfo *pcheck;
1834 AFS_STATCNT(PCheckServers);
1836 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1837 return EIO; /* Inappropriate ioctl for device */
1839 if (*lp == 0x12345678) { /* For afs3.3 version */
1840 pcheck=(struct chservinfo *)ain;
1841 if (pcheck->tinterval >= 0) {
1843 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1844 *aoutSize = sizeof(afs_int32);
1845 if (pcheck->tinterval > 0) {
1846 if (!afs_osi_suser(*acred))
1848 PROBE_INTERVAL=pcheck->tinterval;
1854 temp=pcheck->tflags;
1855 cp = pcheck->tbuffer;
1856 } else { /* For pre afs3.3 versions */
1857 memcpy((char *)&temp, ain, sizeof(afs_int32));
1858 cp = ain+sizeof(afs_int32);
1859 if (ainSize > sizeof(afs_int32))
1864 * 1: fast check, don't contact servers.
1865 * 2: local cell only.
1868 /* have cell name, too */
1869 cellp = afs_GetCellByName(cp, READ_LOCK);
1870 if (!cellp) return ENOENT;
1873 if (!cellp && (temp & 2)) {
1874 /* use local cell */
1875 cellp = afs_GetPrimaryCell(READ_LOCK);
1877 if (!(temp & 1)) { /* if not fast, call server checker routine */
1878 afs_CheckServers(1, cellp); /* check down servers */
1879 afs_CheckServers(0, cellp); /* check up servers */
1881 /* now return the current down server list */
1883 ObtainReadLock(&afs_xserver);
1884 for(i=0;i<NSERVERS;i++) {
1885 for(ts = afs_servers[i]; ts; ts=ts->next) {
1886 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1887 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1888 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1889 cp += sizeof(afs_int32);
1893 ReleaseReadLock(&afs_xserver);
1894 if (cellp) afs_PutCell(cellp, READ_LOCK);
1895 *aoutSize = cp - aout;
1899 DECL_PIOCTL(PCheckVolNames)
1901 AFS_STATCNT(PCheckVolNames);
1902 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1903 return EIO; /* Inappropriate ioctl for device */
1905 afs_CheckRootVolume();
1906 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1907 AFS_VOLCHECK_EXPIRED |
1909 AFS_VOLCHECK_MTPTS);
1913 DECL_PIOCTL(PCheckAuth)
1918 struct unixuser *tu;
1921 AFS_STATCNT(PCheckAuth);
1922 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1923 return EIO; /* Inappropriate ioctl for device */
1926 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1927 if (!tu) retValue = EACCES;
1929 /* we have a user */
1930 ObtainReadLock(&afs_xsrvAddr);
1931 ObtainReadLock(&afs_xconn);
1933 /* any tokens set? */
1934 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1935 /* all connections in cell 1 working? */
1936 for(i=0;i<NSERVERS;i++) {
1937 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1938 for (tc = sa->conns; tc; tc=tc->next) {
1939 if (tc->user == tu && (tu->states & UTokensBad))
1944 ReleaseReadLock(&afs_xsrvAddr);
1945 ReleaseReadLock(&afs_xconn);
1946 afs_PutUser(tu, READ_LOCK);
1948 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1949 *aoutSize = sizeof(afs_int32);
1953 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1956 register afs_int32 code;
1957 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1963 AFS_STATCNT(Prefetch);
1964 if (!apath) return EINVAL;
1965 tp = osi_AllocLargeSpace(1024);
1966 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1968 osi_FreeLargeSpace(tp);
1971 if (afs_BBusy()) { /* do this as late as possible */
1972 osi_FreeLargeSpace(tp);
1973 return EWOULDBLOCK; /* pretty close */
1975 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1976 (afs_size_t) 0, (afs_size_t) 0, tp);
1980 DECL_PIOCTL(PFindVolume)
1982 register struct volume *tvp;
1983 register struct server *ts;
1984 register afs_int32 i;
1987 AFS_STATCNT(PFindVolume);
1988 if (!avc) return EINVAL;
1989 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1992 for(i=0;i<MAXHOSTS;i++) {
1993 ts = tvp->serverHost[i];
1995 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1996 cp += sizeof(afs_int32);
1999 /* still room for terminating NULL, add it on */
2000 ainSize = 0; /* reuse vbl */
2001 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2002 cp += sizeof(afs_int32);
2004 *aoutSize = cp - aout;
2005 afs_PutVolume(tvp, READ_LOCK);
2011 DECL_PIOCTL(PViceAccess)
2013 register afs_int32 code;
2016 AFS_STATCNT(PViceAccess);
2017 if (!avc) return EINVAL;
2018 code = afs_VerifyVCache(avc, areq);
2019 if (code) return code;
2020 memcpy((char *)&temp, ain, sizeof(afs_int32));
2021 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2026 DECL_PIOCTL(PSetCacheSize)
2031 AFS_STATCNT(PSetCacheSize);
2032 if (!afs_osi_suser(*acred))
2034 /* too many things are setup initially in mem cache version */
2035 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2036 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2037 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2039 if (newValue < afs_min_cache)
2040 afs_cacheBlocks = afs_min_cache;
2042 afs_cacheBlocks = newValue;
2044 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2045 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2046 afs_MaybeWakeupTruncateDaemon();
2047 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2048 afs_osi_Wait(1000, 0, 0);
2049 afs_MaybeWakeupTruncateDaemon();
2054 #define MAXGCSTATS 16
2055 DECL_PIOCTL(PGetCacheSize)
2057 afs_int32 results[MAXGCSTATS];
2059 AFS_STATCNT(PGetCacheSize);
2060 memset((char *)results, 0, sizeof(results));
2061 results[0] = afs_cacheBlocks;
2062 results[1] = afs_blocksUsed;
2063 memcpy(aout, (char *)results, sizeof(results));
2064 *aoutSize = sizeof(results);
2068 DECL_PIOCTL(PRemoveCallBack)
2070 register struct conn *tc;
2071 register afs_int32 code;
2072 struct AFSCallBack CallBacks_Array[1];
2073 struct AFSCBFids theFids;
2074 struct AFSCBs theCBs;
2077 AFS_STATCNT(PRemoveCallBack);
2078 if (!avc) return EINVAL;
2079 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2080 ObtainWriteLock(&avc->lock,229);
2081 theFids.AFSCBFids_len = 1;
2082 theCBs.AFSCBs_len = 1;
2083 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2084 theCBs.AFSCBs_val = CallBacks_Array;
2085 CallBacks_Array[0].CallBackType = CB_DROPPED;
2086 if (avc->callback) {
2088 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2090 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2092 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2096 /* don't set code on failure since we wouldn't use it */
2098 (afs_Analyze(tc, code, &avc->fid, areq,
2099 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2100 SHARED_LOCK, NULL));
2102 ObtainWriteLock(&afs_xcbhash, 457);
2103 afs_DequeueCallback(avc);
2105 avc->states &= ~(CStatd | CUnique);
2106 ReleaseWriteLock(&afs_xcbhash);
2107 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2108 osi_dnlc_purgedp(avc);
2110 ReleaseWriteLock(&avc->lock);
2114 DECL_PIOCTL(PNewCell)
2116 /* create a new cell */
2117 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2118 register struct cell *tcell;
2119 char *newcell=0, *linkedcell=0, *tp= ain;
2120 register afs_int32 code, linkedstate=0, ls;
2121 u_short fsport = 0, vlport = 0;
2124 AFS_STATCNT(PNewCell);
2125 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2126 return EIO; /* Inappropriate ioctl for device */
2128 if (!afs_osi_suser(*acred))
2131 memcpy((char *)&magic, tp, sizeof(afs_int32));
2132 tp += sizeof(afs_int32);
2133 if (magic != 0x12345678)
2136 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2137 * server addresses while the 3.5 fs newcell command passes
2138 * MAXHOSTS. To figure out which is which, check if the cellname
2141 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2142 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2144 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2145 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2146 tp += (scount * sizeof(afs_int32));
2148 lp = (afs_int32 *)tp;
2151 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2152 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2153 tp += (3 * sizeof(afs_int32));
2155 if ((ls = *lp) & 1) {
2156 linkedcell = tp + strlen(newcell)+1;
2157 linkedstate |= CLinkedCell;
2160 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2161 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2166 DECL_PIOCTL(PNewAlias)
2168 /* create a new cell alias */
2170 register afs_int32 code;
2171 char *realName, *aliasName;
2173 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2174 return EIO; /* Inappropriate ioctl for device */
2176 if (!afs_osi_suser(*acred))
2180 tp += strlen(aliasName) + 1;
2183 code = afs_NewCellAlias(aliasName, realName);
2188 DECL_PIOCTL(PListCells)
2190 afs_int32 whichCell;
2191 register struct cell *tcell=0;
2192 register afs_int32 i;
2193 register char *cp, *tp = ain;
2195 AFS_STATCNT(PListCells);
2196 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2197 return EIO; /* Inappropriate ioctl for device */
2199 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2200 tp += sizeof(afs_int32);
2201 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2204 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2205 for(i=0;i<MAXCELLHOSTS;i++) {
2206 if (tcell->cellHosts[i] == 0) break;
2207 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2208 cp += sizeof(afs_int32);
2210 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2211 strcpy(cp, tcell->cellName);
2212 cp += strlen(tcell->cellName)+1;
2213 *aoutSize = cp - aout;
2214 afs_PutCell(tcell, READ_LOCK);
2216 if (tcell) return 0;
2220 DECL_PIOCTL(PListAliases)
2222 afs_int32 whichAlias;
2223 register struct cell_alias *tcalias=0;
2224 register char *cp, *tp = ain;
2226 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2227 return EIO; /* Inappropriate ioctl for device */
2228 if (ainSize < sizeof(afs_int32))
2231 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2232 tp += sizeof(afs_int32);
2234 tcalias = afs_GetCellAlias(whichAlias);
2237 strcpy(cp, tcalias->alias);
2238 cp += strlen(tcalias->alias)+1;
2239 strcpy(cp, tcalias->cell);
2240 cp += strlen(tcalias->cell)+1;
2241 *aoutSize = cp - aout;
2242 afs_PutCellAlias(tcalias);
2244 if (tcalias) return 0;
2248 DECL_PIOCTL(PRemoveMount)
2250 register afs_int32 code;
2252 struct sysname_info sysState;
2253 afs_size_t offset, len;
2254 register struct conn *tc;
2255 register struct dcache *tdc;
2256 register struct vcache *tvc;
2257 struct AFSFetchStatus OutDirStatus;
2258 struct VenusFid tfid;
2259 struct AFSVolSync tsync;
2263 /* "ain" is the name of the file in this dir to remove */
2265 AFS_STATCNT(PRemoveMount);
2266 if (!avc) return EINVAL;
2267 code = afs_VerifyVCache(avc, areq);
2268 if (code) return code;
2269 if (vType(avc) != VDIR) return ENOTDIR;
2271 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2272 if (!tdc) return ENOENT;
2273 Check_AtSys(avc, ain, &sysState, areq);
2274 ObtainReadLock(&tdc->lock);
2276 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2277 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2278 ReleaseReadLock(&tdc->lock);
2279 bufp = sysState.name;
2284 tfid.Cell = avc->fid.Cell;
2285 tfid.Fid.Volume = avc->fid.Fid.Volume;
2286 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2287 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2289 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2296 if (tvc->mvstat != 1) {
2302 ObtainWriteLock(&tvc->lock,230);
2303 code = afs_HandleLink(tvc, areq);
2305 if (tvc->linkData) {
2306 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2311 ReleaseWriteLock(&tvc->lock);
2312 osi_dnlc_purgedp(tvc);
2318 ObtainWriteLock(&avc->lock,231);
2319 osi_dnlc_remove(avc, bufp, tvc);
2321 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2323 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2325 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2326 bufp, &OutDirStatus, &tsync);
2332 (afs_Analyze(tc, code, &avc->fid, areq,
2333 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2334 SHARED_LOCK, NULL));
2337 if (tdc) afs_PutDCache(tdc);
2338 ReleaseWriteLock(&avc->lock);
2342 /* we have the thing in the cache */
2343 ObtainWriteLock(&tdc->lock, 661);
2344 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2345 /* we can do it locally */
2346 code = afs_dir_Delete(&tdc->f.inode, bufp);
2348 ZapDCE(tdc); /* surprise error -- invalid value */
2349 DZap(&tdc->f.inode);
2352 ReleaseWriteLock(&tdc->lock);
2353 afs_PutDCache(tdc); /* drop ref count */
2355 avc->states &= ~CUnique; /* For the dfs xlator */
2356 ReleaseWriteLock(&avc->lock);
2359 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2363 DECL_PIOCTL(PVenusLogging)
2365 return EINVAL; /* OBSOLETE */
2368 DECL_PIOCTL(PGetCellStatus)
2370 register struct cell *tcell;
2373 AFS_STATCNT(PGetCellStatus);
2374 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2375 return EIO; /* Inappropriate ioctl for device */
2377 tcell = afs_GetCellByName(ain, READ_LOCK);
2378 if (!tcell) return ENOENT;
2379 temp = tcell->states;
2380 afs_PutCell(tcell, READ_LOCK);
2381 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2382 *aoutSize = sizeof(afs_int32);
2386 DECL_PIOCTL(PSetCellStatus)
2388 register struct cell *tcell;
2391 if (!afs_osi_suser(*acred))
2393 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2394 return EIO; /* Inappropriate ioctl for device */
2396 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2397 if (!tcell) return ENOENT;
2398 memcpy((char *)&temp, ain, sizeof(afs_int32));
2400 tcell->states |= CNoSUID;
2402 tcell->states &= ~CNoSUID;
2403 afs_PutCell(tcell, WRITE_LOCK);
2407 DECL_PIOCTL(PFlushVolumeData)
2409 register afs_int32 i;
2410 register struct dcache *tdc;
2411 register struct vcache *tvc;
2412 register struct volume *tv;
2413 afs_int32 cell, volume;
2415 AFS_STATCNT(PFlushVolumeData);
2418 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2419 return EIO; /* Inappropriate ioctl for device */
2421 volume = avc->fid.Fid.Volume; /* who to zap */
2422 cell = avc->fid.Cell;
2425 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2426 * the vcaches associated with the volume.
2428 ObtainReadLock(&afs_xvcache);
2429 for(i = 0; i < VCSIZE; i++) {
2430 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2431 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2432 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2433 VN_HOLD(AFSTOV(tvc));
2435 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2441 ReleaseReadLock(&afs_xvcache);
2442 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2443 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2445 ObtainWriteLock(&tvc->lock,232);
2447 ObtainWriteLock(&afs_xcbhash, 458);
2448 afs_DequeueCallback(tvc);
2449 tvc->states &= ~(CStatd | CDirty);
2450 ReleaseWriteLock(&afs_xcbhash);
2451 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2452 osi_dnlc_purgedp(tvc);
2453 afs_TryToSmush(tvc, *acred, 1);
2454 ReleaseWriteLock(&tvc->lock);
2455 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2456 afs_BozonUnlock(&tvc->pvnLock, tvc);
2458 ObtainReadLock(&afs_xvcache);
2459 /* our tvc ptr is still good until now */
2464 ReleaseReadLock(&afs_xvcache);
2467 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2468 for(i=0;i<afs_cacheFiles;i++) {
2469 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2470 tdc = afs_GetDSlot(i, NULL);
2471 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2472 ReleaseReadLock(&tdc->tlock);
2473 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2474 if (! (afs_indexFlags[i] & IFDataMod)) {
2475 /* if the file is modified, but has a ref cnt of only 1, then
2476 someone probably has the file open and is writing into it.
2477 Better to skip flushing such a file, it will be brought back
2478 immediately on the next write anyway.
2480 If we *must* flush, then this code has to be rearranged to call
2481 afs_storeAllSegments() first */
2482 afs_FlushDCache(tdc);
2486 ReleaseReadLock(&tdc->tlock);
2488 afs_PutDCache(tdc); /* bumped by getdslot */
2490 MReleaseWriteLock(&afs_xdcache);
2492 ObtainReadLock(&afs_xvolume);
2493 for (i=0;i<NVOLS;i++) {
2494 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2495 if (tv->volume == volume) {
2496 afs_ResetVolumeInfo(tv);
2501 ReleaseReadLock(&afs_xvolume);
2503 /* probably, a user is doing this, probably, because things are screwed up.
2504 * maybe it's the dnlc's fault? */
2511 DECL_PIOCTL(PGetVnodeXStatus)
2513 register afs_int32 code;
2514 struct vcxstat stat;
2517 /* AFS_STATCNT(PGetVnodeXStatus); */
2518 if (!avc) return EINVAL;
2519 code = afs_VerifyVCache(avc, areq);
2520 if (code) return code;
2521 if (vType(avc) == VDIR)
2522 mode = PRSFS_LOOKUP;
2525 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2527 stat.fid = avc->fid;
2528 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2529 stat.lock = avc->lock;
2530 stat.parentVnode = avc->parentVnode;
2531 stat.parentUnique = avc->parentUnique;
2532 hset(stat.flushDV, avc->flushDV);
2533 hset(stat.mapDV, avc->mapDV);
2534 stat.truncPos = avc->truncPos;
2535 { /* just grab the first two - won't break anything... */
2536 struct axscache *ac;
2538 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2539 stat.randomUid[i] = ac->uid;
2540 stat.randomAccess[i] = ac->axess;
2543 stat.callback = afs_data_pointer_to_int32(avc->callback);
2544 stat.cbExpires = avc->cbExpires;
2545 stat.anyAccess = avc->anyAccess;
2546 stat.opens = avc->opens;
2547 stat.execsOrWriters = avc->execsOrWriters;
2548 stat.flockCount = avc->flockCount;
2549 stat.mvstat = avc->mvstat;
2550 stat.states = avc->states;
2551 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2552 *aoutSize = sizeof(struct vcxstat);
2557 /* We require root for local sysname changes, but not for remote */
2558 /* (since we don't really believe remote uids anyway) */
2559 /* outname[] shouldn't really be needed- this is left as an excercise */
2560 /* for the reader. */
2561 DECL_PIOCTL(PSetSysName)
2563 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2564 int setsysname, foundname=0;
2565 register struct afs_exporter *exporter;
2566 register struct unixuser *au;
2567 register afs_int32 pag, error;
2571 AFS_STATCNT(PSetSysName);
2572 if (!afs_globalVFS) {
2573 /* Afsd is NOT running; disable it */
2574 #if defined(KERNEL_HAVE_SETUERROR)
2575 return (setuerror(EINVAL), EINVAL);
2580 memset(inname, 0, MAXSYSNAME);
2581 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2582 ain += sizeof(afs_int32);
2586 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2588 for(cp = ain,count = 0;count < setsysname;count++) {
2589 /* won't go past end of ain since maxsysname*num < ain length */
2591 if (t >= MAXSYSNAME || t <= 0)
2593 /* check for names that can shoot us in the foot */
2594 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2600 /* inname gets first entry in case we're being a translater */
2602 memcpy(inname, ain, t+1); /* include terminating null */
2605 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2606 pag = PagInCred(*acred);
2608 return EINVAL; /* Better than panicing */
2610 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2611 return EINVAL; /* Better than panicing */
2613 if (!(exporter = au->exporter)) {
2614 afs_PutUser(au, READ_LOCK);
2615 return EINVAL; /* Better than panicing */
2617 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2619 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2621 afs_PutUser(au, READ_LOCK);
2626 afs_PutUser(au, READ_LOCK);
2629 /* Not xlating, so local case */
2630 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2631 if (!setsysname) { /* user just wants the info */
2632 strcpy(outname, afs_sysname);
2633 foundname = afs_sysnamecount;
2634 } else { /* Local guy; only root can change sysname */
2635 if (!afs_osi_suser(*acred))
2638 /* clear @sys entries from the dnlc, once afs_lookup can
2639 do lookups of @sys entries and thinks it can trust them */
2640 /* privs ok, store the entry, ... */
2641 strcpy(afs_sysname, inname);
2642 if (setsysname > 1) { /* ... or list */
2644 for(count=1; count < setsysname;++count) {
2645 if (!afs_sysnamelist[count])
2646 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2648 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2652 afs_sysnamecount = setsysname;
2656 cp = aout; /* not changing so report back the count and ... */
2657 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2658 cp += sizeof(afs_int32);
2660 strcpy(cp, outname); /* ... the entry, ... */
2661 cp += strlen(outname)+1;
2662 for(count=1; count < foundname; ++count) { /* ... or list. */
2663 /* Note: we don't support @sys lists for exporters */
2664 if (!afs_sysnamelist[count])
2665 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2666 t = strlen(afs_sysnamelist[count]);
2667 if (t >= MAXSYSNAME)
2668 osi_Panic("PSetSysName: sysname entry garbled\n");
2669 strcpy(cp, afs_sysnamelist[count]);
2673 *aoutSize = cp - aout;
2678 /* sequential search through the list of touched cells is not a good
2679 * long-term solution here. For small n, though, it should be just
2680 * fine. Should consider special-casing the local cell for large n.
2681 * Likewise for PSetSPrefs.
2683 * s - number of ids in array l[] -- NOT index of last id
2684 * l - array of cell ids which have volumes that need to be sorted
2685 * vlonly - sort vl servers or file servers?
2687 static void *ReSortCells_cb(struct cell *cell, void *arg)
2689 afs_int32 *p = (afs_int32 *) arg;
2690 afs_int32 *l = p + 1;
2693 for (i=0; i<s; i++) {
2694 if (l[i] == cell->cellNum) {
2695 ObtainWriteLock(&cell->lock, 690);
2696 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2697 ReleaseWriteLock(&cell->lock);
2702 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2710 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2712 memcpy(p+1, l, s * sizeof(afs_int32));
2713 afs_TraverseCells(&ReSortCells_cb, p);
2714 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2718 ObtainReadLock(&afs_xvolume);
2719 for (i= 0; i< NVOLS; i++) {
2720 for (j=afs_volumes[i];j;j=j->next) {
2722 if (j->cell == l[k]) {
2723 ObtainWriteLock(&j->lock,233);
2724 afs_SortServers(j->serverHost, MAXHOSTS);
2725 ReleaseWriteLock(&j->lock);
2730 ReleaseReadLock(&afs_xvolume);
2734 static int debugsetsp = 0;
2735 static int afs_setsprefs(sp, num, vlonly)
2738 unsigned int vlonly;
2741 int i,j,k,matches,touchedSize;
2742 struct server *srvr = NULL;
2743 afs_int32 touched[34];
2747 for (k=0; k < num; sp++, k++) {
2749 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2752 ObtainReadLock(&afs_xserver);
2754 i = SHash(sp->host.s_addr);
2755 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2756 if (sa->sa_ip == sp->host.s_addr) {
2758 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2759 || (sa->sa_portal == AFS_FSPORT);
2760 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2767 if (sa && matches) { /* found one! */
2769 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2771 sa->sa_iprank = sp->rank + afs_randomMod15();
2772 afs_SortOneServer(sa->server);
2775 /* if we don't know yet what cell it's in, this is moot */
2776 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2777 /* is it in our list of touched cells ? */ ;
2778 if (j < 0) { /* no, it's not */
2779 touched[touchedSize++] = srvr->cell->cellNum;
2780 if (touchedSize >= 32) { /* watch for ovrflow */
2781 ReleaseReadLock(&afs_xserver);
2782 ReSortCells(touchedSize, touched, vlonly);
2784 ObtainReadLock(&afs_xserver);
2790 ReleaseReadLock(&afs_xserver);
2791 /* if we didn't find one, start to create one. */
2792 /* Note that it doesn't have a cell yet... */
2794 afs_uint32 temp = sp->host.s_addr;
2795 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2796 WRITE_LOCK, (afsUUID *)0,0);
2797 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2798 afs_PutServer(srvr, WRITE_LOCK);
2800 } /* for all cited preferences */
2802 ReSortCells(touchedSize, touched, vlonly);
2806 /* Note that this may only be performed by the local root user.
2808 DECL_PIOCTL(PSetSPrefs)
2810 struct setspref *ssp;
2811 AFS_STATCNT(PSetSPrefs);
2813 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2814 return EIO; /* Inappropriate ioctl for device */
2816 if (!afs_osi_suser(*acred))
2819 if (ainSize < sizeof(struct setspref))
2822 ssp = (struct setspref *)ain;
2823 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2826 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2827 (ssp->flags & DBservers));
2831 DECL_PIOCTL(PSetSPrefs33)
2834 AFS_STATCNT(PSetSPrefs);
2835 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2836 return EIO; /* Inappropriate ioctl for device */
2839 if (!afs_osi_suser(*acred))
2842 sp = (struct spref *)ain;
2843 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2847 /* some notes on the following code...
2848 * in the hash table of server structs, all servers with the same IP address
2849 * will be on the same overflow chain.
2850 * This could be sped slightly in some circumstances by having it cache the
2851 * immediately previous slot in the hash table and some supporting information
2852 * Only reports file servers now.
2854 DECL_PIOCTL(PGetSPrefs)
2856 struct sprefrequest *spin; /* input */
2857 struct sprefinfo *spout; /* output */
2858 struct spref *srvout; /* one output component */
2859 int i,j; /* counters for hash table traversal */
2860 struct server *srvr; /* one of CM's server structs */
2863 int vlonly; /* just return vlservers ? */
2866 AFS_STATCNT(PGetSPrefs);
2867 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2868 return EIO; /* Inappropriate ioctl for device */
2871 if (ainSize < sizeof (struct sprefrequest_33)) {
2875 spin = ((struct sprefrequest *) ain);
2878 if (ainSize > sizeof (struct sprefrequest_33)) {
2879 vlonly = (spin->flags & DBservers);
2883 /* struct sprefinfo includes 1 server struct... that size gets added
2884 * in during the loop that follows.
2886 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2887 spout = (struct sprefinfo *) aout;
2888 spout->next_offset = spin->offset;
2889 spout->num_servers = 0;
2890 srvout = spout->servers;
2892 ObtainReadLock(&afs_xserver);
2893 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2894 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2895 if (spin->offset > (unsigned short)i) {
2896 continue; /* catch up to where we left off */
2898 spout->next_offset++;
2901 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2902 || (sa->sa_portal == AFS_FSPORT);
2904 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2905 /* only report ranks for vl servers */
2909 srvout->host.s_addr = sa->sa_ip;
2910 srvout->rank = sa->sa_iprank;
2911 *aoutSize += sizeof(struct spref);
2912 spout->num_servers++;
2915 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2916 ReleaseReadLock(&afs_xserver); /* no more room! */
2921 ReleaseReadLock(&afs_xserver);
2923 spout->next_offset = 0; /* start over from the beginning next time */
2927 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2928 int afs_NFSRootOnly = 1;
2929 DECL_PIOCTL(PExportAfs)
2931 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2932 register struct afs_exporter *exporter;
2934 AFS_STATCNT(PExportAfs);
2935 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2936 type = handleValue >> 24;
2941 exporter = exporter_find(type);
2943 export = handleValue & 3;
2944 changestate = handleValue & 0xff;
2945 smounts = (handleValue >> 2) & 3;
2946 pwsync = (handleValue >> 4) & 3;
2947 convmode = (handleValue >> 6) & 3;
2949 changestate = (handleValue >> 16) & 0x1;
2950 convmode = (handleValue >> 16) & 0x2;
2951 pwsync = (handleValue >> 16) & 0x4;
2952 smounts = (handleValue >> 16) & 0x8;
2953 export = handleValue & 0xff;
2956 /* Failed finding desired exporter; */
2960 handleValue = exporter->exp_states;
2961 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2962 *aoutSize = sizeof(afs_int32);
2964 if (!afs_osi_suser(*acred))
2965 return EACCES; /* Only superuser can do this */
2969 exporter->exp_states |= EXP_EXPORTED;
2971 exporter->exp_states &= ~EXP_EXPORTED;
2975 exporter->exp_states |= EXP_UNIXMODE;
2977 exporter->exp_states &= ~EXP_UNIXMODE;
2981 exporter->exp_states |= EXP_PWSYNC;
2983 exporter->exp_states &= ~EXP_PWSYNC;
2987 afs_NFSRootOnly = 0;
2988 exporter->exp_states |= EXP_SUBMOUNTS;
2990 afs_NFSRootOnly = 1;
2991 exporter->exp_states &= ~EXP_SUBMOUNTS;
2994 handleValue = exporter->exp_states;
2995 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2996 *aoutSize = sizeof(afs_int32);
2999 exporter->exp_states |= EXP_EXPORTED;
3001 exporter->exp_states &= ~EXP_EXPORTED;
3003 exporter->exp_states |= EXP_UNIXMODE;
3005 exporter->exp_states &= ~EXP_UNIXMODE;
3007 exporter->exp_states |= EXP_PWSYNC;
3009 exporter->exp_states &= ~EXP_PWSYNC;
3011 afs_NFSRootOnly = 0;
3012 exporter->exp_states |= EXP_SUBMOUNTS;
3014 afs_NFSRootOnly = 1;
3015 exporter->exp_states &= ~EXP_SUBMOUNTS;
3025 struct gaginfo *gagflags;
3027 if (!afs_osi_suser(*acred))
3030 gagflags = (struct gaginfo *) ain;
3031 afs_showflags = gagflags->showflags;
3037 DECL_PIOCTL(PTwiddleRx)
3039 struct rxparams *rxp;
3041 if (!afs_osi_suser(*acred))
3044 rxp = (struct rxparams *) ain;
3046 if (rxp->rx_initReceiveWindow)
3047 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3048 if (rxp->rx_maxReceiveWindow)
3049 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3050 if (rxp->rx_initSendWindow)
3051 rx_initSendWindow = rxp->rx_initSendWindow;
3052 if (rxp->rx_maxSendWindow)
3053 rx_maxSendWindow = rxp->rx_maxSendWindow;
3054 if (rxp->rxi_nSendFrags)
3055 rxi_nSendFrags = rxp->rxi_nSendFrags;
3056 if (rxp->rxi_nRecvFrags)
3057 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3058 if (rxp->rxi_OrphanFragSize)
3059 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3060 if (rxp->rx_maxReceiveSize)
3062 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3063 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3065 if (rxp->rx_MyMaxSendSize)
3066 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3071 DECL_PIOCTL(PGetInitParams)
3073 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3076 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3077 *aoutSize = sizeof(struct cm_initparams);
3081 #ifdef AFS_SGI65_ENV
3082 /* They took crget() from us, so fake it. */
3083 static cred_t *crget(void)
3086 cr = crdup(get_current_cred());
3087 memset((char*)cr, 0, sizeof(cred_t));
3088 #if CELL || CELL_PREPARE
3095 DECL_PIOCTL(PGetRxkcrypt)
3097 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3098 *aoutSize=sizeof(afs_int32);
3102 DECL_PIOCTL(PSetRxkcrypt)
3106 if (!afs_osi_suser(*acred))
3108 if (ainSize != sizeof(afs_int32) || ain == NULL)
3110 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3111 /* if new mappings added later this will need to be changed */
3112 if (tmpval != 0 && tmpval != 1)
3119 * Create new credentials to correspond to a remote user with given
3120 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3121 * provide pioctl (and other) services to foreign clients (i.e. nfs
3122 * clients) by using this call to `become' the client.
3125 #define PIOCTL_HEADER 6
3126 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3128 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3129 return EINVAL; /* NFS trans not supported for Ultrix */
3132 afs_uint32 hostaddr;
3133 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3134 struct afs_exporter *exporter, *outexporter;
3135 struct AFS_UCRED *newcred;
3136 struct unixuser *au;
3138 #if defined(AFS_SGIMP_ENV)
3139 osi_Assert(ISAFS_GLOCK());
3141 AFS_STATCNT(HandleClientContext);
3142 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3143 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3144 return EINVAL; /* Too small to be good */
3146 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3147 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3149 osi_FreeLargeSpace(inData);
3153 /* Extract information for remote user */
3154 hostaddr = *((afs_uint32 *)ain);
3155 ain += sizeof(hostaddr);
3156 uid = *((afs_uint32 *)ain);
3158 g0 = *((afs_uint32 *)ain);
3160 g1 = *((afs_uint32 *)ain);
3162 *com = *((afs_uint32 *)ain);
3163 ain += sizeof(afs_int32);
3164 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3167 * Of course, one must be root for most of these functions, but
3168 * we'll allow (for knfs) you to set things if the pag is 0 and
3169 * you're setting tokens or unlogging.
3172 if (!afs_osi_suser(credp)) {
3174 #ifndef AFS_SGI64_ENV
3175 /* Since SGI's suser() returns explicit failure after the call.. */
3179 /* check for acceptable opcodes for normal folks, which are, so far,
3180 * set tokens and unlog.
3182 if (i != 9 && i != 3 && i != 38 && i != 8) {
3183 osi_FreeLargeSpace(inData);
3188 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3189 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3190 osi_FreeLargeSpace(inData);
3193 * We map uid 0 to nobody to match the mapping that the nfs
3194 * server does and to ensure that the suser() calls in the afs
3195 * code fails for remote client roots.
3197 uid = afs_nobody; /* NFS_NOBODY == -2 */
3200 #ifdef AFS_AIX41_ENV
3203 newcred->cr_gid = RMTUSER_REQ;
3204 newcred->cr_groups[0] = g0;
3205 newcred->cr_groups[1] = g1;
3207 newcred->cr_ngrps = 2;
3209 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3210 newcred->cr_ngroups = 2;
3212 for (i=2; i<NGROUPS; i++)
3213 newcred->cr_groups[i] = NOGROUP;
3216 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3217 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3219 if (!(exporter = exporter_find(exporter_type))) {
3220 /* Exporter wasn't initialized or an invalid exporter type */
3224 if (exporter->exp_states & EXP_PWSYNC) {
3225 if (uid != credp->cr_uid) {
3227 return ENOEXEC; /* XXX Find a better errno XXX */
3230 newcred->cr_uid = uid; /* Only temporary */
3231 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3232 /* The client's pag is the only unique identifier for it */
3233 newcred->cr_uid = pag;
3235 if (!code && *com == PSETPAG) {
3236 /* Special case for 'setpag' */
3237 afs_uint32 pagvalue = genpag();
3239 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3241 * Note that we leave the 'outexporter' struct held so it won't
3244 au->exporter = outexporter;
3245 if (ablob->out_size >= 4) {
3246 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3248 afs_PutUser(au, WRITE_LOCK);
3249 if (code) return code;
3250 return PSETPAG; /* Special return for setpag */
3252 EXP_RELE(outexporter);
3255 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3258 /* get all interface addresses of this client */
3260 DECL_PIOCTL(PGetCPrefs)
3262 struct sprefrequest *spin; /* input */
3263 struct sprefinfo *spout; /* output */
3264 struct spref *srvout; /* one output component */
3268 AFS_STATCNT(PGetCPrefs);
3269 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3270 return EIO; /* Inappropriate ioctl for device */
3272 if ( ainSize < sizeof (struct sprefrequest ))
3275 spin = (struct sprefrequest *) ain;
3276 spout = (struct sprefinfo *) aout;
3278 maxNumber = spin->num_servers; /* max addrs this time */
3279 srvout = spout->servers;
3281 ObtainReadLock(&afs_xinterface);
3283 /* copy out the client interface information from the
3284 ** kernel data structure "interface" to the output buffer
3286 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3287 && ( j< maxNumber) ; i++, j++, srvout++)
3288 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3290 spout->num_servers = j;
3291 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3293 if ( i >= afs_cb_interface.numberOfInterfaces )
3294 spout->next_offset = 0; /* start from beginning again */
3296 spout->next_offset = spin->offset + j;
3298 ReleaseReadLock(&afs_xinterface);
3302 DECL_PIOCTL(PSetCPrefs)
3304 struct setspref *sin;
3307 AFS_STATCNT(PSetCPrefs);
3308 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3309 return EIO; /* Inappropriate ioctl for device */
3311 sin = (struct setspref *)ain;
3313 if ( ainSize < sizeof(struct setspref) )
3315 #if 0 /* num_servers is unsigned */
3316 if ( sin->num_servers < 0 )
3319 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3322 ObtainWriteLock(&afs_xinterface, 412);
3323 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3324 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3325 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3327 ReleaseWriteLock(&afs_xinterface);
3331 DECL_PIOCTL(PFlushMount)
3333 register afs_int32 code;
3334 register struct vcache *tvc;
3335 register struct dcache *tdc;
3336 struct VenusFid tfid;
3338 struct sysname_info sysState;
3339 afs_size_t offset, len;
3341 AFS_STATCNT(PFlushMount);
3342 if (!avc) return EINVAL;
3343 code = afs_VerifyVCache(avc, areq);
3344 if (code) return code;
3345 if (vType(avc) != VDIR) {
3348 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3349 if (!tdc) return ENOENT;
3350 Check_AtSys(avc, ain, &sysState, areq);
3351 ObtainReadLock(&tdc->lock);
3353 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3354 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3355 ReleaseReadLock(&tdc->lock);
3356 afs_PutDCache(tdc); /* we're done with the data */
3357 bufp = sysState.name;
3361 tfid.Cell = avc->fid.Cell;
3362 tfid.Fid.Volume = avc->fid.Fid.Volume;
3363 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3364 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3366 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3372 if (tvc->mvstat != 1) {
3377 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3378 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3380 ObtainWriteLock(&tvc->lock,649);
3381 ObtainWriteLock(&afs_xcbhash, 650);
3382 afs_DequeueCallback(tvc);
3383 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3384 ReleaseWriteLock(&afs_xcbhash);
3385 /* now find the disk cache entries */
3386 afs_TryToSmush(tvc, *acred, 1);
3387 osi_dnlc_purgedp(tvc);
3388 afs_symhint_inval(tvc);
3389 if (tvc->linkData && !(tvc->states & CCore)) {
3390 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3391 tvc->linkData = NULL;
3393 ReleaseWriteLock(&tvc->lock);
3394 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3395 afs_BozonUnlock(&tvc->pvnLock, tvc);
3399 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3403 DECL_PIOCTL(PRxStatProc)
3408 if (!afs_osi_suser(*acred)) {
3412 if (ainSize != sizeof(afs_int32)) {
3416 memcpy((char *)&flags, ain, sizeof(afs_int32));
3417 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3421 if (flags & AFSCALL_RXSTATS_ENABLE) {
3422 rx_enableProcessRPCStats();
3424 if (flags & AFSCALL_RXSTATS_DISABLE) {
3425 rx_disableProcessRPCStats();
3427 if (flags & AFSCALL_RXSTATS_CLEAR) {
3428 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3436 DECL_PIOCTL(PRxStatPeer)
3441 if (!afs_osi_suser(*acred)) {
3445 if (ainSize != sizeof(afs_int32)) {
3449 memcpy((char *)&flags, ain, sizeof(afs_int32));
3450 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3454 if (flags & AFSCALL_RXSTATS_ENABLE) {
3455 rx_enablePeerRPCStats();
3457 if (flags & AFSCALL_RXSTATS_DISABLE) {
3458 rx_disablePeerRPCStats();
3460 if (flags & AFSCALL_RXSTATS_CLEAR) {
3461 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3468 DECL_PIOCTL(PPrefetchFromTape)
3470 register afs_int32 code, code1;
3473 struct rx_call *tcall;
3474 struct AFSVolSync tsync;
3475 struct AFSFetchStatus OutStatus;
3476 struct AFSCallBack CallBack;
3477 struct VenusFid tfid;
3482 AFS_STATCNT(PSetAcl);
3486 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3487 Fid = (struct AFSFid *) ain;
3489 Fid = &avc->fid.Fid;
3490 tfid.Cell = avc->fid.Cell;
3491 tfid.Fid.Volume = Fid->Volume;
3492 tfid.Fid.Vnode = Fid->Vnode;
3493 tfid.Fid.Unique = Fid->Unique;
3495 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3497 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3498 ICL_TYPE_POINTER, tvc,
3499 ICL_TYPE_FID, &tfid,
3500 ICL_TYPE_FID, &avc->fid);
3503 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3504 ICL_TYPE_POINTER, tvc,
3505 ICL_TYPE_FID, &tfid,
3506 ICL_TYPE_FID, &tvc->fid);
3509 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3513 tcall = rx_NewCall(tc->id);
3514 code = StartRXAFS_FetchData(tcall,
3515 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3517 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3518 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3520 code1 = rx_EndCall(tcall, code);
3525 (afs_Analyze(tc, code, &tvc->fid, areq,
3526 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3528 /* This call is done only to have the callback things handled correctly */
3529 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3533 *aoutSize = sizeof(afs_int32);
3538 DECL_PIOCTL(PResidencyCmd)
3540 register afs_int32 code;
3543 struct ResidencyCmdInputs *Inputs;
3544 struct ResidencyCmdOutputs *Outputs;
3545 struct VenusFid tfid;
3548 Inputs = (struct ResidencyCmdInputs *) ain;
3549 Outputs = (struct ResidencyCmdOutputs *) aout;
3550 if (!avc) return EINVAL;
3551 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3555 Fid = &avc->fid.Fid;
3557 tfid.Cell = avc->fid.Cell;
3558 tfid.Fid.Volume = Fid->Volume;
3559 tfid.Fid.Vnode = Fid->Vnode;
3560 tfid.Fid.Unique = Fid->Unique;
3562 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3563 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3564 ICL_TYPE_POINTER, tvc,
3565 ICL_TYPE_INT32, Inputs->command,
3566 ICL_TYPE_FID, &tfid);
3570 if (Inputs->command) {
3572 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3575 code = RXAFS_ResidencyCmd(tc->id, Fid,
3577 (struct ResidencyCmdOutputs *) aout);
3582 (afs_Analyze(tc, code, &tvc->fid, areq,
3583 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3585 /* This call is done to have the callback things handled correctly */
3586 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3587 } else { /* just a status request, return also link data */
3589 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3590 Outputs->chars[0] = 0;
3591 if (vType(tvc) == VLNK) {
3592 ObtainWriteLock(&tvc->lock,555);
3593 if (afs_HandleLink(tvc, areq) == 0)
3594 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3595 ReleaseWriteLock(&tvc->lock);
3602 *aoutSize = sizeof(struct ResidencyCmdOutputs);