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);
309 return code; /* so far, none implemented */
314 /* For aix we don't temporarily bypass ioctl(2) but rather do our
315 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
316 * is now called from afs_gn_ioctl.
318 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
320 struct afs_ioctl data;
323 AFS_STATCNT(afs_ioctl);
324 if (((cmd >> 8) & 0xff) == 'V') {
325 /* This is a VICEIOCTL call */
326 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
329 error = HandleIoctl(tvc, cmd, &data);
332 /* No-op call; just return. */
336 #endif /* AFS_AIX_ENV */
338 #if defined(AFS_SGI_ENV)
339 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
345 struct afs_ioctl data;
351 AFS_STATCNT(afs_ioctl);
352 if (((cmd >> 8) & 0xff) == 'V') {
353 /* This is a VICEIOCTL call */
354 error = copyin_afs_ioctl(arg, &data);
357 locked = ISAFS_GLOCK();
360 error = HandleIoctl(tvc, cmd, &data);
365 /* No-op call; just return. */
369 #endif /* AFS_SGI_ENV */
372 /* unlike most calls here, this one uses u.u_error to return error conditions,
373 since this is really an intercepted chapter 2 call, rather than a vnode
376 /* AFS_HPUX102 and up uses VNODE ioctl instead */
377 #ifndef AFS_HPUX102_ENV
378 #if !defined(AFS_SGI_ENV)
381 kioctl(fdes, com, arg, ext, arg2, arg3)
384 kioctl(fdes, com, arg, ext)
395 } u_uap, *uap = &u_uap;
399 struct afs_ioctl_sys {
405 afs_xioctl (uap, rvp)
406 struct afs_ioctl_sys *uap;
411 afs_xioctl (p, args, retval)
420 } *uap = (struct a *)args;
421 #else /* AFS_OSF_ENV */
422 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
428 afs_xioctl(p, uap, retval)
430 register struct ioctl_args *uap;
434 #ifdef AFS_LINUX22_ENV
435 struct afs_ioctl_sys {
439 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
440 unsigned int com, unsigned long arg)
442 struct afs_ioctl_sys ua, *uap = &ua;
444 int afs_xioctl (void)
450 } *uap = (struct a *)u.u_ap;
451 #endif /* AFS_LINUX22_ENV */
452 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
453 #endif /* AFS_OSF_ENV */
454 #endif /* AFS_SUN5_ENV */
456 #ifndef AFS_LINUX22_ENV
457 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
460 register struct file *fd;
463 #if defined(AFS_FBSD_ENV)
464 register struct filedesc *fdp;
466 register struct vcache *tvc;
467 register int ioctlDone = 0, code = 0;
469 AFS_STATCNT(afs_xioctl);
470 #if defined(AFS_FBSD_ENV)
472 if ((u_int)uap->fd >= fdp->fd_nfiles ||
473 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
475 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
478 #if defined(AFS_DARWIN_ENV)
479 if ((code=fdgetf(p, uap->fd, &fd)))
482 #ifdef AFS_LINUX22_ENV
496 if (setuerror(getf(uap->fd, &fd))) {
502 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
504 #else /* AFS_OSF_ENV */
506 #if defined(AFS_SUN57_ENV)
508 if (!fd) return(EBADF);
509 #elif defined(AFS_SUN54_ENV)
511 if (!fd) return(EBADF);
513 if (code = getf(uap->fd, &fd)) {
526 /* first determine whether this is any sort of vnode */
527 #ifdef AFS_LINUX22_ENV
532 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
534 if (fd->f_type == DTYPE_VNODE) {
536 /* good, this is a vnode; next see if it is an AFS vnode */
537 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
538 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
540 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
542 #endif /* AFS_LINUX22_ENV */
543 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
545 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
546 if (!tvc) { /* shouldn't happen with held gnodes */
551 /* This is an AFS vnode */
552 if (((uap->com >> 8) & 0xff) == 'V') {
553 register struct afs_ioctl *datap;
555 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
556 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
558 osi_FreeSmallSpace(datap);
560 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
563 #if defined(AFS_SUN5_ENV)
578 #else /* AFS_OSF_ENV */
582 #ifdef AFS_LINUX22_ENV
592 code = HandleIoctl(tvc, uap->com, datap);
593 osi_FreeSmallSpace(datap);
607 #if defined(AFS_LINUX22_ENV)
618 code = okioctl(fdes, com, arg, ext, arg2, arg3);
620 code = okioctl(fdes, com, arg, ext);
625 okioctl(fdes, com, arg, ext);
627 #if defined(AFS_SUN5_ENV)
628 #if defined(AFS_SUN57_ENV)
630 #elif defined(AFS_SUN54_ENV)
635 code = ioctl(uap, rvp);
637 #if defined(AFS_FBSD_ENV)
638 return ioctl(p, uap);
640 #if defined(AFS_DARWIN_ENV)
641 return ioctl(p, uap, retval);
644 code = ioctl(p, args, retval);
651 #else /* AFS_OSF_ENV */
652 #ifndef AFS_LINUX22_ENV
671 #ifdef AFS_LINUX22_ENV
674 #if defined(KERNEL_HAVE_SETUERROR)
677 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
678 return (getuerror() ? -1 : u.u_ioctlrv);
680 return getuerror() ? -1 : 0;
683 #endif /* AFS_LINUX22_ENV */
684 #endif /* AFS_SUN5_ENV */
685 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
689 #endif /* AFS_SGI_ENV */
690 #endif /* AFS_HPUX102_ENV */
692 #if defined(AFS_SGI_ENV)
693 /* "pioctl" system call entry point; just pass argument to the parameterized
702 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
706 AFS_STATCNT(afs_pioctl);
708 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
716 #endif /* AFS_SGI_ENV */
719 afs_pioctl(p, args, retval)
729 } *uap = (struct a *) args;
731 AFS_STATCNT(afs_pioctl);
732 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
735 #else /* AFS_OSF_ENV */
736 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
737 afs_pioctl(p, args, retval)
747 } *uap = (struct a *) args;
749 AFS_STATCNT(afs_pioctl);
750 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
753 #else /* AFS_OSF_ENV */
757 /* macro to avoid adding any more #ifdef's to pioctl code. */
758 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
759 #define PIOCTL_FREE_CRED() crfree(credp)
761 #define PIOCTL_FREE_CRED()
765 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
767 struct AFS_UCRED *credp;
769 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
770 afs_syscall_pioctl(path, com, cmarg, follow, credp)
771 struct AFS_UCRED *credp;
773 afs_syscall_pioctl(path, com, cmarg, follow)
781 struct afs_ioctl data;
782 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
783 register afs_int32 code = 0;
789 struct ucred *credp = crref(); /* don't free until done! */
791 #ifdef AFS_LINUX22_ENV
792 cred_t *credp = crref(); /* don't free until done! */
796 AFS_STATCNT(afs_syscall_pioctl);
797 if (follow) follow = 1; /* compat. with old venus */
798 code = copyin_afs_ioctl(cmarg, &data);
801 #if defined(KERNEL_HAVE_SETUERROR)
806 if ((com & 0xff) == PSetClientContext) {
807 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
808 return EINVAL; /* Not handling these yet. */
810 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
811 code = HandleClientContext(&data, &com, &foreigncreds, credp);
813 #if defined(AFS_HPUX101_ENV)
814 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
817 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
820 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
822 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
823 #endif /* AFS_SGI_ENV */
830 crfree(foreigncreds);
833 #if defined(KERNEL_HAVE_SETUERROR)
834 return (setuerror(code), code);
840 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
843 * We could have done without temporary setting the u.u_cred below
844 * (foreigncreds could be passed as param the pioctl modules)
845 * but calls such as afs_osi_suser() doesn't allow that since it
846 * references u.u_cred directly. We could, of course, do something
847 * like afs_osi_suser(cred) which, I think, is better since it
848 * generalizes and supports multi cred environments...
852 credp = foreigncreds;
855 tmpcred = crref(); /* XXX */
858 #if defined(AFS_HPUX101_ENV)
859 tmpcred = p_cred(u.u_procp);
860 set_p_cred(u.u_procp, foreigncreds);
863 tmpcred = OSI_GET_CURRENT_CRED();
864 OSI_SET_CURRENT_CRED(foreigncreds);
867 tmpcred = osi_curcred();
868 osi_curcred() = foreigncreds;
871 u.u_cred = foreigncreds;
872 #endif /* AFS_SGI64_ENV */
873 #endif /* AFS_HPUX101_ENV */
879 if ((com & 0xff) == 15) {
880 /* special case prefetch so entire pathname eval occurs in helper process.
881 otherwise, the pioctl call is essentially useless */
882 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
883 code = Prefetch(path, &data, follow,
884 foreigncreds ? foreigncreds : credp);
886 #if defined(AFS_HPUX101_ENV)
887 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
890 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
893 code = Prefetch(path, &data, follow, osi_curcred());
895 code = Prefetch(path, &data, follow, u.u_cred);
896 #endif /* AFS_SGI64_ENV */
897 #endif /* AFS_HPUX101_ENV */
900 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
903 crset(tmpcred); /* restore original credentials */
905 #if defined(AFS_HPUX101_ENV)
906 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
910 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
912 u.u_cred = tmpcred; /* restore original credentials */
915 #endif /* AFS_HPUX101_ENV */
916 crfree(foreigncreds);
919 #endif /* AFS_LINUX22_ENV */
921 #if defined(KERNEL_HAVE_SETUERROR)
922 return (setuerror(code), code);
930 code = lookupname(path, USR, follow, NULL, &vp,
931 foreigncreds ? foreigncreds : credp);
933 #ifdef AFS_LINUX22_ENV
934 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
936 vp = (struct vnode *)dp->d_inode;
938 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
939 #endif /* AFS_LINUX22_ENV */
940 #endif /* AFS_AIX41_ENV */
943 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
946 crset(tmpcred); /* restore original credentials */
948 #if defined(AFS_HPUX101_ENV)
949 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
951 #if !defined(AFS_SUN5_ENV)
953 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
955 u.u_cred = tmpcred; /* restore original credentials */
956 #endif /* AFS_SGI64_ENV */
958 #endif /* AFS_HPUX101_ENV */
959 crfree(foreigncreds);
962 #endif /* AFS_LINUX22_ENV */
964 #if defined(KERNEL_HAVE_SETUERROR)
965 return(setuerror(code), code);
973 /* now make the call if we were passed no file, or were passed an AFS file */
974 if (!vp || IsAfsVnode(vp)) {
976 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
977 * So, we must test in this part of the code. Also, must arrange to
978 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
979 * we hold gnodes, whose references hold our vcache entries.
982 gp = vp; /* remember for "put" */
983 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
988 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
992 struct ucred *cred1, *cred2;
995 cred1 = cred2 = foreigncreds;
997 cred1 = cred2 = credp;
999 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
1000 if (cred1 != cred2) {
1001 /* something changed the creds */
1006 #if defined(AFS_HPUX101_ENV)
1008 struct ucred *cred = p_cred(u.u_procp);
1009 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
1015 credp = OSI_GET_CURRENT_CRED();
1016 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
1019 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1020 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
1022 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
1024 #endif /* AFS_SGI_ENV */
1025 #endif /* AFS_HPUX101_ENV */
1026 #endif /* AFS_AIX41_ENV */
1027 #endif /* AFS_SUN5_ENV */
1029 #if defined(KERNEL_HAVE_SETUERROR)
1032 code = EINVAL; /* not in /afs */
1042 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
1044 #ifdef AFS_AIX41_ENV
1047 #if defined(AFS_HPUX101_ENV)
1048 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1050 #ifndef AFS_SUN5_ENV
1052 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1054 u.u_cred = tmpcred; /* restore original credentials */
1055 #endif /* ASF_SGI64_ENV */
1057 #endif /* AFS_HPUX101_ENV */
1058 crfree(foreigncreds);
1061 #endif /* AFS_LINUX22_ENV */
1063 #ifdef AFS_LINUX22_ENV
1066 AFS_RELE(vp); /* put vnode back */
1070 #if defined(KERNEL_HAVE_SETUERROR)
1073 return (getuerror());
1080 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1081 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1083 struct vrequest treq;
1084 register afs_int32 code;
1085 register afs_int32 function, device;
1086 afs_int32 inSize, outSize;
1087 char *inData, *outData;
1088 int (*(*pioctlSw))();
1090 struct afs_fakestat_state fakestate;
1092 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1093 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1094 AFS_STATCNT(HandlePioctl);
1095 if ((code = afs_InitReq(&treq, *acred))) return code;
1096 afs_InitFakeStat(&fakestate);
1098 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1100 afs_PutFakeStat(&fakestate);
1104 device = (acom & 0xff00) >> 8;
1106 case 'V': /* Original pioctl's */
1107 pioctlSw = VpioctlSw;
1108 pioctlSwSize = sizeof(VpioctlSw);
1110 case 'C': /* Coordinated/common pioctl's */
1111 pioctlSw = CpioctlSw;
1112 pioctlSwSize = sizeof(CpioctlSw);
1115 afs_PutFakeStat(&fakestate);
1118 function = acom & 0xff;
1119 if (function >= (pioctlSwSize / sizeof(char *))) {
1120 afs_PutFakeStat(&fakestate);
1121 return EINVAL; /* out of range */
1123 inSize = ablob->in_size;
1124 if (inSize >= PIGGYSIZE) return E2BIG;
1125 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1127 AFS_COPYIN(ablob->in, inData, inSize, code);
1128 inData[inSize]='\0';
1132 osi_FreeLargeSpace(inData);
1133 afs_PutFakeStat(&fakestate);
1136 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1138 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1139 osi_FreeLargeSpace(inData);
1140 if (code == 0 && ablob->out_size > 0) {
1141 if (outSize > ablob->out_size) outSize = ablob->out_size;
1142 if (outSize >= PIGGYSIZE) code = E2BIG;
1144 outData[outSize]='\0';
1145 AFS_COPYOUT(outData, ablob->out, outSize, code);
1148 osi_FreeLargeSpace(outData);
1149 afs_PutFakeStat(&fakestate);
1150 return afs_CheckCode(code, &treq, 41);
1153 DECL_PIOCTL(PGetFID)
1155 register afs_int32 code;
1157 AFS_STATCNT(PGetFID);
1158 if (!avc) return EINVAL;
1159 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1160 *aoutSize = sizeof(struct VenusFid);
1164 DECL_PIOCTL(PSetAcl)
1166 register afs_int32 code;
1168 struct AFSOpaque acl;
1169 struct AFSVolSync tsync;
1170 struct AFSFetchStatus OutStatus;
1173 AFS_STATCNT(PSetAcl);
1176 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1179 acl.AFSOpaque_val = ain;
1181 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1183 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1185 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1186 &acl, &OutStatus, &tsync);
1192 (afs_Analyze(tconn, code, &avc->fid, areq,
1193 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1195 /* now we've forgotten all of the access info */
1196 ObtainWriteLock(&afs_xcbhash, 455);
1198 afs_DequeueCallback(avc);
1199 avc->states &= ~(CStatd | CUnique);
1200 ReleaseWriteLock(&afs_xcbhash);
1201 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1202 osi_dnlc_purgedp(avc);
1206 int afs_defaultAsynchrony = 0;
1208 DECL_PIOCTL(PStoreBehind)
1211 struct sbstruct *sbr;
1213 sbr = (struct sbstruct *)ain;
1214 if (sbr->sb_default != -1) {
1215 if (afs_osi_suser(*acred))
1216 afs_defaultAsynchrony = sbr->sb_default;
1220 if (avc && (sbr->sb_thisfile != -1)) {
1221 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1222 areq, DONT_CHECK_MODE_BITS))
1223 avc->asynchrony = sbr->sb_thisfile;
1227 *aoutSize = sizeof(struct sbstruct);
1228 sbr = (struct sbstruct *)aout;
1229 sbr->sb_default = afs_defaultAsynchrony;
1231 sbr->sb_thisfile = avc->asynchrony;
1237 DECL_PIOCTL(PGCPAGs)
1239 if (!afs_osi_suser(*acred)) {
1242 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1246 DECL_PIOCTL(PGetAcl)
1248 struct AFSOpaque acl;
1249 struct AFSVolSync tsync;
1250 struct AFSFetchStatus OutStatus;
1256 AFS_STATCNT(PGetAcl);
1257 if (!avc) return EINVAL;
1258 Fid.Volume = avc->fid.Fid.Volume;
1259 Fid.Vnode = avc->fid.Fid.Vnode;
1260 Fid.Unique = avc->fid.Fid.Unique;
1261 if (avc->states & CForeign) {
1263 * For a dfs xlator acl we have a special hack so that the
1264 * xlator will distinguish which type of acl will return. So
1265 * we currently use the top 2-bytes (vals 0-4) to tell which
1266 * type of acl to bring back. Horrible hack but this will
1267 * cause the least number of changes to code size and interfaces.
1269 if (Fid.Vnode & 0xc0000000)
1271 Fid.Vnode |= (ainSize << 30);
1273 acl.AFSOpaque_val = aout;
1275 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1278 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1280 code = RXAFS_FetchACL(tconn->id, &Fid,
1281 &acl, &OutStatus, &tsync);
1287 (afs_Analyze(tconn, code, &avc->fid, areq,
1288 AFS_STATS_FS_RPCIDX_FETCHACL,
1289 SHARED_LOCK, NULL));
1292 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1305 AFS_STATCNT(PBogus);
1309 DECL_PIOCTL(PGetFileCell)
1311 register struct cell *tcell;
1313 AFS_STATCNT(PGetFileCell);
1314 if (!avc) return EINVAL;
1315 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1316 if (!tcell) return ESRCH;
1317 strcpy(aout, tcell->cellName);
1318 afs_PutCell(tcell, READ_LOCK);
1319 *aoutSize = strlen(aout) + 1;
1323 DECL_PIOCTL(PGetWSCell)
1325 struct cell *tcell = NULL;
1327 AFS_STATCNT(PGetWSCell);
1328 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1329 return EIO; /* Inappropriate ioctl for device */
1331 tcell = afs_GetPrimaryCell(READ_LOCK);
1332 if (!tcell) /* no primary cell? */
1334 strcpy(aout, tcell->cellName);
1335 *aoutSize = strlen(aout) + 1;
1336 afs_PutCell(tcell, READ_LOCK);
1340 DECL_PIOCTL(PGetUserCell)
1342 register afs_int32 i;
1343 register struct unixuser *tu;
1344 register struct cell *tcell;
1346 AFS_STATCNT(PGetUserCell);
1347 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1348 return EIO; /* Inappropriate ioctl for device */
1350 /* return the cell name of the primary cell for this user */
1351 i = UHash(areq->uid);
1352 ObtainWriteLock(&afs_xuser,224);
1353 for(tu = afs_users[i]; tu; tu = tu->next) {
1354 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1356 ReleaseWriteLock(&afs_xuser);
1361 tcell = afs_GetCell(tu->cell, READ_LOCK);
1362 afs_PutUser(tu, WRITE_LOCK);
1363 if (!tcell) return ESRCH;
1365 strcpy(aout, tcell->cellName);
1366 afs_PutCell(tcell, READ_LOCK);
1367 *aoutSize = strlen(aout)+1; /* 1 for the null */
1371 ReleaseWriteLock(&afs_xuser);
1378 DECL_PIOCTL(PSetTokens)
1381 register struct unixuser *tu;
1382 struct ClearToken clear;
1383 register struct cell *tcell;
1386 struct vrequest treq;
1387 afs_int32 flag, set_parent_pag = 0;
1389 AFS_STATCNT(PSetTokens);
1390 if (!afs_resourceinit_flag) {
1393 memcpy((char *)&i, ain, sizeof(afs_int32));
1394 ain += sizeof(afs_int32);
1395 stp = ain; /* remember where the ticket is */
1396 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1397 if (i > MAXKTCTICKETLEN) return EINVAL;
1399 ain += i; /* skip over ticket */
1400 memcpy((char *)&i, ain, sizeof(afs_int32));
1401 ain += sizeof(afs_int32);
1402 if (i != sizeof(struct ClearToken)) {
1405 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1406 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1407 ain += sizeof(struct ClearToken);
1408 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1409 /* still stuff left? we've got primary flag and cell name. Set these */
1410 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1411 ain += sizeof(afs_int32); /* skip id field */
1412 /* rest is cell name, look it up */
1413 /* some versions of gcc appear to need != 0 in order to get this right */
1414 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1418 tcell = afs_GetCellByName(ain, READ_LOCK);
1419 if (!tcell) goto nocell;
1422 /* default to primary cell, primary id */
1423 flag = 1; /* primary id */
1424 tcell = afs_GetPrimaryCell(READ_LOCK);
1425 if (!tcell) goto nocell;
1428 afs_PutCell(tcell, READ_LOCK);
1429 if (set_parent_pag) {
1431 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1432 #if defined(AFS_DARWIN_ENV)
1433 struct proc *p=current_proc(); /* XXX */
1435 struct proc *p=curproc; /* XXX */
1437 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1438 p->p_pid, p->p_comm);
1439 if (!setpag(p, acred, -1, &pag, 1)) {
1442 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1444 if (!setpag(acred, -1, &pag, 1)) {
1447 afs_InitReq(&treq, *acred);
1451 /* now we just set the tokens */
1452 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1453 tu->vid = clear.ViceId;
1454 if (tu->stp != NULL) {
1455 afs_osi_Free(tu->stp, tu->stLen);
1457 tu->stp = (char *) afs_osi_Alloc(stLen);
1459 memcpy(tu->stp, stp, stLen);
1462 afs_stats_cmfullperf.authent.TicketUpdates++;
1463 afs_ComputePAGStats();
1464 #endif /* AFS_NOSTATS */
1465 tu->states |= UHasTokens;
1466 tu->states &= ~UTokensBad;
1467 afs_SetPrimary(tu, flag);
1468 tu->tokenTime =osi_Time();
1469 afs_ResetUserConns(tu);
1470 afs_PutUser(tu, WRITE_LOCK);
1485 DECL_PIOCTL(PGetVolumeStatus)
1488 char offLineMsg[256];
1490 register struct conn *tc;
1491 register afs_int32 code;
1492 struct VolumeStatus volstat;
1494 char *Name, *OfflineMsg, *MOTD;
1497 AFS_STATCNT(PGetVolumeStatus);
1498 if (!avc) return EINVAL;
1500 OfflineMsg = offLineMsg;
1503 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1505 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1507 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1508 &Name, &OfflineMsg, &MOTD);
1514 (afs_Analyze(tc, code, &avc->fid, areq,
1515 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1516 SHARED_LOCK, NULL));
1518 if (code) return code;
1519 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1521 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1522 cp += sizeof(VolumeStatus);
1523 strcpy(cp, volName);
1524 cp += strlen(volName)+1;
1525 strcpy(cp, offLineMsg);
1526 cp += strlen(offLineMsg)+1;
1528 cp += strlen(motd)+1;
1529 *aoutSize = (cp - aout);
1533 DECL_PIOCTL(PSetVolumeStatus)
1536 char offLineMsg[256];
1538 register struct conn *tc;
1539 register afs_int32 code;
1540 struct AFSFetchVolumeStatus volstat;
1541 struct AFSStoreVolumeStatus storeStat;
1542 register struct volume *tvp;
1546 AFS_STATCNT(PSetVolumeStatus);
1547 if (!avc) return EINVAL;
1549 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1551 if (tvp->states & (VRO | VBackup)) {
1552 afs_PutVolume(tvp, READ_LOCK);
1555 afs_PutVolume(tvp, READ_LOCK);
1558 /* Copy the junk out, using cp as a roving pointer. */
1560 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1561 cp += sizeof(AFSFetchVolumeStatus);
1562 if (strlen(cp) >= sizeof(volName))
1564 strcpy(volName, cp);
1565 cp += strlen(volName)+1;
1566 if (strlen(cp) >= sizeof(offLineMsg))
1568 strcpy(offLineMsg, cp);
1569 cp += strlen(offLineMsg)+1;
1570 if (strlen(cp) >= sizeof(motd))
1574 if (volstat.MinQuota != -1) {
1575 storeStat.MinQuota = volstat.MinQuota;
1576 storeStat.Mask |= AFS_SETMINQUOTA;
1578 if (volstat.MaxQuota != -1) {
1579 storeStat.MaxQuota = volstat.MaxQuota;
1580 storeStat.Mask |= AFS_SETMAXQUOTA;
1583 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1585 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1587 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1588 &storeStat, volName, offLineMsg, motd);
1594 (afs_Analyze(tc, code, &avc->fid, areq,
1595 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1596 SHARED_LOCK, NULL));
1598 if (code) return code;
1599 /* we are sending parms back to make compat. with prev system. should
1600 change interface later to not ask for current status, just set new status */
1602 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1603 cp += sizeof(VolumeStatus);
1604 strcpy(cp, volName);
1605 cp += strlen(volName)+1;
1606 strcpy(cp, offLineMsg);
1607 cp += strlen(offLineMsg)+1;
1609 cp += strlen(motd)+1;
1610 *aoutSize = cp - aout;
1616 AFS_STATCNT(PFlush);
1617 if (!avc) return EINVAL;
1618 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1619 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1621 ObtainWriteLock(&avc->lock,225);
1622 ObtainWriteLock(&afs_xcbhash, 456);
1623 afs_DequeueCallback(avc);
1624 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1625 ReleaseWriteLock(&afs_xcbhash);
1626 /* now find the disk cache entries */
1627 afs_TryToSmush(avc, *acred, 1);
1628 osi_dnlc_purgedp(avc);
1629 afs_symhint_inval(avc);
1630 if (avc->linkData && !(avc->states & CCore)) {
1631 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1632 avc->linkData = NULL;
1634 ReleaseWriteLock(&avc->lock);
1635 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1636 afs_BozonUnlock(&avc->pvnLock, avc);
1641 DECL_PIOCTL(PNewStatMount)
1643 register afs_int32 code;
1644 register struct vcache *tvc;
1645 register struct dcache *tdc;
1646 struct VenusFid tfid;
1648 struct sysname_info sysState;
1649 afs_size_t offset, len;
1651 AFS_STATCNT(PNewStatMount);
1652 if (!avc) return EINVAL;
1653 code = afs_VerifyVCache(avc, areq);
1654 if (code) return code;
1655 if (vType(avc) != VDIR) {
1658 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1659 if (!tdc) return ENOENT;
1660 Check_AtSys(avc, ain, &sysState, areq);
1661 ObtainReadLock(&tdc->lock);
1663 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1664 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1665 ReleaseReadLock(&tdc->lock);
1666 afs_PutDCache(tdc); /* we're done with the data */
1667 bufp = sysState.name;
1671 tfid.Cell = avc->fid.Cell;
1672 tfid.Fid.Volume = avc->fid.Fid.Volume;
1673 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1674 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1676 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1682 if (tvc->mvstat != 1) {
1687 ObtainWriteLock(&tvc->lock,226);
1688 code = afs_HandleLink(tvc, areq);
1690 if (tvc->linkData) {
1691 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1694 /* we have the data */
1695 strcpy(aout, tvc->linkData);
1696 *aoutSize = strlen(tvc->linkData)+1;
1701 ReleaseWriteLock(&tvc->lock);
1704 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1708 DECL_PIOCTL(PGetTokens)
1710 register struct cell *tcell;
1711 register afs_int32 i;
1712 register struct unixuser *tu;
1717 AFS_STATCNT(PGetTokens);
1718 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1719 return EIO; /* Inappropriate ioctl for device */
1721 /* weird interface. If input parameter is present, it is an integer and
1722 we're supposed to return the parm'th tokens for this unix uid.
1723 If not present, we just return tokens for cell 1.
1724 If counter out of bounds, return EDOM.
1725 If no tokens for the particular cell, return ENOTCONN.
1726 Also, if this mysterious parm is present, we return, along with the
1727 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1728 at the end, in that order.
1730 if ((newStyle = (ainSize > 0))) {
1731 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1733 i = UHash(areq->uid);
1734 ObtainReadLock(&afs_xuser);
1735 for(tu = afs_users[i]; tu; tu=tu->next) {
1737 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1738 if (iterator-- == 0) break; /* are we done yet? */
1742 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1747 * No need to hold a read lock on each user entry
1751 ReleaseReadLock(&afs_xuser);
1756 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1757 tu->states |= (UTokensBad | UNeedsReset);
1758 afs_PutUser(tu, READ_LOCK);
1761 /* use iterator for temp */
1763 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1764 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1765 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1766 cp += sizeof(afs_int32);
1767 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1769 iterator = sizeof(struct ClearToken);
1770 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1771 cp += sizeof(afs_int32);
1772 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1773 cp += sizeof(struct ClearToken);
1775 /* put out primary id and cell name, too */
1776 iterator = (tu->states & UPrimary ? 1 : 0);
1777 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1778 cp += sizeof(afs_int32);
1779 tcell = afs_GetCell(tu->cell, READ_LOCK);
1781 strcpy(cp, tcell->cellName);
1782 cp += strlen(tcell->cellName)+1;
1783 afs_PutCell(tcell, READ_LOCK);
1787 *aoutSize = cp - aout;
1788 afs_PutUser(tu, READ_LOCK);
1794 register afs_int32 i;
1795 register struct unixuser *tu;
1797 AFS_STATCNT(PUnlog);
1798 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1799 return EIO; /* Inappropriate ioctl for device */
1801 i = UHash(areq->uid);
1802 ObtainWriteLock(&afs_xuser,227);
1803 for(tu=afs_users[i]; tu; tu=tu->next) {
1804 if (tu->uid == areq->uid) {
1806 tu->states &= ~UHasTokens;
1807 /* security is not having to say you're sorry */
1808 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1810 ReleaseWriteLock(&afs_xuser);
1811 /* We have to drop the lock over the call to afs_ResetUserConns, since
1812 * it obtains the afs_xvcache lock. We could also keep the lock, and
1813 * modify ResetUserConns to take parm saying we obtained the lock
1814 * already, but that is overkill. By keeping the "tu" pointer
1815 * held over the released lock, we guarantee that we won't lose our
1816 * place, and that we'll pass over every user conn that existed when
1817 * we began this call.
1819 afs_ResetUserConns(tu);
1821 ObtainWriteLock(&afs_xuser,228);
1823 /* set the expire times to 0, causes
1824 * afs_GCUserData to remove this entry
1826 tu->ct.EndTimestamp = 0;
1828 #endif /* UKERNEL */
1831 ReleaseWriteLock(&afs_xuser);
1835 DECL_PIOCTL(PMariner)
1837 afs_int32 newHostAddr;
1838 afs_int32 oldHostAddr;
1840 AFS_STATCNT(PMariner);
1842 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1844 oldHostAddr = 0xffffffff; /* disabled */
1846 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1847 if (newHostAddr == 0xffffffff) {
1848 /* disable mariner operations */
1851 else if (newHostAddr) {
1853 afs_marinerHost = newHostAddr;
1855 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1856 *aoutSize = sizeof(afs_int32);
1860 DECL_PIOCTL(PCheckServers)
1862 register char *cp = 0;
1864 register struct server *ts;
1865 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1867 struct chservinfo *pcheck;
1869 AFS_STATCNT(PCheckServers);
1871 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1872 return EIO; /* Inappropriate ioctl for device */
1874 if (*lp == 0x12345678) { /* For afs3.3 version */
1875 pcheck=(struct chservinfo *)ain;
1876 if (pcheck->tinterval >= 0) {
1878 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1879 *aoutSize = sizeof(afs_int32);
1880 if (pcheck->tinterval > 0) {
1881 if (!afs_osi_suser(*acred))
1883 PROBE_INTERVAL=pcheck->tinterval;
1889 temp=pcheck->tflags;
1890 cp = pcheck->tbuffer;
1891 } else { /* For pre afs3.3 versions */
1892 memcpy((char *)&temp, ain, sizeof(afs_int32));
1893 cp = ain+sizeof(afs_int32);
1894 if (ainSize > sizeof(afs_int32))
1899 * 1: fast check, don't contact servers.
1900 * 2: local cell only.
1903 /* have cell name, too */
1904 cellp = afs_GetCellByName(cp, READ_LOCK);
1905 if (!cellp) return ENOENT;
1908 if (!cellp && (temp & 2)) {
1909 /* use local cell */
1910 cellp = afs_GetPrimaryCell(READ_LOCK);
1912 if (!(temp & 1)) { /* if not fast, call server checker routine */
1913 afs_CheckServers(1, cellp); /* check down servers */
1914 afs_CheckServers(0, cellp); /* check up servers */
1916 /* now return the current down server list */
1918 ObtainReadLock(&afs_xserver);
1919 for(i=0;i<NSERVERS;i++) {
1920 for(ts = afs_servers[i]; ts; ts=ts->next) {
1921 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1922 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1923 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1924 cp += sizeof(afs_int32);
1928 ReleaseReadLock(&afs_xserver);
1929 if (cellp) afs_PutCell(cellp, READ_LOCK);
1930 *aoutSize = cp - aout;
1934 DECL_PIOCTL(PCheckVolNames)
1936 AFS_STATCNT(PCheckVolNames);
1937 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1938 return EIO; /* Inappropriate ioctl for device */
1940 afs_CheckRootVolume();
1941 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1942 AFS_VOLCHECK_EXPIRED |
1944 AFS_VOLCHECK_MTPTS);
1948 DECL_PIOCTL(PCheckAuth)
1953 struct unixuser *tu;
1956 AFS_STATCNT(PCheckAuth);
1957 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1958 return EIO; /* Inappropriate ioctl for device */
1961 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1962 if (!tu) retValue = EACCES;
1964 /* we have a user */
1965 ObtainReadLock(&afs_xsrvAddr);
1966 ObtainReadLock(&afs_xconn);
1968 /* any tokens set? */
1969 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1970 /* all connections in cell 1 working? */
1971 for(i=0;i<NSERVERS;i++) {
1972 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1973 for (tc = sa->conns; tc; tc=tc->next) {
1974 if (tc->user == tu && (tu->states & UTokensBad))
1979 ReleaseReadLock(&afs_xsrvAddr);
1980 ReleaseReadLock(&afs_xconn);
1981 afs_PutUser(tu, READ_LOCK);
1983 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1984 *aoutSize = sizeof(afs_int32);
1988 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1991 register afs_int32 code;
1992 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1998 AFS_STATCNT(Prefetch);
1999 if (!apath) return EINVAL;
2000 tp = osi_AllocLargeSpace(1024);
2001 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2003 osi_FreeLargeSpace(tp);
2006 if (afs_BBusy()) { /* do this as late as possible */
2007 osi_FreeLargeSpace(tp);
2008 return EWOULDBLOCK; /* pretty close */
2010 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
2011 (afs_size_t) 0, (afs_size_t) 0, tp);
2015 DECL_PIOCTL(PFindVolume)
2017 register struct volume *tvp;
2018 register struct server *ts;
2019 register afs_int32 i;
2022 AFS_STATCNT(PFindVolume);
2023 if (!avc) return EINVAL;
2024 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2027 for(i=0;i<MAXHOSTS;i++) {
2028 ts = tvp->serverHost[i];
2030 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2031 cp += sizeof(afs_int32);
2034 /* still room for terminating NULL, add it on */
2035 ainSize = 0; /* reuse vbl */
2036 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2037 cp += sizeof(afs_int32);
2039 *aoutSize = cp - aout;
2040 afs_PutVolume(tvp, READ_LOCK);
2046 DECL_PIOCTL(PViceAccess)
2048 register afs_int32 code;
2051 AFS_STATCNT(PViceAccess);
2052 if (!avc) return EINVAL;
2053 code = afs_VerifyVCache(avc, areq);
2054 if (code) return code;
2055 memcpy((char *)&temp, ain, sizeof(afs_int32));
2056 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2061 DECL_PIOCTL(PSetCacheSize)
2066 AFS_STATCNT(PSetCacheSize);
2067 if (!afs_osi_suser(*acred))
2069 /* too many things are setup initially in mem cache version */
2070 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2071 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2072 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2074 if (newValue < afs_min_cache)
2075 afs_cacheBlocks = afs_min_cache;
2077 afs_cacheBlocks = newValue;
2079 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2080 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2081 afs_MaybeWakeupTruncateDaemon();
2082 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2083 afs_osi_Wait(1000, 0, 0);
2084 afs_MaybeWakeupTruncateDaemon();
2089 #define MAXGCSTATS 16
2090 DECL_PIOCTL(PGetCacheSize)
2092 afs_int32 results[MAXGCSTATS];
2094 AFS_STATCNT(PGetCacheSize);
2095 memset((char *)results, 0, sizeof(results));
2096 results[0] = afs_cacheBlocks;
2097 results[1] = afs_blocksUsed;
2098 memcpy(aout, (char *)results, sizeof(results));
2099 *aoutSize = sizeof(results);
2103 DECL_PIOCTL(PRemoveCallBack)
2105 register struct conn *tc;
2106 register afs_int32 code;
2107 struct AFSCallBack CallBacks_Array[1];
2108 struct AFSCBFids theFids;
2109 struct AFSCBs theCBs;
2112 AFS_STATCNT(PRemoveCallBack);
2113 if (!avc) return EINVAL;
2114 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2115 ObtainWriteLock(&avc->lock,229);
2116 theFids.AFSCBFids_len = 1;
2117 theCBs.AFSCBs_len = 1;
2118 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2119 theCBs.AFSCBs_val = CallBacks_Array;
2120 CallBacks_Array[0].CallBackType = CB_DROPPED;
2121 if (avc->callback) {
2123 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2125 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2127 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2131 /* don't set code on failure since we wouldn't use it */
2133 (afs_Analyze(tc, code, &avc->fid, areq,
2134 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2135 SHARED_LOCK, NULL));
2137 ObtainWriteLock(&afs_xcbhash, 457);
2138 afs_DequeueCallback(avc);
2140 avc->states &= ~(CStatd | CUnique);
2141 ReleaseWriteLock(&afs_xcbhash);
2142 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2143 osi_dnlc_purgedp(avc);
2145 ReleaseWriteLock(&avc->lock);
2149 DECL_PIOCTL(PNewCell)
2151 /* create a new cell */
2152 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2153 register struct cell *tcell;
2154 char *newcell=0, *linkedcell=0, *tp= ain;
2155 register afs_int32 code, linkedstate=0, ls;
2156 u_short fsport = 0, vlport = 0;
2159 AFS_STATCNT(PNewCell);
2160 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2161 return EIO; /* Inappropriate ioctl for device */
2163 if (!afs_osi_suser(*acred))
2166 memcpy((char *)&magic, tp, sizeof(afs_int32));
2167 tp += sizeof(afs_int32);
2168 if (magic != 0x12345678)
2171 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2172 * server addresses while the 3.5 fs newcell command passes
2173 * MAXHOSTS. To figure out which is which, check if the cellname
2176 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2177 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2179 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2180 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2181 tp += (scount * sizeof(afs_int32));
2183 lp = (afs_int32 *)tp;
2186 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2187 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2188 tp += (3 * sizeof(afs_int32));
2190 if ((ls = *lp) & 1) {
2191 linkedcell = tp + strlen(newcell)+1;
2192 linkedstate |= CLinkedCell;
2195 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2196 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2201 DECL_PIOCTL(PNewAlias)
2203 /* create a new cell alias */
2205 register afs_int32 code;
2206 char *realName, *aliasName;
2208 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2209 return EIO; /* Inappropriate ioctl for device */
2211 if (!afs_osi_suser(*acred))
2215 tp += strlen(aliasName) + 1;
2218 code = afs_NewCellAlias(aliasName, realName);
2223 DECL_PIOCTL(PListCells)
2225 afs_int32 whichCell;
2226 register struct cell *tcell=0;
2227 register afs_int32 i;
2228 register char *cp, *tp = ain;
2230 AFS_STATCNT(PListCells);
2231 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2232 return EIO; /* Inappropriate ioctl for device */
2234 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2235 tp += sizeof(afs_int32);
2236 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2239 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2240 for(i=0;i<MAXCELLHOSTS;i++) {
2241 if (tcell->cellHosts[i] == 0) break;
2242 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2243 cp += sizeof(afs_int32);
2245 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2246 strcpy(cp, tcell->cellName);
2247 cp += strlen(tcell->cellName)+1;
2248 *aoutSize = cp - aout;
2249 afs_PutCell(tcell, READ_LOCK);
2251 if (tcell) return 0;
2255 DECL_PIOCTL(PListAliases)
2257 afs_int32 whichAlias;
2258 register struct cell_alias *tcalias=0;
2259 register char *cp, *tp = ain;
2261 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2262 return EIO; /* Inappropriate ioctl for device */
2263 if (ainSize < sizeof(afs_int32))
2266 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2267 tp += sizeof(afs_int32);
2269 tcalias = afs_GetCellAlias(whichAlias);
2272 strcpy(cp, tcalias->alias);
2273 cp += strlen(tcalias->alias)+1;
2274 strcpy(cp, tcalias->cell);
2275 cp += strlen(tcalias->cell)+1;
2276 *aoutSize = cp - aout;
2277 afs_PutCellAlias(tcalias);
2279 if (tcalias) return 0;
2283 DECL_PIOCTL(PRemoveMount)
2285 register afs_int32 code;
2287 struct sysname_info sysState;
2288 afs_size_t offset, len;
2289 register struct conn *tc;
2290 register struct dcache *tdc;
2291 register struct vcache *tvc;
2292 struct AFSFetchStatus OutDirStatus;
2293 struct VenusFid tfid;
2294 struct AFSVolSync tsync;
2298 /* "ain" is the name of the file in this dir to remove */
2300 AFS_STATCNT(PRemoveMount);
2301 if (!avc) return EINVAL;
2302 code = afs_VerifyVCache(avc, areq);
2303 if (code) return code;
2304 if (vType(avc) != VDIR) return ENOTDIR;
2306 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2307 if (!tdc) return ENOENT;
2308 Check_AtSys(avc, ain, &sysState, areq);
2309 ObtainReadLock(&tdc->lock);
2311 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2312 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2313 ReleaseReadLock(&tdc->lock);
2314 bufp = sysState.name;
2319 tfid.Cell = avc->fid.Cell;
2320 tfid.Fid.Volume = avc->fid.Fid.Volume;
2321 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2322 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2324 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2331 if (tvc->mvstat != 1) {
2337 ObtainWriteLock(&tvc->lock,230);
2338 code = afs_HandleLink(tvc, areq);
2340 if (tvc->linkData) {
2341 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2346 ReleaseWriteLock(&tvc->lock);
2347 osi_dnlc_purgedp(tvc);
2353 ObtainWriteLock(&avc->lock,231);
2354 osi_dnlc_remove(avc, bufp, tvc);
2356 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2358 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2360 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2361 bufp, &OutDirStatus, &tsync);
2367 (afs_Analyze(tc, code, &avc->fid, areq,
2368 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2369 SHARED_LOCK, NULL));
2372 if (tdc) afs_PutDCache(tdc);
2373 ReleaseWriteLock(&avc->lock);
2377 /* we have the thing in the cache */
2378 ObtainWriteLock(&tdc->lock, 661);
2379 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2380 /* we can do it locally */
2381 code = afs_dir_Delete(&tdc->f.inode, bufp);
2383 ZapDCE(tdc); /* surprise error -- invalid value */
2384 DZap(&tdc->f.inode);
2387 ReleaseWriteLock(&tdc->lock);
2388 afs_PutDCache(tdc); /* drop ref count */
2390 avc->states &= ~CUnique; /* For the dfs xlator */
2391 ReleaseWriteLock(&avc->lock);
2394 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2398 DECL_PIOCTL(PVenusLogging)
2400 return EINVAL; /* OBSOLETE */
2403 DECL_PIOCTL(PGetCellStatus)
2405 register struct cell *tcell;
2408 AFS_STATCNT(PGetCellStatus);
2409 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2410 return EIO; /* Inappropriate ioctl for device */
2412 tcell = afs_GetCellByName(ain, READ_LOCK);
2413 if (!tcell) return ENOENT;
2414 temp = tcell->states;
2415 afs_PutCell(tcell, READ_LOCK);
2416 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2417 *aoutSize = sizeof(afs_int32);
2421 DECL_PIOCTL(PSetCellStatus)
2423 register struct cell *tcell;
2426 if (!afs_osi_suser(*acred))
2428 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2429 return EIO; /* Inappropriate ioctl for device */
2431 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2432 if (!tcell) return ENOENT;
2433 memcpy((char *)&temp, ain, sizeof(afs_int32));
2435 tcell->states |= CNoSUID;
2437 tcell->states &= ~CNoSUID;
2438 afs_PutCell(tcell, WRITE_LOCK);
2442 DECL_PIOCTL(PFlushVolumeData)
2444 register afs_int32 i;
2445 register struct dcache *tdc;
2446 register struct vcache *tvc;
2447 register struct volume *tv;
2448 afs_int32 cell, volume;
2450 AFS_STATCNT(PFlushVolumeData);
2453 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2454 return EIO; /* Inappropriate ioctl for device */
2456 volume = avc->fid.Fid.Volume; /* who to zap */
2457 cell = avc->fid.Cell;
2460 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2461 * the vcaches associated with the volume.
2463 ObtainReadLock(&afs_xvcache);
2464 for(i = 0; i < VCSIZE; i++) {
2465 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2466 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2467 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2468 VN_HOLD(AFSTOV(tvc));
2470 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2476 ReleaseReadLock(&afs_xvcache);
2477 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2478 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2480 ObtainWriteLock(&tvc->lock,232);
2482 ObtainWriteLock(&afs_xcbhash, 458);
2483 afs_DequeueCallback(tvc);
2484 tvc->states &= ~(CStatd | CDirty);
2485 ReleaseWriteLock(&afs_xcbhash);
2486 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2487 osi_dnlc_purgedp(tvc);
2488 afs_TryToSmush(tvc, *acred, 1);
2489 ReleaseWriteLock(&tvc->lock);
2490 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2491 afs_BozonUnlock(&tvc->pvnLock, tvc);
2493 ObtainReadLock(&afs_xvcache);
2494 /* our tvc ptr is still good until now */
2499 ReleaseReadLock(&afs_xvcache);
2502 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2503 for(i=0;i<afs_cacheFiles;i++) {
2504 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2505 tdc = afs_GetDSlot(i, NULL);
2506 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2507 ReleaseReadLock(&tdc->tlock);
2508 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2509 if (! (afs_indexFlags[i] & IFDataMod)) {
2510 /* if the file is modified, but has a ref cnt of only 1, then
2511 someone probably has the file open and is writing into it.
2512 Better to skip flushing such a file, it will be brought back
2513 immediately on the next write anyway.
2515 If we *must* flush, then this code has to be rearranged to call
2516 afs_storeAllSegments() first */
2517 afs_FlushDCache(tdc);
2521 ReleaseReadLock(&tdc->tlock);
2523 afs_PutDCache(tdc); /* bumped by getdslot */
2525 MReleaseWriteLock(&afs_xdcache);
2527 ObtainReadLock(&afs_xvolume);
2528 for (i=0;i<NVOLS;i++) {
2529 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2530 if (tv->volume == volume) {
2531 afs_ResetVolumeInfo(tv);
2536 ReleaseReadLock(&afs_xvolume);
2538 /* probably, a user is doing this, probably, because things are screwed up.
2539 * maybe it's the dnlc's fault? */
2546 DECL_PIOCTL(PGetVnodeXStatus)
2548 register afs_int32 code;
2549 struct vcxstat stat;
2552 /* AFS_STATCNT(PGetVnodeXStatus); */
2553 if (!avc) return EINVAL;
2554 code = afs_VerifyVCache(avc, areq);
2555 if (code) return code;
2556 if (vType(avc) == VDIR)
2557 mode = PRSFS_LOOKUP;
2560 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2562 stat.fid = avc->fid;
2563 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2564 stat.lock = avc->lock;
2565 stat.parentVnode = avc->parentVnode;
2566 stat.parentUnique = avc->parentUnique;
2567 hset(stat.flushDV, avc->flushDV);
2568 hset(stat.mapDV, avc->mapDV);
2569 stat.truncPos = avc->truncPos;
2570 { /* just grab the first two - won't break anything... */
2571 struct axscache *ac;
2573 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2574 stat.randomUid[i] = ac->uid;
2575 stat.randomAccess[i] = ac->axess;
2578 stat.callback = afs_data_pointer_to_int32(avc->callback);
2579 stat.cbExpires = avc->cbExpires;
2580 stat.anyAccess = avc->anyAccess;
2581 stat.opens = avc->opens;
2582 stat.execsOrWriters = avc->execsOrWriters;
2583 stat.flockCount = avc->flockCount;
2584 stat.mvstat = avc->mvstat;
2585 stat.states = avc->states;
2586 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2587 *aoutSize = sizeof(struct vcxstat);
2592 /* We require root for local sysname changes, but not for remote */
2593 /* (since we don't really believe remote uids anyway) */
2594 /* outname[] shouldn't really be needed- this is left as an excercise */
2595 /* for the reader. */
2596 DECL_PIOCTL(PSetSysName)
2598 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2599 int setsysname, foundname=0;
2600 register struct afs_exporter *exporter;
2601 register struct unixuser *au;
2602 register afs_int32 pag, error;
2606 AFS_STATCNT(PSetSysName);
2607 if (!afs_globalVFS) {
2608 /* Afsd is NOT running; disable it */
2609 #if defined(KERNEL_HAVE_SETUERROR)
2610 return (setuerror(EINVAL), EINVAL);
2615 memset(inname, 0, MAXSYSNAME);
2616 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2617 ain += sizeof(afs_int32);
2621 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2623 for(cp = ain,count = 0;count < setsysname;count++) {
2624 /* won't go past end of ain since maxsysname*num < ain length */
2626 if (t >= MAXSYSNAME || t <= 0)
2628 /* check for names that can shoot us in the foot */
2629 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2635 /* inname gets first entry in case we're being a translater */
2637 memcpy(inname, ain, t+1); /* include terminating null */
2640 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2641 pag = PagInCred(*acred);
2643 return EINVAL; /* Better than panicing */
2645 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2646 return EINVAL; /* Better than panicing */
2648 if (!(exporter = au->exporter)) {
2649 afs_PutUser(au, READ_LOCK);
2650 return EINVAL; /* Better than panicing */
2652 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2654 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2656 afs_PutUser(au, READ_LOCK);
2661 afs_PutUser(au, READ_LOCK);
2664 /* Not xlating, so local case */
2665 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2666 if (!setsysname) { /* user just wants the info */
2667 strcpy(outname, afs_sysname);
2668 foundname = afs_sysnamecount;
2669 } else { /* Local guy; only root can change sysname */
2670 if (!afs_osi_suser(*acred))
2673 /* clear @sys entries from the dnlc, once afs_lookup can
2674 do lookups of @sys entries and thinks it can trust them */
2675 /* privs ok, store the entry, ... */
2676 strcpy(afs_sysname, inname);
2677 if (setsysname > 1) { /* ... or list */
2679 for(count=1; count < setsysname;++count) {
2680 if (!afs_sysnamelist[count])
2681 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2683 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2687 afs_sysnamecount = setsysname;
2691 cp = aout; /* not changing so report back the count and ... */
2692 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2693 cp += sizeof(afs_int32);
2695 strcpy(cp, outname); /* ... the entry, ... */
2696 cp += strlen(outname)+1;
2697 for(count=1; count < foundname; ++count) { /* ... or list. */
2698 /* Note: we don't support @sys lists for exporters */
2699 if (!afs_sysnamelist[count])
2700 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2701 t = strlen(afs_sysnamelist[count]);
2702 if (t >= MAXSYSNAME)
2703 osi_Panic("PSetSysName: sysname entry garbled\n");
2704 strcpy(cp, afs_sysnamelist[count]);
2708 *aoutSize = cp - aout;
2713 /* sequential search through the list of touched cells is not a good
2714 * long-term solution here. For small n, though, it should be just
2715 * fine. Should consider special-casing the local cell for large n.
2716 * Likewise for PSetSPrefs.
2718 * s - number of ids in array l[] -- NOT index of last id
2719 * l - array of cell ids which have volumes that need to be sorted
2720 * vlonly - sort vl servers or file servers?
2722 static void *ReSortCells_cb(struct cell *cell, void *arg)
2724 afs_int32 *p = (afs_int32 *) arg;
2725 afs_int32 *l = p + 1;
2728 for (i=0; i<s; i++) {
2729 if (l[i] == cell->cellNum) {
2730 ObtainWriteLock(&cell->lock, 690);
2731 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2732 ReleaseWriteLock(&cell->lock);
2737 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2745 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2747 memcpy(p+1, l, s * sizeof(afs_int32));
2748 afs_TraverseCells(&ReSortCells_cb, p);
2749 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2753 ObtainReadLock(&afs_xvolume);
2754 for (i= 0; i< NVOLS; i++) {
2755 for (j=afs_volumes[i];j;j=j->next) {
2757 if (j->cell == l[k]) {
2758 ObtainWriteLock(&j->lock,233);
2759 afs_SortServers(j->serverHost, MAXHOSTS);
2760 ReleaseWriteLock(&j->lock);
2765 ReleaseReadLock(&afs_xvolume);
2769 static int debugsetsp = 0;
2770 static int afs_setsprefs(sp, num, vlonly)
2773 unsigned int vlonly;
2776 int i,j,k,matches,touchedSize;
2777 struct server *srvr = NULL;
2778 afs_int32 touched[34];
2782 for (k=0; k < num; sp++, k++) {
2784 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2787 ObtainReadLock(&afs_xserver);
2789 i = SHash(sp->host.s_addr);
2790 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2791 if (sa->sa_ip == sp->host.s_addr) {
2793 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2794 || (sa->sa_portal == AFS_FSPORT);
2795 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2802 if (sa && matches) { /* found one! */
2804 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2806 sa->sa_iprank = sp->rank + afs_randomMod15();
2807 afs_SortOneServer(sa->server);
2810 /* if we don't know yet what cell it's in, this is moot */
2811 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2812 /* is it in our list of touched cells ? */ ;
2813 if (j < 0) { /* no, it's not */
2814 touched[touchedSize++] = srvr->cell->cellNum;
2815 if (touchedSize >= 32) { /* watch for ovrflow */
2816 ReleaseReadLock(&afs_xserver);
2817 ReSortCells(touchedSize, touched, vlonly);
2819 ObtainReadLock(&afs_xserver);
2825 ReleaseReadLock(&afs_xserver);
2826 /* if we didn't find one, start to create one. */
2827 /* Note that it doesn't have a cell yet... */
2829 afs_uint32 temp = sp->host.s_addr;
2830 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2831 WRITE_LOCK, (afsUUID *)0,0);
2832 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2833 afs_PutServer(srvr, WRITE_LOCK);
2835 } /* for all cited preferences */
2837 ReSortCells(touchedSize, touched, vlonly);
2841 /* Note that this may only be performed by the local root user.
2843 DECL_PIOCTL(PSetSPrefs)
2845 struct setspref *ssp;
2846 AFS_STATCNT(PSetSPrefs);
2848 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2849 return EIO; /* Inappropriate ioctl for device */
2851 if (!afs_osi_suser(*acred))
2854 if (ainSize < sizeof(struct setspref))
2857 ssp = (struct setspref *)ain;
2858 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2861 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2862 (ssp->flags & DBservers));
2866 DECL_PIOCTL(PSetSPrefs33)
2869 AFS_STATCNT(PSetSPrefs);
2870 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2871 return EIO; /* Inappropriate ioctl for device */
2874 if (!afs_osi_suser(*acred))
2877 sp = (struct spref *)ain;
2878 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2882 /* some notes on the following code...
2883 * in the hash table of server structs, all servers with the same IP address
2884 * will be on the same overflow chain.
2885 * This could be sped slightly in some circumstances by having it cache the
2886 * immediately previous slot in the hash table and some supporting information
2887 * Only reports file servers now.
2889 DECL_PIOCTL(PGetSPrefs)
2891 struct sprefrequest *spin; /* input */
2892 struct sprefinfo *spout; /* output */
2893 struct spref *srvout; /* one output component */
2894 int i,j; /* counters for hash table traversal */
2895 struct server *srvr; /* one of CM's server structs */
2898 int vlonly; /* just return vlservers ? */
2901 AFS_STATCNT(PGetSPrefs);
2902 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2903 return EIO; /* Inappropriate ioctl for device */
2906 if (ainSize < sizeof (struct sprefrequest_33)) {
2910 spin = ((struct sprefrequest *) ain);
2913 if (ainSize > sizeof (struct sprefrequest_33)) {
2914 vlonly = (spin->flags & DBservers);
2918 /* struct sprefinfo includes 1 server struct... that size gets added
2919 * in during the loop that follows.
2921 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2922 spout = (struct sprefinfo *) aout;
2923 spout->next_offset = spin->offset;
2924 spout->num_servers = 0;
2925 srvout = spout->servers;
2927 ObtainReadLock(&afs_xserver);
2928 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2929 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2930 if (spin->offset > (unsigned short)i) {
2931 continue; /* catch up to where we left off */
2933 spout->next_offset++;
2936 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2937 || (sa->sa_portal == AFS_FSPORT);
2939 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2940 /* only report ranks for vl servers */
2944 srvout->host.s_addr = sa->sa_ip;
2945 srvout->rank = sa->sa_iprank;
2946 *aoutSize += sizeof(struct spref);
2947 spout->num_servers++;
2950 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2951 ReleaseReadLock(&afs_xserver); /* no more room! */
2956 ReleaseReadLock(&afs_xserver);
2958 spout->next_offset = 0; /* start over from the beginning next time */
2962 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2963 int afs_NFSRootOnly = 1;
2964 DECL_PIOCTL(PExportAfs)
2966 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2967 register struct afs_exporter *exporter;
2969 AFS_STATCNT(PExportAfs);
2970 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2971 type = handleValue >> 24;
2976 exporter = exporter_find(type);
2978 export = handleValue & 3;
2979 changestate = handleValue & 0xff;
2980 smounts = (handleValue >> 2) & 3;
2981 pwsync = (handleValue >> 4) & 3;
2982 convmode = (handleValue >> 6) & 3;
2984 changestate = (handleValue >> 16) & 0x1;
2985 convmode = (handleValue >> 16) & 0x2;
2986 pwsync = (handleValue >> 16) & 0x4;
2987 smounts = (handleValue >> 16) & 0x8;
2988 export = handleValue & 0xff;
2991 /* Failed finding desired exporter; */
2995 handleValue = exporter->exp_states;
2996 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2997 *aoutSize = sizeof(afs_int32);
2999 if (!afs_osi_suser(*acred))
3000 return EACCES; /* Only superuser can do this */
3004 exporter->exp_states |= EXP_EXPORTED;
3006 exporter->exp_states &= ~EXP_EXPORTED;
3010 exporter->exp_states |= EXP_UNIXMODE;
3012 exporter->exp_states &= ~EXP_UNIXMODE;
3016 exporter->exp_states |= EXP_PWSYNC;
3018 exporter->exp_states &= ~EXP_PWSYNC;
3022 afs_NFSRootOnly = 0;
3023 exporter->exp_states |= EXP_SUBMOUNTS;
3025 afs_NFSRootOnly = 1;
3026 exporter->exp_states &= ~EXP_SUBMOUNTS;
3029 handleValue = exporter->exp_states;
3030 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3031 *aoutSize = sizeof(afs_int32);
3034 exporter->exp_states |= EXP_EXPORTED;
3036 exporter->exp_states &= ~EXP_EXPORTED;
3038 exporter->exp_states |= EXP_UNIXMODE;
3040 exporter->exp_states &= ~EXP_UNIXMODE;
3042 exporter->exp_states |= EXP_PWSYNC;
3044 exporter->exp_states &= ~EXP_PWSYNC;
3046 afs_NFSRootOnly = 0;
3047 exporter->exp_states |= EXP_SUBMOUNTS;
3049 afs_NFSRootOnly = 1;
3050 exporter->exp_states &= ~EXP_SUBMOUNTS;
3060 struct gaginfo *gagflags;
3062 if (!afs_osi_suser(*acred))
3065 gagflags = (struct gaginfo *) ain;
3066 afs_showflags = gagflags->showflags;
3072 DECL_PIOCTL(PTwiddleRx)
3074 struct rxparams *rxp;
3076 if (!afs_osi_suser(*acred))
3079 rxp = (struct rxparams *) ain;
3081 if (rxp->rx_initReceiveWindow)
3082 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3083 if (rxp->rx_maxReceiveWindow)
3084 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3085 if (rxp->rx_initSendWindow)
3086 rx_initSendWindow = rxp->rx_initSendWindow;
3087 if (rxp->rx_maxSendWindow)
3088 rx_maxSendWindow = rxp->rx_maxSendWindow;
3089 if (rxp->rxi_nSendFrags)
3090 rxi_nSendFrags = rxp->rxi_nSendFrags;
3091 if (rxp->rxi_nRecvFrags)
3092 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3093 if (rxp->rxi_OrphanFragSize)
3094 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3095 if (rxp->rx_maxReceiveSize)
3097 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3098 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3100 if (rxp->rx_MyMaxSendSize)
3101 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3106 DECL_PIOCTL(PGetInitParams)
3108 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3111 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3112 *aoutSize = sizeof(struct cm_initparams);
3116 #ifdef AFS_SGI65_ENV
3117 /* They took crget() from us, so fake it. */
3118 static cred_t *crget(void)
3121 cr = crdup(get_current_cred());
3122 memset((char*)cr, 0, sizeof(cred_t));
3123 #if CELL || CELL_PREPARE
3130 DECL_PIOCTL(PGetRxkcrypt)
3132 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3133 *aoutSize=sizeof(afs_int32);
3137 DECL_PIOCTL(PSetRxkcrypt)
3141 if (!afs_osi_suser(*acred))
3143 if (ainSize != sizeof(afs_int32) || ain == NULL)
3145 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3146 /* if new mappings added later this will need to be changed */
3147 if (tmpval != 0 && tmpval != 1)
3154 * Create new credentials to correspond to a remote user with given
3155 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3156 * provide pioctl (and other) services to foreign clients (i.e. nfs
3157 * clients) by using this call to `become' the client.
3160 #define PIOCTL_HEADER 6
3161 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3163 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3164 return EINVAL; /* NFS trans not supported for Ultrix */
3167 afs_uint32 hostaddr;
3168 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3169 struct afs_exporter *exporter, *outexporter;
3170 struct AFS_UCRED *newcred;
3171 struct unixuser *au;
3173 #if defined(AFS_SGIMP_ENV)
3174 osi_Assert(ISAFS_GLOCK());
3176 AFS_STATCNT(HandleClientContext);
3177 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3178 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3179 return EINVAL; /* Too small to be good */
3181 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3182 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3184 osi_FreeLargeSpace(inData);
3188 /* Extract information for remote user */
3189 hostaddr = *((afs_uint32 *)ain);
3190 ain += sizeof(hostaddr);
3191 uid = *((afs_uint32 *)ain);
3193 g0 = *((afs_uint32 *)ain);
3195 g1 = *((afs_uint32 *)ain);
3197 *com = *((afs_uint32 *)ain);
3198 ain += sizeof(afs_int32);
3199 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3202 * Of course, one must be root for most of these functions, but
3203 * we'll allow (for knfs) you to set things if the pag is 0 and
3204 * you're setting tokens or unlogging.
3207 if (!afs_osi_suser(credp)) {
3209 #ifndef AFS_SGI64_ENV
3210 /* Since SGI's suser() returns explicit failure after the call.. */
3214 /* check for acceptable opcodes for normal folks, which are, so far,
3215 * set tokens and unlog.
3217 if (i != 9 && i != 3 && i != 38 && i != 8) {
3218 osi_FreeLargeSpace(inData);
3223 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3224 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3225 osi_FreeLargeSpace(inData);
3228 * We map uid 0 to nobody to match the mapping that the nfs
3229 * server does and to ensure that the suser() calls in the afs
3230 * code fails for remote client roots.
3232 uid = afs_nobody; /* NFS_NOBODY == -2 */
3235 #ifdef AFS_AIX41_ENV
3238 newcred->cr_gid = RMTUSER_REQ;
3239 #ifdef AFS_AIX51_ENV
3240 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3241 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3243 newcred->cr_groups[0] = g0;
3244 newcred->cr_groups[1] = g1;
3247 newcred->cr_ngrps = 2;
3249 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3250 newcred->cr_ngroups = 2;
3252 for (i=2; i<NGROUPS; i++)
3253 newcred->cr_groups[i] = NOGROUP;
3256 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3257 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3259 if (!(exporter = exporter_find(exporter_type))) {
3260 /* Exporter wasn't initialized or an invalid exporter type */
3264 if (exporter->exp_states & EXP_PWSYNC) {
3265 if (uid != credp->cr_uid) {
3267 return ENOEXEC; /* XXX Find a better errno XXX */
3270 newcred->cr_uid = uid; /* Only temporary */
3271 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3272 /* The client's pag is the only unique identifier for it */
3273 newcred->cr_uid = pag;
3275 if (!code && *com == PSETPAG) {
3276 /* Special case for 'setpag' */
3277 afs_uint32 pagvalue = genpag();
3279 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3281 * Note that we leave the 'outexporter' struct held so it won't
3284 au->exporter = outexporter;
3285 if (ablob->out_size >= 4) {
3286 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3288 afs_PutUser(au, WRITE_LOCK);
3289 if (code) return code;
3290 return PSETPAG; /* Special return for setpag */
3292 EXP_RELE(outexporter);
3295 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3298 /* get all interface addresses of this client */
3300 DECL_PIOCTL(PGetCPrefs)
3302 struct sprefrequest *spin; /* input */
3303 struct sprefinfo *spout; /* output */
3304 struct spref *srvout; /* one output component */
3308 AFS_STATCNT(PGetCPrefs);
3309 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3310 return EIO; /* Inappropriate ioctl for device */
3312 if ( ainSize < sizeof (struct sprefrequest ))
3315 spin = (struct sprefrequest *) ain;
3316 spout = (struct sprefinfo *) aout;
3318 maxNumber = spin->num_servers; /* max addrs this time */
3319 srvout = spout->servers;
3321 ObtainReadLock(&afs_xinterface);
3323 /* copy out the client interface information from the
3324 ** kernel data structure "interface" to the output buffer
3326 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3327 && ( j< maxNumber) ; i++, j++, srvout++)
3328 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3330 spout->num_servers = j;
3331 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3333 if ( i >= afs_cb_interface.numberOfInterfaces )
3334 spout->next_offset = 0; /* start from beginning again */
3336 spout->next_offset = spin->offset + j;
3338 ReleaseReadLock(&afs_xinterface);
3342 DECL_PIOCTL(PSetCPrefs)
3344 struct setspref *sin;
3347 AFS_STATCNT(PSetCPrefs);
3348 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3349 return EIO; /* Inappropriate ioctl for device */
3351 sin = (struct setspref *)ain;
3353 if ( ainSize < sizeof(struct setspref) )
3355 #if 0 /* num_servers is unsigned */
3356 if ( sin->num_servers < 0 )
3359 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3362 ObtainWriteLock(&afs_xinterface, 412);
3363 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3364 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3365 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3367 ReleaseWriteLock(&afs_xinterface);
3371 DECL_PIOCTL(PFlushMount)
3373 register afs_int32 code;
3374 register struct vcache *tvc;
3375 register struct dcache *tdc;
3376 struct VenusFid tfid;
3378 struct sysname_info sysState;
3379 afs_size_t offset, len;
3381 AFS_STATCNT(PFlushMount);
3382 if (!avc) return EINVAL;
3383 code = afs_VerifyVCache(avc, areq);
3384 if (code) return code;
3385 if (vType(avc) != VDIR) {
3388 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3389 if (!tdc) return ENOENT;
3390 Check_AtSys(avc, ain, &sysState, areq);
3391 ObtainReadLock(&tdc->lock);
3393 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3394 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3395 ReleaseReadLock(&tdc->lock);
3396 afs_PutDCache(tdc); /* we're done with the data */
3397 bufp = sysState.name;
3401 tfid.Cell = avc->fid.Cell;
3402 tfid.Fid.Volume = avc->fid.Fid.Volume;
3403 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3404 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3406 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3412 if (tvc->mvstat != 1) {
3417 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3418 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3420 ObtainWriteLock(&tvc->lock,649);
3421 ObtainWriteLock(&afs_xcbhash, 650);
3422 afs_DequeueCallback(tvc);
3423 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3424 ReleaseWriteLock(&afs_xcbhash);
3425 /* now find the disk cache entries */
3426 afs_TryToSmush(tvc, *acred, 1);
3427 osi_dnlc_purgedp(tvc);
3428 afs_symhint_inval(tvc);
3429 if (tvc->linkData && !(tvc->states & CCore)) {
3430 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3431 tvc->linkData = NULL;
3433 ReleaseWriteLock(&tvc->lock);
3434 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3435 afs_BozonUnlock(&tvc->pvnLock, tvc);
3439 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3443 DECL_PIOCTL(PRxStatProc)
3448 if (!afs_osi_suser(*acred)) {
3452 if (ainSize != sizeof(afs_int32)) {
3456 memcpy((char *)&flags, ain, sizeof(afs_int32));
3457 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3461 if (flags & AFSCALL_RXSTATS_ENABLE) {
3462 rx_enableProcessRPCStats();
3464 if (flags & AFSCALL_RXSTATS_DISABLE) {
3465 rx_disableProcessRPCStats();
3467 if (flags & AFSCALL_RXSTATS_CLEAR) {
3468 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3476 DECL_PIOCTL(PRxStatPeer)
3481 if (!afs_osi_suser(*acred)) {
3485 if (ainSize != sizeof(afs_int32)) {
3489 memcpy((char *)&flags, ain, sizeof(afs_int32));
3490 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3494 if (flags & AFSCALL_RXSTATS_ENABLE) {
3495 rx_enablePeerRPCStats();
3497 if (flags & AFSCALL_RXSTATS_DISABLE) {
3498 rx_disablePeerRPCStats();
3500 if (flags & AFSCALL_RXSTATS_CLEAR) {
3501 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3508 DECL_PIOCTL(PPrefetchFromTape)
3510 register afs_int32 code, code1;
3513 struct rx_call *tcall;
3514 struct AFSVolSync tsync;
3515 struct AFSFetchStatus OutStatus;
3516 struct AFSCallBack CallBack;
3517 struct VenusFid tfid;
3522 AFS_STATCNT(PSetAcl);
3526 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3527 Fid = (struct AFSFid *) ain;
3529 Fid = &avc->fid.Fid;
3530 tfid.Cell = avc->fid.Cell;
3531 tfid.Fid.Volume = Fid->Volume;
3532 tfid.Fid.Vnode = Fid->Vnode;
3533 tfid.Fid.Unique = Fid->Unique;
3535 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3537 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3538 ICL_TYPE_POINTER, tvc,
3539 ICL_TYPE_FID, &tfid,
3540 ICL_TYPE_FID, &avc->fid);
3543 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3544 ICL_TYPE_POINTER, tvc,
3545 ICL_TYPE_FID, &tfid,
3546 ICL_TYPE_FID, &tvc->fid);
3549 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3553 tcall = rx_NewCall(tc->id);
3554 code = StartRXAFS_FetchData(tcall,
3555 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3557 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3558 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3560 code1 = rx_EndCall(tcall, code);
3565 (afs_Analyze(tc, code, &tvc->fid, areq,
3566 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3568 /* This call is done only to have the callback things handled correctly */
3569 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3573 *aoutSize = sizeof(afs_int32);
3578 DECL_PIOCTL(PResidencyCmd)
3580 register afs_int32 code;
3583 struct ResidencyCmdInputs *Inputs;
3584 struct ResidencyCmdOutputs *Outputs;
3585 struct VenusFid tfid;
3588 Inputs = (struct ResidencyCmdInputs *) ain;
3589 Outputs = (struct ResidencyCmdOutputs *) aout;
3590 if (!avc) return EINVAL;
3591 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3595 Fid = &avc->fid.Fid;
3597 tfid.Cell = avc->fid.Cell;
3598 tfid.Fid.Volume = Fid->Volume;
3599 tfid.Fid.Vnode = Fid->Vnode;
3600 tfid.Fid.Unique = Fid->Unique;
3602 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3603 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3604 ICL_TYPE_POINTER, tvc,
3605 ICL_TYPE_INT32, Inputs->command,
3606 ICL_TYPE_FID, &tfid);
3610 if (Inputs->command) {
3612 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3615 code = RXAFS_ResidencyCmd(tc->id, Fid,
3617 (struct ResidencyCmdOutputs *) aout);
3622 (afs_Analyze(tc, code, &tvc->fid, areq,
3623 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3625 /* This call is done to have the callback things handled correctly */
3626 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3627 } else { /* just a status request, return also link data */
3629 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3630 Outputs->chars[0] = 0;
3631 if (vType(tvc) == VLNK) {
3632 ObtainWriteLock(&tvc->lock,555);
3633 if (afs_HandleLink(tvc, areq) == 0)
3634 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3635 ReleaseWriteLock(&tvc->lock);
3642 *aoutSize = sizeof(struct ResidencyCmdOutputs);