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());
819 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
820 #endif /* AFS_SGI_ENV */
826 crfree(foreigncreds);
829 #if defined(KERNEL_HAVE_SETUERROR)
830 return (setuerror(code), code);
836 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
839 * We could have done without temporary setting the u.u_cred below
840 * (foreigncreds could be passed as param the pioctl modules)
841 * but calls such as afs_osi_suser() doesn't allow that since it
842 * references u.u_cred directly. We could, of course, do something
843 * like afs_osi_suser(cred) which, I think, is better since it
844 * generalizes and supports multi cred environments...
848 credp = foreigncreds;
851 tmpcred = crref(); /* XXX */
854 #if defined(AFS_HPUX101_ENV)
855 tmpcred = p_cred(u.u_procp);
856 set_p_cred(u.u_procp, foreigncreds);
859 tmpcred = OSI_GET_CURRENT_CRED();
860 OSI_SET_CURRENT_CRED(foreigncreds);
863 u.u_cred = foreigncreds;
864 #endif /* AFS_SGI64_ENV */
865 #endif /* AFS_HPUX101_ENV */
870 if ((com & 0xff) == 15) {
871 /* special case prefetch so entire pathname eval occurs in helper process.
872 otherwise, the pioctl call is essentially useless */
873 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
874 code = Prefetch(path, &data, follow,
875 foreigncreds ? foreigncreds : credp);
877 #if defined(AFS_HPUX101_ENV)
878 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
881 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
883 code = Prefetch(path, &data, follow, u.u_cred);
884 #endif /* AFS_SGI64_ENV */
885 #endif /* AFS_HPUX101_ENV */
887 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
890 crset(tmpcred); /* restore original credentials */
892 #if defined(AFS_HPUX101_ENV)
893 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
897 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
899 u.u_cred = tmpcred; /* restore original credentials */
902 #endif /* AFS_HPUX101_ENV */
903 crfree(foreigncreds);
906 #endif /* AFS_LINUX22_ENV */
908 #if defined(KERNEL_HAVE_SETUERROR)
909 return (setuerror(code), code);
917 code = lookupname(path, USR, follow, NULL, &vp,
918 foreigncreds ? foreigncreds : credp);
920 #ifdef AFS_LINUX22_ENV
921 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
923 vp = (struct vnode *)dp->d_inode;
925 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
926 #endif /* AFS_LINUX22_ENV */
927 #endif /* AFS_AIX41_ENV */
930 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
933 crset(tmpcred); /* restore original credentials */
935 #if defined(AFS_HPUX101_ENV)
936 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
938 #if !defined(AFS_SUN5_ENV)
940 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
942 u.u_cred = tmpcred; /* restore original credentials */
943 #endif /* AFS_SGI64_ENV */
945 #endif /* AFS_HPUX101_ENV */
946 crfree(foreigncreds);
949 #endif /* AFS_LINUX22_ENV */
951 #if defined(KERNEL_HAVE_SETUERROR)
952 return(setuerror(code), code);
960 /* now make the call if we were passed no file, or were passed an AFS file */
961 if (!vp || IsAfsVnode(vp)) {
963 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
964 * So, we must test in this part of the code. Also, must arrange to
965 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
966 * we hold gnodes, whose references hold our vcache entries.
969 gp = vp; /* remember for "put" */
970 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
975 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
979 struct ucred *cred1, *cred2;
982 cred1 = cred2 = foreigncreds;
984 cred1 = cred2 = credp;
986 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
987 if (cred1 != cred2) {
988 /* something changed the creds */
993 #if defined(AFS_HPUX101_ENV)
995 struct ucred *cred = p_cred(u.u_procp);
996 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
1002 credp = OSI_GET_CURRENT_CRED();
1003 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
1006 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1007 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
1009 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
1011 #endif /* AFS_SGI_ENV */
1012 #endif /* AFS_HPUX101_ENV */
1013 #endif /* AFS_AIX41_ENV */
1014 #endif /* AFS_SUN5_ENV */
1016 #if defined(KERNEL_HAVE_SETUERROR)
1019 code = EINVAL; /* not in /afs */
1029 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
1031 #ifdef AFS_AIX41_ENV
1034 #if defined(AFS_HPUX101_ENV)
1035 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1037 #ifndef AFS_SUN5_ENV
1039 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1041 u.u_cred = tmpcred; /* restore original credentials */
1042 #endif /* ASF_SGI64_ENV */
1044 #endif /* AFS_HPUX101_ENV */
1045 crfree(foreigncreds);
1048 #endif /* AFS_LINUX22_ENV */
1050 #ifdef AFS_LINUX22_ENV
1053 AFS_RELE(vp); /* put vnode back */
1057 #if defined(KERNEL_HAVE_SETUERROR)
1060 return (getuerror());
1067 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1068 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1070 struct vrequest treq;
1071 register afs_int32 code;
1072 register afs_int32 function, device;
1073 afs_int32 inSize, outSize;
1074 char *inData, *outData;
1075 int (*(*pioctlSw))();
1077 struct afs_fakestat_state fakestate;
1079 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1080 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1081 AFS_STATCNT(HandlePioctl);
1082 if ((code = afs_InitReq(&treq, *acred))) return code;
1083 afs_InitFakeStat(&fakestate);
1085 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1087 afs_PutFakeStat(&fakestate);
1091 device = (acom & 0xff00) >> 8;
1093 case 'V': /* Original pioctl's */
1094 pioctlSw = VpioctlSw;
1095 pioctlSwSize = sizeof(VpioctlSw);
1097 case 'C': /* Coordinated/common pioctl's */
1098 pioctlSw = CpioctlSw;
1099 pioctlSwSize = sizeof(CpioctlSw);
1102 afs_PutFakeStat(&fakestate);
1105 function = acom & 0xff;
1106 if (function >= (pioctlSwSize / sizeof(char *))) {
1107 afs_PutFakeStat(&fakestate);
1108 return EINVAL; /* out of range */
1110 inSize = ablob->in_size;
1111 if (inSize >= PIGGYSIZE) return E2BIG;
1112 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1114 AFS_COPYIN(ablob->in, inData, inSize, code);
1115 inData[inSize]='\0';
1119 osi_FreeLargeSpace(inData);
1120 afs_PutFakeStat(&fakestate);
1123 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1125 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1126 osi_FreeLargeSpace(inData);
1127 if (code == 0 && ablob->out_size > 0) {
1128 if (outSize > ablob->out_size) outSize = ablob->out_size;
1129 if (outSize >= PIGGYSIZE) code = E2BIG;
1131 outData[outSize]='\0';
1132 AFS_COPYOUT(outData, ablob->out, outSize, code);
1135 osi_FreeLargeSpace(outData);
1136 afs_PutFakeStat(&fakestate);
1137 return afs_CheckCode(code, &treq, 41);
1140 DECL_PIOCTL(PGetFID)
1142 register afs_int32 code;
1144 AFS_STATCNT(PGetFID);
1145 if (!avc) return EINVAL;
1146 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1147 *aoutSize = sizeof(struct VenusFid);
1151 DECL_PIOCTL(PSetAcl)
1153 register afs_int32 code;
1155 struct AFSOpaque acl;
1156 struct AFSVolSync tsync;
1157 struct AFSFetchStatus OutStatus;
1160 AFS_STATCNT(PSetAcl);
1163 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1166 acl.AFSOpaque_val = ain;
1168 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1170 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1172 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1173 &acl, &OutStatus, &tsync);
1179 (afs_Analyze(tconn, code, &avc->fid, areq,
1180 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1182 /* now we've forgotten all of the access info */
1183 ObtainWriteLock(&afs_xcbhash, 455);
1185 afs_DequeueCallback(avc);
1186 avc->states &= ~(CStatd | CUnique);
1187 ReleaseWriteLock(&afs_xcbhash);
1188 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1189 osi_dnlc_purgedp(avc);
1193 int afs_defaultAsynchrony = 0;
1195 DECL_PIOCTL(PStoreBehind)
1198 struct sbstruct *sbr;
1200 sbr = (struct sbstruct *)ain;
1201 if (sbr->sb_default != -1) {
1202 if (afs_osi_suser(*acred))
1203 afs_defaultAsynchrony = sbr->sb_default;
1207 if (avc && (sbr->sb_thisfile != -1)) {
1208 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1209 areq, DONT_CHECK_MODE_BITS))
1210 avc->asynchrony = sbr->sb_thisfile;
1214 *aoutSize = sizeof(struct sbstruct);
1215 sbr = (struct sbstruct *)aout;
1216 sbr->sb_default = afs_defaultAsynchrony;
1218 sbr->sb_thisfile = avc->asynchrony;
1224 DECL_PIOCTL(PGCPAGs)
1226 if (!afs_osi_suser(*acred)) {
1229 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1233 DECL_PIOCTL(PGetAcl)
1235 struct AFSOpaque acl;
1236 struct AFSVolSync tsync;
1237 struct AFSFetchStatus OutStatus;
1243 AFS_STATCNT(PGetAcl);
1244 if (!avc) return EINVAL;
1245 Fid.Volume = avc->fid.Fid.Volume;
1246 Fid.Vnode = avc->fid.Fid.Vnode;
1247 Fid.Unique = avc->fid.Fid.Unique;
1248 if (avc->states & CForeign) {
1250 * For a dfs xlator acl we have a special hack so that the
1251 * xlator will distinguish which type of acl will return. So
1252 * we currently use the top 2-bytes (vals 0-4) to tell which
1253 * type of acl to bring back. Horrible hack but this will
1254 * cause the least number of changes to code size and interfaces.
1256 if (Fid.Vnode & 0xc0000000)
1258 Fid.Vnode |= (ainSize << 30);
1260 acl.AFSOpaque_val = aout;
1262 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1265 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1267 code = RXAFS_FetchACL(tconn->id, &Fid,
1268 &acl, &OutStatus, &tsync);
1274 (afs_Analyze(tconn, code, &avc->fid, areq,
1275 AFS_STATS_FS_RPCIDX_FETCHACL,
1276 SHARED_LOCK, NULL));
1279 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1292 AFS_STATCNT(PBogus);
1296 DECL_PIOCTL(PGetFileCell)
1298 register struct cell *tcell;
1300 AFS_STATCNT(PGetFileCell);
1301 if (!avc) return EINVAL;
1302 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1303 if (!tcell) return ESRCH;
1304 strcpy(aout, tcell->cellName);
1305 afs_PutCell(tcell, READ_LOCK);
1306 *aoutSize = strlen(aout) + 1;
1310 DECL_PIOCTL(PGetWSCell)
1312 struct cell *tcell = NULL;
1314 AFS_STATCNT(PGetWSCell);
1315 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1316 return EIO; /* Inappropriate ioctl for device */
1318 tcell = afs_GetPrimaryCell(READ_LOCK);
1319 if (!tcell) /* no primary cell? */
1321 strcpy(aout, tcell->cellName);
1322 *aoutSize = strlen(aout) + 1;
1323 afs_PutCell(tcell, READ_LOCK);
1327 DECL_PIOCTL(PGetUserCell)
1329 register afs_int32 i;
1330 register struct unixuser *tu;
1331 register struct cell *tcell;
1333 AFS_STATCNT(PGetUserCell);
1334 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1335 return EIO; /* Inappropriate ioctl for device */
1337 /* return the cell name of the primary cell for this user */
1338 i = UHash(areq->uid);
1339 ObtainWriteLock(&afs_xuser,224);
1340 for(tu = afs_users[i]; tu; tu = tu->next) {
1341 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1343 ReleaseWriteLock(&afs_xuser);
1348 tcell = afs_GetCell(tu->cell, READ_LOCK);
1349 afs_PutUser(tu, WRITE_LOCK);
1350 if (!tcell) return ESRCH;
1352 strcpy(aout, tcell->cellName);
1353 afs_PutCell(tcell, READ_LOCK);
1354 *aoutSize = strlen(aout)+1; /* 1 for the null */
1358 ReleaseWriteLock(&afs_xuser);
1365 DECL_PIOCTL(PSetTokens)
1368 register struct unixuser *tu;
1369 struct ClearToken clear;
1370 register struct cell *tcell;
1373 struct vrequest treq;
1374 afs_int32 flag, set_parent_pag = 0;
1376 AFS_STATCNT(PSetTokens);
1377 if (!afs_resourceinit_flag) {
1380 memcpy((char *)&i, ain, sizeof(afs_int32));
1381 ain += sizeof(afs_int32);
1382 stp = ain; /* remember where the ticket is */
1383 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1384 if (i > MAXKTCTICKETLEN) return EINVAL;
1386 ain += i; /* skip over ticket */
1387 memcpy((char *)&i, ain, sizeof(afs_int32));
1388 ain += sizeof(afs_int32);
1389 if (i != sizeof(struct ClearToken)) {
1392 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1393 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1394 ain += sizeof(struct ClearToken);
1395 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1396 /* still stuff left? we've got primary flag and cell name. Set these */
1397 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1398 ain += sizeof(afs_int32); /* skip id field */
1399 /* rest is cell name, look it up */
1400 /* some versions of gcc appear to need != 0 in order to get this right */
1401 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1405 tcell = afs_GetCellByName(ain, READ_LOCK);
1406 if (!tcell) goto nocell;
1409 /* default to primary cell, primary id */
1410 flag = 1; /* primary id */
1411 tcell = afs_GetPrimaryCell(READ_LOCK);
1412 if (!tcell) goto nocell;
1415 afs_PutCell(tcell, READ_LOCK);
1416 if (set_parent_pag) {
1418 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1419 #if defined(AFS_DARWIN_ENV)
1420 struct proc *p=current_proc(); /* XXX */
1422 struct proc *p=curproc; /* XXX */
1424 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1425 p->p_pid, p->p_comm);
1426 if (!setpag(p, acred, -1, &pag, 1)) {
1429 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1431 if (!setpag(acred, -1, &pag, 1)) {
1434 afs_InitReq(&treq, *acred);
1438 /* now we just set the tokens */
1439 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1440 tu->vid = clear.ViceId;
1441 if (tu->stp != NULL) {
1442 afs_osi_Free(tu->stp, tu->stLen);
1444 tu->stp = (char *) afs_osi_Alloc(stLen);
1446 memcpy(tu->stp, stp, stLen);
1449 afs_stats_cmfullperf.authent.TicketUpdates++;
1450 afs_ComputePAGStats();
1451 #endif /* AFS_NOSTATS */
1452 tu->states |= UHasTokens;
1453 tu->states &= ~UTokensBad;
1454 afs_SetPrimary(tu, flag);
1455 tu->tokenTime =osi_Time();
1456 afs_ResetUserConns(tu);
1457 afs_PutUser(tu, WRITE_LOCK);
1472 DECL_PIOCTL(PGetVolumeStatus)
1475 char offLineMsg[256];
1477 register struct conn *tc;
1478 register afs_int32 code;
1479 struct VolumeStatus volstat;
1481 char *Name, *OfflineMsg, *MOTD;
1484 AFS_STATCNT(PGetVolumeStatus);
1485 if (!avc) return EINVAL;
1487 OfflineMsg = offLineMsg;
1490 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1492 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1494 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1495 &Name, &OfflineMsg, &MOTD);
1501 (afs_Analyze(tc, code, &avc->fid, areq,
1502 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1503 SHARED_LOCK, NULL));
1505 if (code) return code;
1506 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1508 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1509 cp += sizeof(VolumeStatus);
1510 strcpy(cp, volName);
1511 cp += strlen(volName)+1;
1512 strcpy(cp, offLineMsg);
1513 cp += strlen(offLineMsg)+1;
1515 cp += strlen(motd)+1;
1516 *aoutSize = (cp - aout);
1520 DECL_PIOCTL(PSetVolumeStatus)
1523 char offLineMsg[256];
1525 register struct conn *tc;
1526 register afs_int32 code;
1527 struct AFSFetchVolumeStatus volstat;
1528 struct AFSStoreVolumeStatus storeStat;
1529 register struct volume *tvp;
1533 AFS_STATCNT(PSetVolumeStatus);
1534 if (!avc) return EINVAL;
1536 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1538 if (tvp->states & (VRO | VBackup)) {
1539 afs_PutVolume(tvp, READ_LOCK);
1542 afs_PutVolume(tvp, READ_LOCK);
1545 /* Copy the junk out, using cp as a roving pointer. */
1547 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1548 cp += sizeof(AFSFetchVolumeStatus);
1549 if (strlen(cp) >= sizeof(volName))
1551 strcpy(volName, cp);
1552 cp += strlen(volName)+1;
1553 if (strlen(cp) >= sizeof(offLineMsg))
1555 strcpy(offLineMsg, cp);
1556 cp += strlen(offLineMsg)+1;
1557 if (strlen(cp) >= sizeof(motd))
1561 if (volstat.MinQuota != -1) {
1562 storeStat.MinQuota = volstat.MinQuota;
1563 storeStat.Mask |= AFS_SETMINQUOTA;
1565 if (volstat.MaxQuota != -1) {
1566 storeStat.MaxQuota = volstat.MaxQuota;
1567 storeStat.Mask |= AFS_SETMAXQUOTA;
1570 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1572 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1574 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1575 &storeStat, volName, offLineMsg, motd);
1581 (afs_Analyze(tc, code, &avc->fid, areq,
1582 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1583 SHARED_LOCK, NULL));
1585 if (code) return code;
1586 /* we are sending parms back to make compat. with prev system. should
1587 change interface later to not ask for current status, just set new status */
1589 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1590 cp += sizeof(VolumeStatus);
1591 strcpy(cp, volName);
1592 cp += strlen(volName)+1;
1593 strcpy(cp, offLineMsg);
1594 cp += strlen(offLineMsg)+1;
1596 cp += strlen(motd)+1;
1597 *aoutSize = cp - aout;
1603 AFS_STATCNT(PFlush);
1604 if (!avc) return EINVAL;
1605 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1606 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1608 ObtainWriteLock(&avc->lock,225);
1609 ObtainWriteLock(&afs_xcbhash, 456);
1610 afs_DequeueCallback(avc);
1611 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1612 ReleaseWriteLock(&afs_xcbhash);
1613 /* now find the disk cache entries */
1614 afs_TryToSmush(avc, *acred, 1);
1615 osi_dnlc_purgedp(avc);
1616 afs_symhint_inval(avc);
1617 if (avc->linkData && !(avc->states & CCore)) {
1618 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1619 avc->linkData = NULL;
1621 ReleaseWriteLock(&avc->lock);
1622 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1623 afs_BozonUnlock(&avc->pvnLock, avc);
1628 DECL_PIOCTL(PNewStatMount)
1630 register afs_int32 code;
1631 register struct vcache *tvc;
1632 register struct dcache *tdc;
1633 struct VenusFid tfid;
1635 struct sysname_info sysState;
1636 afs_size_t offset, len;
1638 AFS_STATCNT(PNewStatMount);
1639 if (!avc) return EINVAL;
1640 code = afs_VerifyVCache(avc, areq);
1641 if (code) return code;
1642 if (vType(avc) != VDIR) {
1645 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1646 if (!tdc) return ENOENT;
1647 Check_AtSys(avc, ain, &sysState, areq);
1648 ObtainReadLock(&tdc->lock);
1650 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1651 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1652 ReleaseReadLock(&tdc->lock);
1653 afs_PutDCache(tdc); /* we're done with the data */
1654 bufp = sysState.name;
1658 tfid.Cell = avc->fid.Cell;
1659 tfid.Fid.Volume = avc->fid.Fid.Volume;
1660 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1661 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1663 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1669 if (tvc->mvstat != 1) {
1674 ObtainWriteLock(&tvc->lock,226);
1675 code = afs_HandleLink(tvc, areq);
1677 if (tvc->linkData) {
1678 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1681 /* we have the data */
1682 strcpy(aout, tvc->linkData);
1683 *aoutSize = strlen(tvc->linkData)+1;
1688 ReleaseWriteLock(&tvc->lock);
1691 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1695 DECL_PIOCTL(PGetTokens)
1697 register struct cell *tcell;
1698 register afs_int32 i;
1699 register struct unixuser *tu;
1704 AFS_STATCNT(PGetTokens);
1705 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1706 return EIO; /* Inappropriate ioctl for device */
1708 /* weird interface. If input parameter is present, it is an integer and
1709 we're supposed to return the parm'th tokens for this unix uid.
1710 If not present, we just return tokens for cell 1.
1711 If counter out of bounds, return EDOM.
1712 If no tokens for the particular cell, return ENOTCONN.
1713 Also, if this mysterious parm is present, we return, along with the
1714 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1715 at the end, in that order.
1717 if ((newStyle = (ainSize > 0))) {
1718 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1720 i = UHash(areq->uid);
1721 ObtainReadLock(&afs_xuser);
1722 for(tu = afs_users[i]; tu; tu=tu->next) {
1724 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1725 if (iterator-- == 0) break; /* are we done yet? */
1729 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1734 * No need to hold a read lock on each user entry
1738 ReleaseReadLock(&afs_xuser);
1743 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1744 tu->states |= (UTokensBad | UNeedsReset);
1745 afs_PutUser(tu, READ_LOCK);
1748 /* use iterator for temp */
1750 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1751 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1752 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1753 cp += sizeof(afs_int32);
1754 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1756 iterator = sizeof(struct ClearToken);
1757 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1758 cp += sizeof(afs_int32);
1759 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1760 cp += sizeof(struct ClearToken);
1762 /* put out primary id and cell name, too */
1763 iterator = (tu->states & UPrimary ? 1 : 0);
1764 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1765 cp += sizeof(afs_int32);
1766 tcell = afs_GetCell(tu->cell, READ_LOCK);
1768 strcpy(cp, tcell->cellName);
1769 cp += strlen(tcell->cellName)+1;
1770 afs_PutCell(tcell, READ_LOCK);
1774 *aoutSize = cp - aout;
1775 afs_PutUser(tu, READ_LOCK);
1781 register afs_int32 i;
1782 register struct unixuser *tu;
1784 AFS_STATCNT(PUnlog);
1785 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1786 return EIO; /* Inappropriate ioctl for device */
1788 i = UHash(areq->uid);
1789 ObtainWriteLock(&afs_xuser,227);
1790 for(tu=afs_users[i]; tu; tu=tu->next) {
1791 if (tu->uid == areq->uid) {
1793 tu->states &= ~UHasTokens;
1794 /* security is not having to say you're sorry */
1795 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1797 ReleaseWriteLock(&afs_xuser);
1798 /* We have to drop the lock over the call to afs_ResetUserConns, since
1799 * it obtains the afs_xvcache lock. We could also keep the lock, and
1800 * modify ResetUserConns to take parm saying we obtained the lock
1801 * already, but that is overkill. By keeping the "tu" pointer
1802 * held over the released lock, we guarantee that we won't lose our
1803 * place, and that we'll pass over every user conn that existed when
1804 * we began this call.
1806 afs_ResetUserConns(tu);
1808 ObtainWriteLock(&afs_xuser,228);
1810 /* set the expire times to 0, causes
1811 * afs_GCUserData to remove this entry
1813 tu->ct.EndTimestamp = 0;
1815 #endif /* UKERNEL */
1818 ReleaseWriteLock(&afs_xuser);
1822 DECL_PIOCTL(PMariner)
1824 afs_int32 newHostAddr;
1825 afs_int32 oldHostAddr;
1827 AFS_STATCNT(PMariner);
1829 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1831 oldHostAddr = 0xffffffff; /* disabled */
1833 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1834 if (newHostAddr == 0xffffffff) {
1835 /* disable mariner operations */
1838 else if (newHostAddr) {
1840 afs_marinerHost = newHostAddr;
1842 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1843 *aoutSize = sizeof(afs_int32);
1847 DECL_PIOCTL(PCheckServers)
1849 register char *cp = 0;
1851 register struct server *ts;
1852 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1854 struct chservinfo *pcheck;
1856 AFS_STATCNT(PCheckServers);
1858 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1859 return EIO; /* Inappropriate ioctl for device */
1861 if (*lp == 0x12345678) { /* For afs3.3 version */
1862 pcheck=(struct chservinfo *)ain;
1863 if (pcheck->tinterval >= 0) {
1865 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1866 *aoutSize = sizeof(afs_int32);
1867 if (pcheck->tinterval > 0) {
1868 if (!afs_osi_suser(*acred))
1870 PROBE_INTERVAL=pcheck->tinterval;
1876 temp=pcheck->tflags;
1877 cp = pcheck->tbuffer;
1878 } else { /* For pre afs3.3 versions */
1879 memcpy((char *)&temp, ain, sizeof(afs_int32));
1880 cp = ain+sizeof(afs_int32);
1881 if (ainSize > sizeof(afs_int32))
1886 * 1: fast check, don't contact servers.
1887 * 2: local cell only.
1890 /* have cell name, too */
1891 cellp = afs_GetCellByName(cp, READ_LOCK);
1892 if (!cellp) return ENOENT;
1895 if (!cellp && (temp & 2)) {
1896 /* use local cell */
1897 cellp = afs_GetPrimaryCell(READ_LOCK);
1899 if (!(temp & 1)) { /* if not fast, call server checker routine */
1900 afs_CheckServers(1, cellp); /* check down servers */
1901 afs_CheckServers(0, cellp); /* check up servers */
1903 /* now return the current down server list */
1905 ObtainReadLock(&afs_xserver);
1906 for(i=0;i<NSERVERS;i++) {
1907 for(ts = afs_servers[i]; ts; ts=ts->next) {
1908 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1909 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1910 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1911 cp += sizeof(afs_int32);
1915 ReleaseReadLock(&afs_xserver);
1916 if (cellp) afs_PutCell(cellp, READ_LOCK);
1917 *aoutSize = cp - aout;
1921 DECL_PIOCTL(PCheckVolNames)
1923 AFS_STATCNT(PCheckVolNames);
1924 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1925 return EIO; /* Inappropriate ioctl for device */
1927 afs_CheckRootVolume();
1928 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1929 AFS_VOLCHECK_EXPIRED |
1931 AFS_VOLCHECK_MTPTS);
1935 DECL_PIOCTL(PCheckAuth)
1940 struct unixuser *tu;
1943 AFS_STATCNT(PCheckAuth);
1944 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1945 return EIO; /* Inappropriate ioctl for device */
1948 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1949 if (!tu) retValue = EACCES;
1951 /* we have a user */
1952 ObtainReadLock(&afs_xsrvAddr);
1953 ObtainReadLock(&afs_xconn);
1955 /* any tokens set? */
1956 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1957 /* all connections in cell 1 working? */
1958 for(i=0;i<NSERVERS;i++) {
1959 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1960 for (tc = sa->conns; tc; tc=tc->next) {
1961 if (tc->user == tu && (tu->states & UTokensBad))
1966 ReleaseReadLock(&afs_xsrvAddr);
1967 ReleaseReadLock(&afs_xconn);
1968 afs_PutUser(tu, READ_LOCK);
1970 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1971 *aoutSize = sizeof(afs_int32);
1975 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1978 register afs_int32 code;
1979 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1985 AFS_STATCNT(Prefetch);
1986 if (!apath) return EINVAL;
1987 tp = osi_AllocLargeSpace(1024);
1988 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1990 osi_FreeLargeSpace(tp);
1993 if (afs_BBusy()) { /* do this as late as possible */
1994 osi_FreeLargeSpace(tp);
1995 return EWOULDBLOCK; /* pretty close */
1997 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1998 (afs_size_t) 0, (afs_size_t) 0, tp);
2002 DECL_PIOCTL(PFindVolume)
2004 register struct volume *tvp;
2005 register struct server *ts;
2006 register afs_int32 i;
2009 AFS_STATCNT(PFindVolume);
2010 if (!avc) return EINVAL;
2011 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2014 for(i=0;i<MAXHOSTS;i++) {
2015 ts = tvp->serverHost[i];
2017 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2018 cp += sizeof(afs_int32);
2021 /* still room for terminating NULL, add it on */
2022 ainSize = 0; /* reuse vbl */
2023 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2024 cp += sizeof(afs_int32);
2026 *aoutSize = cp - aout;
2027 afs_PutVolume(tvp, READ_LOCK);
2033 DECL_PIOCTL(PViceAccess)
2035 register afs_int32 code;
2038 AFS_STATCNT(PViceAccess);
2039 if (!avc) return EINVAL;
2040 code = afs_VerifyVCache(avc, areq);
2041 if (code) return code;
2042 memcpy((char *)&temp, ain, sizeof(afs_int32));
2043 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2048 DECL_PIOCTL(PSetCacheSize)
2053 AFS_STATCNT(PSetCacheSize);
2054 if (!afs_osi_suser(*acred))
2056 /* too many things are setup initially in mem cache version */
2057 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2058 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2059 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2061 if (newValue < afs_min_cache)
2062 afs_cacheBlocks = afs_min_cache;
2064 afs_cacheBlocks = newValue;
2066 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2067 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2068 afs_MaybeWakeupTruncateDaemon();
2069 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2070 afs_osi_Wait(1000, 0, 0);
2071 afs_MaybeWakeupTruncateDaemon();
2076 #define MAXGCSTATS 16
2077 DECL_PIOCTL(PGetCacheSize)
2079 afs_int32 results[MAXGCSTATS];
2081 AFS_STATCNT(PGetCacheSize);
2082 memset((char *)results, 0, sizeof(results));
2083 results[0] = afs_cacheBlocks;
2084 results[1] = afs_blocksUsed;
2085 memcpy(aout, (char *)results, sizeof(results));
2086 *aoutSize = sizeof(results);
2090 DECL_PIOCTL(PRemoveCallBack)
2092 register struct conn *tc;
2093 register afs_int32 code;
2094 struct AFSCallBack CallBacks_Array[1];
2095 struct AFSCBFids theFids;
2096 struct AFSCBs theCBs;
2099 AFS_STATCNT(PRemoveCallBack);
2100 if (!avc) return EINVAL;
2101 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2102 ObtainWriteLock(&avc->lock,229);
2103 theFids.AFSCBFids_len = 1;
2104 theCBs.AFSCBs_len = 1;
2105 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2106 theCBs.AFSCBs_val = CallBacks_Array;
2107 CallBacks_Array[0].CallBackType = CB_DROPPED;
2108 if (avc->callback) {
2110 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2112 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2114 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2118 /* don't set code on failure since we wouldn't use it */
2120 (afs_Analyze(tc, code, &avc->fid, areq,
2121 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2122 SHARED_LOCK, NULL));
2124 ObtainWriteLock(&afs_xcbhash, 457);
2125 afs_DequeueCallback(avc);
2127 avc->states &= ~(CStatd | CUnique);
2128 ReleaseWriteLock(&afs_xcbhash);
2129 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2130 osi_dnlc_purgedp(avc);
2132 ReleaseWriteLock(&avc->lock);
2136 DECL_PIOCTL(PNewCell)
2138 /* create a new cell */
2139 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2140 register struct cell *tcell;
2141 char *newcell=0, *linkedcell=0, *tp= ain;
2142 register afs_int32 code, linkedstate=0, ls;
2143 u_short fsport = 0, vlport = 0;
2146 AFS_STATCNT(PNewCell);
2147 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2148 return EIO; /* Inappropriate ioctl for device */
2150 if (!afs_osi_suser(*acred))
2153 memcpy((char *)&magic, tp, sizeof(afs_int32));
2154 tp += sizeof(afs_int32);
2155 if (magic != 0x12345678)
2158 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2159 * server addresses while the 3.5 fs newcell command passes
2160 * MAXHOSTS. To figure out which is which, check if the cellname
2163 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2164 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2166 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2167 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2168 tp += (scount * sizeof(afs_int32));
2170 lp = (afs_int32 *)tp;
2173 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2174 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2175 tp += (3 * sizeof(afs_int32));
2177 if ((ls = *lp) & 1) {
2178 linkedcell = tp + strlen(newcell)+1;
2179 linkedstate |= CLinkedCell;
2182 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2183 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2188 DECL_PIOCTL(PNewAlias)
2190 /* create a new cell alias */
2192 register afs_int32 code;
2193 char *realName, *aliasName;
2195 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2196 return EIO; /* Inappropriate ioctl for device */
2198 if (!afs_osi_suser(*acred))
2202 tp += strlen(aliasName) + 1;
2205 code = afs_NewCellAlias(aliasName, realName);
2210 DECL_PIOCTL(PListCells)
2212 afs_int32 whichCell;
2213 register struct cell *tcell=0;
2214 register afs_int32 i;
2215 register char *cp, *tp = ain;
2217 AFS_STATCNT(PListCells);
2218 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2219 return EIO; /* Inappropriate ioctl for device */
2221 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2222 tp += sizeof(afs_int32);
2223 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2226 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2227 for(i=0;i<MAXCELLHOSTS;i++) {
2228 if (tcell->cellHosts[i] == 0) break;
2229 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2230 cp += sizeof(afs_int32);
2232 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2233 strcpy(cp, tcell->cellName);
2234 cp += strlen(tcell->cellName)+1;
2235 *aoutSize = cp - aout;
2236 afs_PutCell(tcell, READ_LOCK);
2238 if (tcell) return 0;
2242 DECL_PIOCTL(PListAliases)
2244 afs_int32 whichAlias;
2245 register struct cell_alias *tcalias=0;
2246 register char *cp, *tp = ain;
2248 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2249 return EIO; /* Inappropriate ioctl for device */
2250 if (ainSize < sizeof(afs_int32))
2253 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2254 tp += sizeof(afs_int32);
2256 tcalias = afs_GetCellAlias(whichAlias);
2259 strcpy(cp, tcalias->alias);
2260 cp += strlen(tcalias->alias)+1;
2261 strcpy(cp, tcalias->cell);
2262 cp += strlen(tcalias->cell)+1;
2263 *aoutSize = cp - aout;
2264 afs_PutCellAlias(tcalias);
2266 if (tcalias) return 0;
2270 DECL_PIOCTL(PRemoveMount)
2272 register afs_int32 code;
2274 struct sysname_info sysState;
2275 afs_size_t offset, len;
2276 register struct conn *tc;
2277 register struct dcache *tdc;
2278 register struct vcache *tvc;
2279 struct AFSFetchStatus OutDirStatus;
2280 struct VenusFid tfid;
2281 struct AFSVolSync tsync;
2285 /* "ain" is the name of the file in this dir to remove */
2287 AFS_STATCNT(PRemoveMount);
2288 if (!avc) return EINVAL;
2289 code = afs_VerifyVCache(avc, areq);
2290 if (code) return code;
2291 if (vType(avc) != VDIR) return ENOTDIR;
2293 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2294 if (!tdc) return ENOENT;
2295 Check_AtSys(avc, ain, &sysState, areq);
2296 ObtainReadLock(&tdc->lock);
2298 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2299 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2300 ReleaseReadLock(&tdc->lock);
2301 bufp = sysState.name;
2306 tfid.Cell = avc->fid.Cell;
2307 tfid.Fid.Volume = avc->fid.Fid.Volume;
2308 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2309 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2311 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2318 if (tvc->mvstat != 1) {
2324 ObtainWriteLock(&tvc->lock,230);
2325 code = afs_HandleLink(tvc, areq);
2327 if (tvc->linkData) {
2328 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2333 ReleaseWriteLock(&tvc->lock);
2334 osi_dnlc_purgedp(tvc);
2340 ObtainWriteLock(&avc->lock,231);
2341 osi_dnlc_remove(avc, bufp, tvc);
2343 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2345 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2347 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2348 bufp, &OutDirStatus, &tsync);
2354 (afs_Analyze(tc, code, &avc->fid, areq,
2355 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2356 SHARED_LOCK, NULL));
2359 if (tdc) afs_PutDCache(tdc);
2360 ReleaseWriteLock(&avc->lock);
2364 /* we have the thing in the cache */
2365 ObtainWriteLock(&tdc->lock, 661);
2366 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2367 /* we can do it locally */
2368 code = afs_dir_Delete(&tdc->f.inode, bufp);
2370 ZapDCE(tdc); /* surprise error -- invalid value */
2371 DZap(&tdc->f.inode);
2374 ReleaseWriteLock(&tdc->lock);
2375 afs_PutDCache(tdc); /* drop ref count */
2377 avc->states &= ~CUnique; /* For the dfs xlator */
2378 ReleaseWriteLock(&avc->lock);
2381 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2385 DECL_PIOCTL(PVenusLogging)
2387 return EINVAL; /* OBSOLETE */
2390 DECL_PIOCTL(PGetCellStatus)
2392 register struct cell *tcell;
2395 AFS_STATCNT(PGetCellStatus);
2396 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2397 return EIO; /* Inappropriate ioctl for device */
2399 tcell = afs_GetCellByName(ain, READ_LOCK);
2400 if (!tcell) return ENOENT;
2401 temp = tcell->states;
2402 afs_PutCell(tcell, READ_LOCK);
2403 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2404 *aoutSize = sizeof(afs_int32);
2408 DECL_PIOCTL(PSetCellStatus)
2410 register struct cell *tcell;
2413 if (!afs_osi_suser(*acred))
2415 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2416 return EIO; /* Inappropriate ioctl for device */
2418 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2419 if (!tcell) return ENOENT;
2420 memcpy((char *)&temp, ain, sizeof(afs_int32));
2422 tcell->states |= CNoSUID;
2424 tcell->states &= ~CNoSUID;
2425 afs_PutCell(tcell, WRITE_LOCK);
2429 DECL_PIOCTL(PFlushVolumeData)
2431 register afs_int32 i;
2432 register struct dcache *tdc;
2433 register struct vcache *tvc;
2434 register struct volume *tv;
2435 afs_int32 cell, volume;
2437 AFS_STATCNT(PFlushVolumeData);
2440 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2441 return EIO; /* Inappropriate ioctl for device */
2443 volume = avc->fid.Fid.Volume; /* who to zap */
2444 cell = avc->fid.Cell;
2447 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2448 * the vcaches associated with the volume.
2450 ObtainReadLock(&afs_xvcache);
2451 for(i = 0; i < VCSIZE; i++) {
2452 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2453 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2454 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2455 VN_HOLD(AFSTOV(tvc));
2457 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2463 ReleaseReadLock(&afs_xvcache);
2464 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2465 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2467 ObtainWriteLock(&tvc->lock,232);
2469 ObtainWriteLock(&afs_xcbhash, 458);
2470 afs_DequeueCallback(tvc);
2471 tvc->states &= ~(CStatd | CDirty);
2472 ReleaseWriteLock(&afs_xcbhash);
2473 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2474 osi_dnlc_purgedp(tvc);
2475 afs_TryToSmush(tvc, *acred, 1);
2476 ReleaseWriteLock(&tvc->lock);
2477 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2478 afs_BozonUnlock(&tvc->pvnLock, tvc);
2480 ObtainReadLock(&afs_xvcache);
2481 /* our tvc ptr is still good until now */
2486 ReleaseReadLock(&afs_xvcache);
2489 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2490 for(i=0;i<afs_cacheFiles;i++) {
2491 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2492 tdc = afs_GetDSlot(i, NULL);
2493 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2494 ReleaseReadLock(&tdc->tlock);
2495 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2496 if (! (afs_indexFlags[i] & IFDataMod)) {
2497 /* if the file is modified, but has a ref cnt of only 1, then
2498 someone probably has the file open and is writing into it.
2499 Better to skip flushing such a file, it will be brought back
2500 immediately on the next write anyway.
2502 If we *must* flush, then this code has to be rearranged to call
2503 afs_storeAllSegments() first */
2504 afs_FlushDCache(tdc);
2508 ReleaseReadLock(&tdc->tlock);
2510 afs_PutDCache(tdc); /* bumped by getdslot */
2512 MReleaseWriteLock(&afs_xdcache);
2514 ObtainReadLock(&afs_xvolume);
2515 for (i=0;i<NVOLS;i++) {
2516 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2517 if (tv->volume == volume) {
2518 afs_ResetVolumeInfo(tv);
2523 ReleaseReadLock(&afs_xvolume);
2525 /* probably, a user is doing this, probably, because things are screwed up.
2526 * maybe it's the dnlc's fault? */
2533 DECL_PIOCTL(PGetVnodeXStatus)
2535 register afs_int32 code;
2536 struct vcxstat stat;
2539 /* AFS_STATCNT(PGetVnodeXStatus); */
2540 if (!avc) return EINVAL;
2541 code = afs_VerifyVCache(avc, areq);
2542 if (code) return code;
2543 if (vType(avc) == VDIR)
2544 mode = PRSFS_LOOKUP;
2547 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2549 stat.fid = avc->fid;
2550 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2551 stat.lock = avc->lock;
2552 stat.parentVnode = avc->parentVnode;
2553 stat.parentUnique = avc->parentUnique;
2554 hset(stat.flushDV, avc->flushDV);
2555 hset(stat.mapDV, avc->mapDV);
2556 stat.truncPos = avc->truncPos;
2557 { /* just grab the first two - won't break anything... */
2558 struct axscache *ac;
2560 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2561 stat.randomUid[i] = ac->uid;
2562 stat.randomAccess[i] = ac->axess;
2565 stat.callback = afs_data_pointer_to_int32(avc->callback);
2566 stat.cbExpires = avc->cbExpires;
2567 stat.anyAccess = avc->anyAccess;
2568 stat.opens = avc->opens;
2569 stat.execsOrWriters = avc->execsOrWriters;
2570 stat.flockCount = avc->flockCount;
2571 stat.mvstat = avc->mvstat;
2572 stat.states = avc->states;
2573 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2574 *aoutSize = sizeof(struct vcxstat);
2579 /* We require root for local sysname changes, but not for remote */
2580 /* (since we don't really believe remote uids anyway) */
2581 /* outname[] shouldn't really be needed- this is left as an excercise */
2582 /* for the reader. */
2583 DECL_PIOCTL(PSetSysName)
2585 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2586 int setsysname, foundname=0;
2587 register struct afs_exporter *exporter;
2588 register struct unixuser *au;
2589 register afs_int32 pag, error;
2593 AFS_STATCNT(PSetSysName);
2594 if (!afs_globalVFS) {
2595 /* Afsd is NOT running; disable it */
2596 #if defined(KERNEL_HAVE_SETUERROR)
2597 return (setuerror(EINVAL), EINVAL);
2602 memset(inname, 0, MAXSYSNAME);
2603 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2604 ain += sizeof(afs_int32);
2608 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2610 for(cp = ain,count = 0;count < setsysname;count++) {
2611 /* won't go past end of ain since maxsysname*num < ain length */
2613 if (t >= MAXSYSNAME || t <= 0)
2615 /* check for names that can shoot us in the foot */
2616 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2622 /* inname gets first entry in case we're being a translater */
2624 memcpy(inname, ain, t+1); /* include terminating null */
2627 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2628 pag = PagInCred(*acred);
2630 return EINVAL; /* Better than panicing */
2632 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2633 return EINVAL; /* Better than panicing */
2635 if (!(exporter = au->exporter)) {
2636 afs_PutUser(au, READ_LOCK);
2637 return EINVAL; /* Better than panicing */
2639 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2641 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2643 afs_PutUser(au, READ_LOCK);
2648 afs_PutUser(au, READ_LOCK);
2651 /* Not xlating, so local case */
2652 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2653 if (!setsysname) { /* user just wants the info */
2654 strcpy(outname, afs_sysname);
2655 foundname = afs_sysnamecount;
2656 } else { /* Local guy; only root can change sysname */
2657 if (!afs_osi_suser(*acred))
2660 /* clear @sys entries from the dnlc, once afs_lookup can
2661 do lookups of @sys entries and thinks it can trust them */
2662 /* privs ok, store the entry, ... */
2663 strcpy(afs_sysname, inname);
2664 if (setsysname > 1) { /* ... or list */
2666 for(count=1; count < setsysname;++count) {
2667 if (!afs_sysnamelist[count])
2668 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2670 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2674 afs_sysnamecount = setsysname;
2678 cp = aout; /* not changing so report back the count and ... */
2679 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2680 cp += sizeof(afs_int32);
2682 strcpy(cp, outname); /* ... the entry, ... */
2683 cp += strlen(outname)+1;
2684 for(count=1; count < foundname; ++count) { /* ... or list. */
2685 /* Note: we don't support @sys lists for exporters */
2686 if (!afs_sysnamelist[count])
2687 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2688 t = strlen(afs_sysnamelist[count]);
2689 if (t >= MAXSYSNAME)
2690 osi_Panic("PSetSysName: sysname entry garbled\n");
2691 strcpy(cp, afs_sysnamelist[count]);
2695 *aoutSize = cp - aout;
2700 /* sequential search through the list of touched cells is not a good
2701 * long-term solution here. For small n, though, it should be just
2702 * fine. Should consider special-casing the local cell for large n.
2703 * Likewise for PSetSPrefs.
2705 * s - number of ids in array l[] -- NOT index of last id
2706 * l - array of cell ids which have volumes that need to be sorted
2707 * vlonly - sort vl servers or file servers?
2709 static void *ReSortCells_cb(struct cell *cell, void *arg)
2711 afs_int32 *p = (afs_int32 *) arg;
2712 afs_int32 *l = p + 1;
2715 for (i=0; i<s; i++) {
2716 if (l[i] == cell->cellNum) {
2717 ObtainWriteLock(&cell->lock, 690);
2718 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2719 ReleaseWriteLock(&cell->lock);
2724 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2732 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2734 memcpy(p+1, l, s * sizeof(afs_int32));
2735 afs_TraverseCells(&ReSortCells_cb, p);
2736 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2740 ObtainReadLock(&afs_xvolume);
2741 for (i= 0; i< NVOLS; i++) {
2742 for (j=afs_volumes[i];j;j=j->next) {
2744 if (j->cell == l[k]) {
2745 ObtainWriteLock(&j->lock,233);
2746 afs_SortServers(j->serverHost, MAXHOSTS);
2747 ReleaseWriteLock(&j->lock);
2752 ReleaseReadLock(&afs_xvolume);
2756 static int debugsetsp = 0;
2757 static int afs_setsprefs(sp, num, vlonly)
2760 unsigned int vlonly;
2763 int i,j,k,matches,touchedSize;
2764 struct server *srvr = NULL;
2765 afs_int32 touched[34];
2769 for (k=0; k < num; sp++, k++) {
2771 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2774 ObtainReadLock(&afs_xserver);
2776 i = SHash(sp->host.s_addr);
2777 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2778 if (sa->sa_ip == sp->host.s_addr) {
2780 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2781 || (sa->sa_portal == AFS_FSPORT);
2782 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2789 if (sa && matches) { /* found one! */
2791 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2793 sa->sa_iprank = sp->rank + afs_randomMod15();
2794 afs_SortOneServer(sa->server);
2797 /* if we don't know yet what cell it's in, this is moot */
2798 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2799 /* is it in our list of touched cells ? */ ;
2800 if (j < 0) { /* no, it's not */
2801 touched[touchedSize++] = srvr->cell->cellNum;
2802 if (touchedSize >= 32) { /* watch for ovrflow */
2803 ReleaseReadLock(&afs_xserver);
2804 ReSortCells(touchedSize, touched, vlonly);
2806 ObtainReadLock(&afs_xserver);
2812 ReleaseReadLock(&afs_xserver);
2813 /* if we didn't find one, start to create one. */
2814 /* Note that it doesn't have a cell yet... */
2816 afs_uint32 temp = sp->host.s_addr;
2817 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2818 WRITE_LOCK, (afsUUID *)0,0);
2819 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2820 afs_PutServer(srvr, WRITE_LOCK);
2822 } /* for all cited preferences */
2824 ReSortCells(touchedSize, touched, vlonly);
2828 /* Note that this may only be performed by the local root user.
2830 DECL_PIOCTL(PSetSPrefs)
2832 struct setspref *ssp;
2833 AFS_STATCNT(PSetSPrefs);
2835 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2836 return EIO; /* Inappropriate ioctl for device */
2838 if (!afs_osi_suser(*acred))
2841 if (ainSize < sizeof(struct setspref))
2844 ssp = (struct setspref *)ain;
2845 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2848 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2849 (ssp->flags & DBservers));
2853 DECL_PIOCTL(PSetSPrefs33)
2856 AFS_STATCNT(PSetSPrefs);
2857 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2858 return EIO; /* Inappropriate ioctl for device */
2861 if (!afs_osi_suser(*acred))
2864 sp = (struct spref *)ain;
2865 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2869 /* some notes on the following code...
2870 * in the hash table of server structs, all servers with the same IP address
2871 * will be on the same overflow chain.
2872 * This could be sped slightly in some circumstances by having it cache the
2873 * immediately previous slot in the hash table and some supporting information
2874 * Only reports file servers now.
2876 DECL_PIOCTL(PGetSPrefs)
2878 struct sprefrequest *spin; /* input */
2879 struct sprefinfo *spout; /* output */
2880 struct spref *srvout; /* one output component */
2881 int i,j; /* counters for hash table traversal */
2882 struct server *srvr; /* one of CM's server structs */
2885 int vlonly; /* just return vlservers ? */
2888 AFS_STATCNT(PGetSPrefs);
2889 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2890 return EIO; /* Inappropriate ioctl for device */
2893 if (ainSize < sizeof (struct sprefrequest_33)) {
2897 spin = ((struct sprefrequest *) ain);
2900 if (ainSize > sizeof (struct sprefrequest_33)) {
2901 vlonly = (spin->flags & DBservers);
2905 /* struct sprefinfo includes 1 server struct... that size gets added
2906 * in during the loop that follows.
2908 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2909 spout = (struct sprefinfo *) aout;
2910 spout->next_offset = spin->offset;
2911 spout->num_servers = 0;
2912 srvout = spout->servers;
2914 ObtainReadLock(&afs_xserver);
2915 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2916 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2917 if (spin->offset > (unsigned short)i) {
2918 continue; /* catch up to where we left off */
2920 spout->next_offset++;
2923 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2924 || (sa->sa_portal == AFS_FSPORT);
2926 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2927 /* only report ranks for vl servers */
2931 srvout->host.s_addr = sa->sa_ip;
2932 srvout->rank = sa->sa_iprank;
2933 *aoutSize += sizeof(struct spref);
2934 spout->num_servers++;
2937 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2938 ReleaseReadLock(&afs_xserver); /* no more room! */
2943 ReleaseReadLock(&afs_xserver);
2945 spout->next_offset = 0; /* start over from the beginning next time */
2949 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2950 int afs_NFSRootOnly = 1;
2951 DECL_PIOCTL(PExportAfs)
2953 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2954 register struct afs_exporter *exporter;
2956 AFS_STATCNT(PExportAfs);
2957 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2958 type = handleValue >> 24;
2963 exporter = exporter_find(type);
2965 export = handleValue & 3;
2966 changestate = handleValue & 0xff;
2967 smounts = (handleValue >> 2) & 3;
2968 pwsync = (handleValue >> 4) & 3;
2969 convmode = (handleValue >> 6) & 3;
2971 changestate = (handleValue >> 16) & 0x1;
2972 convmode = (handleValue >> 16) & 0x2;
2973 pwsync = (handleValue >> 16) & 0x4;
2974 smounts = (handleValue >> 16) & 0x8;
2975 export = handleValue & 0xff;
2978 /* Failed finding desired exporter; */
2982 handleValue = exporter->exp_states;
2983 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2984 *aoutSize = sizeof(afs_int32);
2986 if (!afs_osi_suser(*acred))
2987 return EACCES; /* Only superuser can do this */
2991 exporter->exp_states |= EXP_EXPORTED;
2993 exporter->exp_states &= ~EXP_EXPORTED;
2997 exporter->exp_states |= EXP_UNIXMODE;
2999 exporter->exp_states &= ~EXP_UNIXMODE;
3003 exporter->exp_states |= EXP_PWSYNC;
3005 exporter->exp_states &= ~EXP_PWSYNC;
3009 afs_NFSRootOnly = 0;
3010 exporter->exp_states |= EXP_SUBMOUNTS;
3012 afs_NFSRootOnly = 1;
3013 exporter->exp_states &= ~EXP_SUBMOUNTS;
3016 handleValue = exporter->exp_states;
3017 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3018 *aoutSize = sizeof(afs_int32);
3021 exporter->exp_states |= EXP_EXPORTED;
3023 exporter->exp_states &= ~EXP_EXPORTED;
3025 exporter->exp_states |= EXP_UNIXMODE;
3027 exporter->exp_states &= ~EXP_UNIXMODE;
3029 exporter->exp_states |= EXP_PWSYNC;
3031 exporter->exp_states &= ~EXP_PWSYNC;
3033 afs_NFSRootOnly = 0;
3034 exporter->exp_states |= EXP_SUBMOUNTS;
3036 afs_NFSRootOnly = 1;
3037 exporter->exp_states &= ~EXP_SUBMOUNTS;
3047 struct gaginfo *gagflags;
3049 if (!afs_osi_suser(*acred))
3052 gagflags = (struct gaginfo *) ain;
3053 afs_showflags = gagflags->showflags;
3059 DECL_PIOCTL(PTwiddleRx)
3061 struct rxparams *rxp;
3063 if (!afs_osi_suser(*acred))
3066 rxp = (struct rxparams *) ain;
3068 if (rxp->rx_initReceiveWindow)
3069 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3070 if (rxp->rx_maxReceiveWindow)
3071 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3072 if (rxp->rx_initSendWindow)
3073 rx_initSendWindow = rxp->rx_initSendWindow;
3074 if (rxp->rx_maxSendWindow)
3075 rx_maxSendWindow = rxp->rx_maxSendWindow;
3076 if (rxp->rxi_nSendFrags)
3077 rxi_nSendFrags = rxp->rxi_nSendFrags;
3078 if (rxp->rxi_nRecvFrags)
3079 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3080 if (rxp->rxi_OrphanFragSize)
3081 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3082 if (rxp->rx_maxReceiveSize)
3084 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3085 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3087 if (rxp->rx_MyMaxSendSize)
3088 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3093 DECL_PIOCTL(PGetInitParams)
3095 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3098 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3099 *aoutSize = sizeof(struct cm_initparams);
3103 #ifdef AFS_SGI65_ENV
3104 /* They took crget() from us, so fake it. */
3105 static cred_t *crget(void)
3108 cr = crdup(get_current_cred());
3109 memset((char*)cr, 0, sizeof(cred_t));
3110 #if CELL || CELL_PREPARE
3117 DECL_PIOCTL(PGetRxkcrypt)
3119 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3120 *aoutSize=sizeof(afs_int32);
3124 DECL_PIOCTL(PSetRxkcrypt)
3128 if (!afs_osi_suser(*acred))
3130 if (ainSize != sizeof(afs_int32) || ain == NULL)
3132 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3133 /* if new mappings added later this will need to be changed */
3134 if (tmpval != 0 && tmpval != 1)
3141 * Create new credentials to correspond to a remote user with given
3142 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3143 * provide pioctl (and other) services to foreign clients (i.e. nfs
3144 * clients) by using this call to `become' the client.
3147 #define PIOCTL_HEADER 6
3148 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3150 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3151 return EINVAL; /* NFS trans not supported for Ultrix */
3154 afs_uint32 hostaddr;
3155 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3156 struct afs_exporter *exporter, *outexporter;
3157 struct AFS_UCRED *newcred;
3158 struct unixuser *au;
3160 #if defined(AFS_SGIMP_ENV)
3161 osi_Assert(ISAFS_GLOCK());
3163 AFS_STATCNT(HandleClientContext);
3164 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3165 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3166 return EINVAL; /* Too small to be good */
3168 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3169 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3171 osi_FreeLargeSpace(inData);
3175 /* Extract information for remote user */
3176 hostaddr = *((afs_uint32 *)ain);
3177 ain += sizeof(hostaddr);
3178 uid = *((afs_uint32 *)ain);
3180 g0 = *((afs_uint32 *)ain);
3182 g1 = *((afs_uint32 *)ain);
3184 *com = *((afs_uint32 *)ain);
3185 ain += sizeof(afs_int32);
3186 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3189 * Of course, one must be root for most of these functions, but
3190 * we'll allow (for knfs) you to set things if the pag is 0 and
3191 * you're setting tokens or unlogging.
3194 if (!afs_osi_suser(credp)) {
3196 #ifndef AFS_SGI64_ENV
3197 /* Since SGI's suser() returns explicit failure after the call.. */
3201 /* check for acceptable opcodes for normal folks, which are, so far,
3202 * set tokens and unlog.
3204 if (i != 9 && i != 3 && i != 38 && i != 8) {
3205 osi_FreeLargeSpace(inData);
3210 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3211 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3212 osi_FreeLargeSpace(inData);
3215 * We map uid 0 to nobody to match the mapping that the nfs
3216 * server does and to ensure that the suser() calls in the afs
3217 * code fails for remote client roots.
3219 uid = afs_nobody; /* NFS_NOBODY == -2 */
3222 #ifdef AFS_AIX41_ENV
3225 newcred->cr_gid = RMTUSER_REQ;
3226 #ifdef AFS_AIX51_ENV
3227 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3228 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3230 newcred->cr_groups[0] = g0;
3231 newcred->cr_groups[1] = g1;
3234 newcred->cr_ngrps = 2;
3236 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3237 newcred->cr_ngroups = 2;
3239 for (i=2; i<NGROUPS; i++)
3240 newcred->cr_groups[i] = NOGROUP;
3243 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3244 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3246 if (!(exporter = exporter_find(exporter_type))) {
3247 /* Exporter wasn't initialized or an invalid exporter type */
3251 if (exporter->exp_states & EXP_PWSYNC) {
3252 if (uid != credp->cr_uid) {
3254 return ENOEXEC; /* XXX Find a better errno XXX */
3257 newcred->cr_uid = uid; /* Only temporary */
3258 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3259 /* The client's pag is the only unique identifier for it */
3260 newcred->cr_uid = pag;
3262 if (!code && *com == PSETPAG) {
3263 /* Special case for 'setpag' */
3264 afs_uint32 pagvalue = genpag();
3266 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3268 * Note that we leave the 'outexporter' struct held so it won't
3271 au->exporter = outexporter;
3272 if (ablob->out_size >= 4) {
3273 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3275 afs_PutUser(au, WRITE_LOCK);
3276 if (code) return code;
3277 return PSETPAG; /* Special return for setpag */
3279 EXP_RELE(outexporter);
3282 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3285 /* get all interface addresses of this client */
3287 DECL_PIOCTL(PGetCPrefs)
3289 struct sprefrequest *spin; /* input */
3290 struct sprefinfo *spout; /* output */
3291 struct spref *srvout; /* one output component */
3295 AFS_STATCNT(PGetCPrefs);
3296 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3297 return EIO; /* Inappropriate ioctl for device */
3299 if ( ainSize < sizeof (struct sprefrequest ))
3302 spin = (struct sprefrequest *) ain;
3303 spout = (struct sprefinfo *) aout;
3305 maxNumber = spin->num_servers; /* max addrs this time */
3306 srvout = spout->servers;
3308 ObtainReadLock(&afs_xinterface);
3310 /* copy out the client interface information from the
3311 ** kernel data structure "interface" to the output buffer
3313 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3314 && ( j< maxNumber) ; i++, j++, srvout++)
3315 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3317 spout->num_servers = j;
3318 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3320 if ( i >= afs_cb_interface.numberOfInterfaces )
3321 spout->next_offset = 0; /* start from beginning again */
3323 spout->next_offset = spin->offset + j;
3325 ReleaseReadLock(&afs_xinterface);
3329 DECL_PIOCTL(PSetCPrefs)
3331 struct setspref *sin;
3334 AFS_STATCNT(PSetCPrefs);
3335 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3336 return EIO; /* Inappropriate ioctl for device */
3338 sin = (struct setspref *)ain;
3340 if ( ainSize < sizeof(struct setspref) )
3342 #if 0 /* num_servers is unsigned */
3343 if ( sin->num_servers < 0 )
3346 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3349 ObtainWriteLock(&afs_xinterface, 412);
3350 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3351 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3352 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3354 ReleaseWriteLock(&afs_xinterface);
3358 DECL_PIOCTL(PFlushMount)
3360 register afs_int32 code;
3361 register struct vcache *tvc;
3362 register struct dcache *tdc;
3363 struct VenusFid tfid;
3365 struct sysname_info sysState;
3366 afs_size_t offset, len;
3368 AFS_STATCNT(PFlushMount);
3369 if (!avc) return EINVAL;
3370 code = afs_VerifyVCache(avc, areq);
3371 if (code) return code;
3372 if (vType(avc) != VDIR) {
3375 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3376 if (!tdc) return ENOENT;
3377 Check_AtSys(avc, ain, &sysState, areq);
3378 ObtainReadLock(&tdc->lock);
3380 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3381 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3382 ReleaseReadLock(&tdc->lock);
3383 afs_PutDCache(tdc); /* we're done with the data */
3384 bufp = sysState.name;
3388 tfid.Cell = avc->fid.Cell;
3389 tfid.Fid.Volume = avc->fid.Fid.Volume;
3390 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3391 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3393 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3399 if (tvc->mvstat != 1) {
3404 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3405 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3407 ObtainWriteLock(&tvc->lock,649);
3408 ObtainWriteLock(&afs_xcbhash, 650);
3409 afs_DequeueCallback(tvc);
3410 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3411 ReleaseWriteLock(&afs_xcbhash);
3412 /* now find the disk cache entries */
3413 afs_TryToSmush(tvc, *acred, 1);
3414 osi_dnlc_purgedp(tvc);
3415 afs_symhint_inval(tvc);
3416 if (tvc->linkData && !(tvc->states & CCore)) {
3417 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3418 tvc->linkData = NULL;
3420 ReleaseWriteLock(&tvc->lock);
3421 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3422 afs_BozonUnlock(&tvc->pvnLock, tvc);
3426 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3430 DECL_PIOCTL(PRxStatProc)
3435 if (!afs_osi_suser(*acred)) {
3439 if (ainSize != sizeof(afs_int32)) {
3443 memcpy((char *)&flags, ain, sizeof(afs_int32));
3444 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3448 if (flags & AFSCALL_RXSTATS_ENABLE) {
3449 rx_enableProcessRPCStats();
3451 if (flags & AFSCALL_RXSTATS_DISABLE) {
3452 rx_disableProcessRPCStats();
3454 if (flags & AFSCALL_RXSTATS_CLEAR) {
3455 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3463 DECL_PIOCTL(PRxStatPeer)
3468 if (!afs_osi_suser(*acred)) {
3472 if (ainSize != sizeof(afs_int32)) {
3476 memcpy((char *)&flags, ain, sizeof(afs_int32));
3477 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3481 if (flags & AFSCALL_RXSTATS_ENABLE) {
3482 rx_enablePeerRPCStats();
3484 if (flags & AFSCALL_RXSTATS_DISABLE) {
3485 rx_disablePeerRPCStats();
3487 if (flags & AFSCALL_RXSTATS_CLEAR) {
3488 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3495 DECL_PIOCTL(PPrefetchFromTape)
3497 register afs_int32 code, code1;
3500 struct rx_call *tcall;
3501 struct AFSVolSync tsync;
3502 struct AFSFetchStatus OutStatus;
3503 struct AFSCallBack CallBack;
3504 struct VenusFid tfid;
3509 AFS_STATCNT(PSetAcl);
3513 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3514 Fid = (struct AFSFid *) ain;
3516 Fid = &avc->fid.Fid;
3517 tfid.Cell = avc->fid.Cell;
3518 tfid.Fid.Volume = Fid->Volume;
3519 tfid.Fid.Vnode = Fid->Vnode;
3520 tfid.Fid.Unique = Fid->Unique;
3522 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3524 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3525 ICL_TYPE_POINTER, tvc,
3526 ICL_TYPE_FID, &tfid,
3527 ICL_TYPE_FID, &avc->fid);
3530 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3531 ICL_TYPE_POINTER, tvc,
3532 ICL_TYPE_FID, &tfid,
3533 ICL_TYPE_FID, &tvc->fid);
3536 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3540 tcall = rx_NewCall(tc->id);
3541 code = StartRXAFS_FetchData(tcall,
3542 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3544 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3545 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3547 code1 = rx_EndCall(tcall, code);
3552 (afs_Analyze(tc, code, &tvc->fid, areq,
3553 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3555 /* This call is done only to have the callback things handled correctly */
3556 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3560 *aoutSize = sizeof(afs_int32);
3565 DECL_PIOCTL(PResidencyCmd)
3567 register afs_int32 code;
3570 struct ResidencyCmdInputs *Inputs;
3571 struct ResidencyCmdOutputs *Outputs;
3572 struct VenusFid tfid;
3575 Inputs = (struct ResidencyCmdInputs *) ain;
3576 Outputs = (struct ResidencyCmdOutputs *) aout;
3577 if (!avc) return EINVAL;
3578 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3582 Fid = &avc->fid.Fid;
3584 tfid.Cell = avc->fid.Cell;
3585 tfid.Fid.Volume = Fid->Volume;
3586 tfid.Fid.Vnode = Fid->Vnode;
3587 tfid.Fid.Unique = Fid->Unique;
3589 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3590 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3591 ICL_TYPE_POINTER, tvc,
3592 ICL_TYPE_INT32, Inputs->command,
3593 ICL_TYPE_FID, &tfid);
3597 if (Inputs->command) {
3599 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3602 code = RXAFS_ResidencyCmd(tc->id, Fid,
3604 (struct ResidencyCmdOutputs *) aout);
3609 (afs_Analyze(tc, code, &tvc->fid, areq,
3610 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3612 /* This call is done to have the callback things handled correctly */
3613 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3614 } else { /* just a status request, return also link data */
3616 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3617 Outputs->chars[0] = 0;
3618 if (vType(tvc) == VLNK) {
3619 ObtainWriteLock(&tvc->lock,555);
3620 if (afs_HandleLink(tvc, areq) == 0)
3621 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3622 ReleaseWriteLock(&tvc->lock);
3629 *aoutSize = sizeof(struct ResidencyCmdOutputs);