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"
16 #include "afs/sysincludes.h" /* Standard vendor system headers */
18 #include "h/syscallargs.h"
21 #include "h/sysproto.h"
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs/afs_stats.h" /* afs statistics */
26 #include "afs/afs_bypasscache.h"
27 #include "rx/rx_globals.h"
29 struct VenusFid afs_rootFid;
30 afs_int32 afs_waitForever = 0;
31 short afs_waitForeverCount = 0;
32 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
35 afs_int32 afs_is_disconnected;
36 afs_int32 afs_is_logging;
37 afs_int32 afs_is_discon_rw;
38 /* On reconnection, turn this knob on until it finishes,
41 afs_int32 afs_in_sync = 0;
45 * \defgroup pioctl Path IOCTL functions
47 * DECL_PIOCTL is a macro defined to contain the following parameters for functions:
49 * \param[in] avc the AFS vcache structure in use by pioctl
50 * \param[in] afun not in use
51 * \param[in] areq the AFS vrequest structure
52 * \param[in] ain as defined by the function
53 * \param[in] aout as defined by the function
54 * \param[in] ainSize size of ain
55 * \param[in] aoutSize size of aout
56 * \param[in] acred UNIX credentials structure underlying the operation
59 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
60 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
61 struct AFS_UCRED **acred)
63 /* Prototypes for pioctl routines */
66 DECL_PIOCTL(PStoreBehind);
71 DECL_PIOCTL(PGetFileCell);
72 DECL_PIOCTL(PGetWSCell);
73 DECL_PIOCTL(PGetUserCell);
74 DECL_PIOCTL(PSetTokens);
75 DECL_PIOCTL(PGetVolumeStatus);
76 DECL_PIOCTL(PSetVolumeStatus);
78 DECL_PIOCTL(PNewStatMount);
79 DECL_PIOCTL(PGetTokens);
81 DECL_PIOCTL(PMariner);
82 DECL_PIOCTL(PCheckServers);
83 DECL_PIOCTL(PCheckVolNames);
84 DECL_PIOCTL(PCheckAuth);
85 DECL_PIOCTL(PFindVolume);
86 DECL_PIOCTL(PViceAccess);
87 DECL_PIOCTL(PSetCacheSize);
88 DECL_PIOCTL(PGetCacheSize);
89 DECL_PIOCTL(PRemoveCallBack);
90 DECL_PIOCTL(PNewCell);
91 DECL_PIOCTL(PNewAlias);
92 DECL_PIOCTL(PListCells);
93 DECL_PIOCTL(PListAliases);
94 DECL_PIOCTL(PRemoveMount);
95 DECL_PIOCTL(PVenusLogging);
96 DECL_PIOCTL(PGetCellStatus);
97 DECL_PIOCTL(PSetCellStatus);
98 DECL_PIOCTL(PFlushVolumeData);
99 DECL_PIOCTL(PGetVnodeXStatus);
100 DECL_PIOCTL(PGetVnodeXStatus2);
101 DECL_PIOCTL(PSetSysName);
102 DECL_PIOCTL(PSetSPrefs);
103 DECL_PIOCTL(PSetSPrefs33);
104 DECL_PIOCTL(PGetSPrefs);
105 DECL_PIOCTL(PExportAfs);
107 DECL_PIOCTL(PTwiddleRx);
108 DECL_PIOCTL(PGetInitParams);
109 DECL_PIOCTL(PGetRxkcrypt);
110 DECL_PIOCTL(PSetRxkcrypt);
111 DECL_PIOCTL(PGetCPrefs);
112 DECL_PIOCTL(PSetCPrefs);
113 DECL_PIOCTL(PFlushMount);
114 DECL_PIOCTL(PRxStatProc);
115 DECL_PIOCTL(PRxStatPeer);
116 DECL_PIOCTL(PPrefetchFromTape);
118 DECL_PIOCTL(PCallBackAddr);
119 DECL_PIOCTL(PDiscon);
120 DECL_PIOCTL(PNFSNukeCreds);
121 DECL_PIOCTL(PNewUuid);
122 DECL_PIOCTL(PPrecache);
123 #if defined(AFS_CACHE_BYPASS)
124 DECL_PIOCTL(PSetCachingThreshold);
125 DECL_PIOCTL(PSetCachingBlkSize);
129 * A macro that says whether we're going to need HandleClientContext().
130 * This is currently used only by the nfs translator.
132 #if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
133 #define AFS_NEED_CLIENTCONTEXT
136 /* Prototypes for private routines */
137 #ifdef AFS_NEED_CLIENTCONTEXT
138 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
139 struct AFS_UCRED **acred,
140 struct AFS_UCRED *credp);
142 int HandleIoctl(register struct vcache *avc, register afs_int32 acom,
143 struct afs_ioctl *adata);
144 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
145 register struct afs_ioctl *ablob, int afollow,
146 struct AFS_UCRED **acred);
147 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
148 struct AFS_UCRED *acred);
150 typedef int (*pioctlFunction) (struct vcache *, int, struct vrequest *,
151 char *, char *, afs_int32, afs_int32 *,
152 struct AFS_UCRED **);
154 static pioctlFunction VpioctlSw[] = {
159 PGetVolumeStatus, /* 4 */
160 PSetVolumeStatus, /* 5 */
165 PCheckServers, /* 10 */
166 PCheckVolNames, /* 11 */
168 PBogus, /* 13 -- used to be quick check time */
169 PFindVolume, /* 14 */
170 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
171 PBogus, /* 16 -- used to be testing code */
172 PNoop, /* 17 -- used to be enable group */
173 PNoop, /* 18 -- used to be disable group */
174 PBogus, /* 19 -- used to be list group */
175 PViceAccess, /* 20 */
176 PUnlog, /* 21 -- unlog *is* unpag in this system */
177 PGetFID, /* 22 -- get file ID */
178 PBogus, /* 23 -- used to be waitforever */
179 PSetCacheSize, /* 24 */
180 PRemoveCallBack, /* 25 -- flush only the callback */
183 PRemoveMount, /* 28 -- delete mount point */
184 PNewStatMount, /* 29 -- new style mount point stat */
185 PGetFileCell, /* 30 -- get cell name for input file */
186 PGetWSCell, /* 31 -- get cell name for workstation */
187 PMariner, /* 32 - set/get mariner host */
188 PGetUserCell, /* 33 -- get cell name for user */
189 PVenusLogging, /* 34 -- Enable/Disable logging */
190 PGetCellStatus, /* 35 */
191 PSetCellStatus, /* 36 */
192 PFlushVolumeData, /* 37 -- flush all data from a volume */
193 PSetSysName, /* 38 - Set system name */
194 PExportAfs, /* 39 - Export Afs to remote nfs clients */
195 PGetCacheSize, /* 40 - get cache size and usage */
196 PGetVnodeXStatus, /* 41 - get vcache's special status */
197 PSetSPrefs33, /* 42 - Set CM Server preferences... */
198 PGetSPrefs, /* 43 - Get CM Server preferences... */
199 PGag, /* 44 - turn off/on all CM messages */
200 PTwiddleRx, /* 45 - adjust some RX params */
201 PSetSPrefs, /* 46 - Set CM Server preferences... */
202 PStoreBehind, /* 47 - set degree of store behind to be done */
203 PGCPAGs, /* 48 - disable automatic pag gc-ing */
204 PGetInitParams, /* 49 - get initial cm params */
205 PGetCPrefs, /* 50 - get client interface addresses */
206 PSetCPrefs, /* 51 - set client interface addresses */
207 PFlushMount, /* 52 - flush mount symlink data */
208 PRxStatProc, /* 53 - control process RX statistics */
209 PRxStatPeer, /* 54 - control peer RX statistics */
210 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
211 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
212 PBogus, /* 57 -- arla: set file prio */
213 PBogus, /* 58 -- arla: fallback getfh */
214 PBogus, /* 59 -- arla: fallback fhopen */
215 PBogus, /* 60 -- arla: controls xfsdebug */
216 PBogus, /* 61 -- arla: controls arla debug */
217 PBogus, /* 62 -- arla: debug interface */
218 PBogus, /* 63 -- arla: print xfs status */
219 PBogus, /* 64 -- arla: force cache check */
220 PBogus, /* 65 -- arla: break callback */
221 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
222 PFsCmd, /* 67 -- RXOSD: generic commnd interface */
223 PBogus, /* 68 -- arla: fetch stats */
224 PGetVnodeXStatus2, /* 69 - get caller access and some vcache status */
227 static pioctlFunction CpioctlSw[] = {
229 PNewAlias, /* 1 -- create new cell alias */
230 PListAliases, /* 2 -- list cell aliases */
231 PCallBackAddr, /* 3 -- request addr for callback rxcon */
233 PDiscon, /* 5 -- get/set discon mode */
243 static int (*(OpioctlSw[])) () = {
245 PNFSNukeCreds, /* 1 -- nuke all creds for NFS client */
246 #if defined(AFS_CACHE_BYPASS)
247 PSetCachingThreshold /* 2 -- get/set cache-bypass size threshold */
249 PNoop /* 2 -- get/set cache-bypass size threshold */
253 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
254 int afs_nobody = NFS_NOBODY;
257 HandleIoctl(register struct vcache *avc, register afs_int32 acom,
258 struct afs_ioctl *adata)
260 register afs_int32 code;
263 AFS_STATCNT(HandleIoctl);
265 switch (acom & 0xff) {
267 avc->states |= CSafeStore;
271 /* case 2 used to be abort store, but this is no longer provided,
272 * since it is impossible to implement under normal Unix.
276 /* return the name of the cell this file is open on */
277 register struct cell *tcell;
278 register afs_int32 i;
280 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
282 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
284 if (i > adata->out_size) {
285 /* 0 means we're not interested in the output */
286 if (adata->out_size != 0)
290 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
292 afs_PutCell(tcell, READ_LOCK);
298 case 49: /* VIOC_GETINITPARAMS */
299 if (adata->out_size < sizeof(struct cm_initparams)) {
302 AFS_COPYOUT(&cm_initParams, adata->out,
303 sizeof(struct cm_initparams), code);
315 return code; /* so far, none implemented */
320 /* For aix we don't temporarily bypass ioctl(2) but rather do our
321 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
322 * is now called from afs_gn_ioctl.
325 afs_ioctl(struct vcache *tvc, int cmd, int arg)
327 struct afs_ioctl data;
330 AFS_STATCNT(afs_ioctl);
331 if (((cmd >> 8) & 0xff) == 'V') {
332 /* This is a VICEIOCTL call */
333 AFS_COPYIN(arg, (caddr_t) & data, sizeof(data), error);
336 error = HandleIoctl(tvc, cmd, &data);
339 /* No-op call; just return. */
343 #endif /* AFS_AIX_ENV */
345 #if defined(AFS_SGI_ENV)
346 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void *arg, int flag, cred_t * cr,
349 , struct vopbd * vbds
353 struct afs_ioctl data;
359 AFS_STATCNT(afs_ioctl);
360 if (((cmd >> 8) & 0xff) == 'V') {
361 /* This is a VICEIOCTL call */
362 error = copyin_afs_ioctl(arg, &data);
365 locked = ISAFS_GLOCK();
368 error = HandleIoctl(tvc, cmd, &data);
373 /* No-op call; just return. */
377 #endif /* AFS_SGI_ENV */
379 /* unlike most calls here, this one uses u.u_error to return error conditions,
380 since this is really an intercepted chapter 2 call, rather than a vnode
383 /* AFS_HPUX102 and up uses VNODE ioctl instead */
384 #if !defined(AFS_HPUX102_ENV) && !defined(AFS_DARWIN80_ENV)
385 #if !defined(AFS_SGI_ENV)
390 kioctl(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
392 #else /* __64BIT__ */
394 kioctl32(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
396 #endif /* __64BIT__ */
399 kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
408 } u_uap, *uap = &u_uap;
410 #if defined(AFS_SUN5_ENV)
412 struct afs_ioctl_sys {
419 afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
421 #elif defined(AFS_OSF_ENV)
423 afs_xioctl(struct proc *p, void *args, long *retval)
429 } *uap = (struct a *)args;
430 #elif defined(AFS_FBSD50_ENV)
433 afs_xioctl(struct thread *td, register struct ioctl_args *uap,
436 struct proc *p = td->td_proc;
437 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
445 afs_xioctl(struct proc *p, register struct ioctl_args *uap, register_t *retval)
447 #elif defined(AFS_LINUX22_ENV)
448 struct afs_ioctl_sys {
453 afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
456 struct afs_ioctl_sys ua, *uap = &ua;
465 } *uap = (struct a *)u.u_ap;
466 #endif /* AFS_SUN5_ENV */
468 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
470 #elif !defined(AFS_LINUX22_ENV)
471 register struct file *fd;
473 #if defined(AFS_XBSD_ENV)
474 register struct filedesc *fdp;
476 register struct vcache *tvc;
477 register int ioctlDone = 0, code = 0;
479 AFS_STATCNT(afs_xioctl);
480 #if defined(AFS_DARWIN_ENV)
481 if ((code = fdgetf(p, uap->fd, &fd)))
483 #elif defined(AFS_XBSD_ENV)
485 if ((u_int) uap->fd >= fdp->fd_nfiles
486 || (fd = fdp->fd_ofiles[uap->fd]) == NULL)
488 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
490 #elif defined(AFS_LINUX22_ENV)
493 #elif defined(AFS_AIX32_ENV)
501 if (setuerror(getf(uap->fd, &fd))) {
504 #elif defined(AFS_OSF_ENV)
506 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
508 #elif defined(AFS_SUN5_ENV)
509 # if defined(AFS_SUN57_ENV)
513 # elif defined(AFS_SUN54_ENV)
518 if (code = getf(uap->fd, &fd)) {
521 # endif /* AFS_SUN57_ENV */
527 /* first determine whether this is any sort of vnode */
528 #if defined(AFS_LINUX22_ENV)
533 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
535 if (fd->f_type == DTYPE_VNODE) {
537 /* good, this is a vnode; next see if it is an AFS vnode */
538 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
539 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
540 #elif defined(AFS_OBSD_ENV)
542 IsAfsVnode((struct vnode *)fd->
543 f_data) ? VTOAFS((struct vnode *)fd->f_data) : NULL;
545 tvc = VTOAFS((struct vnode *)fd->f_data); /* valid, given a vnode */
547 #endif /* AFS_LINUX22_ENV */
548 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
549 /* This is an AFS vnode */
550 if (((uap->com >> 8) & 0xff) == 'V') {
551 register struct afs_ioctl *datap;
554 (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
555 code=copyin_afs_ioctl((char *)uap->arg, datap);
557 osi_FreeSmallSpace(datap);
559 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
562 #if defined(AFS_SUN5_ENV)
577 #else /* AFS_OSF_ENV */
581 #ifdef AFS_LINUX22_ENV
591 code = HandleIoctl(tvc, uap->com, datap);
592 osi_FreeSmallSpace(datap);
606 #if defined(AFS_LINUX22_ENV)
618 code = okioctl(fdes, com, arg, ext, arg2, arg3);
619 #else /* __64BIT__ */
620 code = okioctl32(fdes, com, arg, ext, arg2, arg3);
621 #endif /* __64BIT__ */
622 #else /* !AFS_AIX51_ENV */
623 code = okioctl(fdes, com, arg, ext);
624 #endif /* AFS_AIX51_ENV */
626 #else /* !AFS_AIX41_ENV */
628 okioctl(fdes, com, arg, ext);
629 #elif defined(AFS_SUN5_ENV)
630 #if defined(AFS_SUN57_ENV)
632 #elif defined(AFS_SUN54_ENV)
637 code = ioctl(uap, rvp);
638 #elif defined(AFS_FBSD50_ENV)
639 return ioctl(td, uap);
640 #elif defined(AFS_FBSD_ENV)
641 return ioctl(p, uap);
642 #elif defined(AFS_OBSD_ENV)
643 code = sys_ioctl(p, uap, retval);
644 #elif defined(AFS_DARWIN_ENV)
645 return ioctl(p, uap, retval);
646 #elif defined(AFS_OSF_ENV)
647 code = ioctl(p, args, retval);
654 #elif !defined(AFS_LINUX22_ENV)
668 #ifdef AFS_LINUX22_ENV
671 #if defined(KERNEL_HAVE_UERROR)
674 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
675 return (getuerror()? -1 : u.u_ioctlrv);
677 return getuerror()? -1 : 0;
680 #endif /* AFS_LINUX22_ENV */
681 #endif /* AFS_SUN5_ENV */
682 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
686 #endif /* AFS_SGI_ENV */
687 #endif /* AFS_HPUX102_ENV */
689 #if defined(AFS_SGI_ENV)
690 /* "pioctl" system call entry point; just pass argument to the parameterized
699 afs_pioctl(struct pioctlargs *uap, rval_t * rvp)
703 AFS_STATCNT(afs_pioctl);
705 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
714 #elif defined(AFS_OSF_ENV)
715 afs_pioctl(struct proc *p, void *args, int *retval)
722 } *uap = (struct a *)args;
724 AFS_STATCNT(afs_pioctl);
725 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
728 #elif defined(AFS_FBSD50_ENV)
730 afs_pioctl(struct thread *td, void *args, int *retval)
737 } *uap = (struct a *)args;
739 AFS_STATCNT(afs_pioctl);
740 return (afs_syscall_pioctl
741 (uap->path, uap->cmd, uap->cmarg, uap->follow, td->td_ucred));
744 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
746 afs_pioctl(struct proc *p, void *args, int *retval)
753 } *uap = (struct a *)args;
755 AFS_STATCNT(afs_pioctl);
756 #ifdef AFS_DARWIN80_ENV
757 return (afs_syscall_pioctl
758 (uap->path, uap->cmd, uap->cmarg, uap->follow,
761 return (afs_syscall_pioctl
762 (uap->path, uap->cmd, uap->cmarg, uap->follow,
763 p->p_cred->pc_ucred));
769 /* macro to avoid adding any more #ifdef's to pioctl code. */
770 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
771 #define PIOCTL_FREE_CRED() crfree(credp)
773 #define PIOCTL_FREE_CRED()
778 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
779 rval_t *vvp, struct AFS_UCRED *credp)
781 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
782 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
783 struct AFS_UCRED *credp)
785 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
789 struct afs_ioctl data;
790 #ifdef AFS_NEED_CLIENTCONTEXT
791 struct AFS_UCRED *tmpcred = NULL;
793 struct AFS_UCRED *foreigncreds = NULL;
794 register afs_int32 code = 0;
795 struct vnode *vp = NULL;
797 struct ucred *credp = crref(); /* don't free until done! */
799 #ifdef AFS_LINUX22_ENV
800 cred_t *credp = crref(); /* don't free until done! */
804 AFS_STATCNT(afs_syscall_pioctl);
806 follow = 1; /* compat. with old venus */
807 code = copyin_afs_ioctl(cmarg, &data);
810 #if defined(KERNEL_HAVE_UERROR)
815 if ((com & 0xff) == PSetClientContext) {
816 #ifdef AFS_NEED_CLIENTCONTEXT
817 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
818 code = HandleClientContext(&data, &com, &foreigncreds, credp);
820 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
824 crfree(foreigncreds);
827 #if defined(KERNEL_HAVE_UERROR)
828 return (setuerror(code), code);
833 #else /* AFS_NEED_CLIENTCONTEXT */
835 #endif /* AFS_NEED_CLIENTCONTEXT */
837 #ifdef AFS_NEED_CLIENTCONTEXT
840 * We could have done without temporary setting the u.u_cred below
841 * (foreigncreds could be passed as param the pioctl modules)
842 * but calls such as afs_osi_suser() doesn't allow that since it
843 * references u.u_cred directly. We could, of course, do something
844 * like afs_osi_suser(cred) which, I think, is better since it
845 * generalizes and supports multi cred environments...
847 #if defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
849 credp = foreigncreds;
850 #elif defined(AFS_AIX41_ENV)
851 tmpcred = crref(); /* XXX */
853 #elif defined(AFS_HPUX101_ENV)
854 tmpcred = p_cred(u.u_procp);
855 set_p_cred(u.u_procp, foreigncreds);
856 #elif defined(AFS_SGI_ENV)
857 tmpcred = OSI_GET_CURRENT_CRED();
858 OSI_SET_CURRENT_CRED(foreigncreds);
861 u.u_cred = foreigncreds;
864 #endif /* AFS_NEED_CLIENTCONTEXT */
865 if ((com & 0xff) == 15) {
866 /* special case prefetch so entire pathname eval occurs in helper process.
867 * otherwise, the pioctl call is essentially useless */
868 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
870 Prefetch(path, &data, follow,
871 foreigncreds ? foreigncreds : credp);
873 code = Prefetch(path, &data, follow, osi_curcred());
876 #if defined(KERNEL_HAVE_UERROR)
885 lookupname(path, USR, follow, NULL, &vp,
886 foreigncreds ? foreigncreds : credp);
888 #ifdef AFS_LINUX22_ENV
889 code = gop_lookupname(path, AFS_UIOUSER, follow, &dp);
891 vp = (struct vnode *)dp->d_inode;
893 code = gop_lookupname(path, AFS_UIOUSER, follow, &vp);
894 #endif /* AFS_LINUX22_ENV */
895 #endif /* AFS_AIX41_ENV */
899 #if defined(KERNEL_HAVE_UERROR)
907 #if defined(AFS_SUN510_ENV)
908 if (vp && !IsAfsVnode(vp)) {
909 struct vnode *realvp;
911 #ifdef AFS_SUN511_ENV
912 (VOP_REALVP(vp, &realvp, NULL) == 0)
914 (VOP_REALVP(vp, &realvp) == 0)
917 struct vnode *oldvp = vp;
925 /* now make the call if we were passed no file, or were passed an AFS file */
926 if (!vp || IsAfsVnode(vp)) {
927 #if defined(AFS_SUN5_ENV)
928 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
929 #elif defined(AFS_AIX41_ENV)
931 struct ucred *cred1, *cred2;
934 cred1 = cred2 = foreigncreds;
936 cred1 = cred2 = credp;
938 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
939 if (cred1 != cred2) {
940 /* something changed the creds */
944 #elif defined(AFS_HPUX101_ENV)
946 struct ucred *cred = p_cred(u.u_procp);
947 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
949 #elif defined(AFS_SGI_ENV)
952 credp = OSI_GET_CURRENT_CRED();
953 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
955 #elif defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
956 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
958 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
961 #if defined(KERNEL_HAVE_UERROR)
964 code = EINVAL; /* not in /afs */
969 #if defined(AFS_NEED_CLIENTCONTEXT)
972 crset(tmpcred); /* restore original credentials */
974 #if defined(AFS_HPUX101_ENV)
975 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
976 #elif defined(AFS_SGI_ENV)
977 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
978 #elif defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
979 credp = tmpcred; /* restore original credentials */
981 osi_curcred() = tmpcred; /* restore original credentials */
982 #endif /* AFS_HPUX101_ENV */
983 crfree(foreigncreds);
986 #endif /* AFS_NEED_CLIENTCONTEXT */
988 #ifdef AFS_LINUX22_ENV
991 AFS_RELE(vp); /* put vnode back */
995 #if defined(KERNEL_HAVE_UERROR)
998 return (getuerror());
1004 #define MAXPIOCTLTOKENLEN \
1005 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
1008 afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
1009 register struct afs_ioctl *ablob, int afollow,
1010 struct AFS_UCRED **acred)
1013 struct vrequest treq;
1014 register afs_int32 code;
1015 register afs_int32 function, device;
1016 afs_int32 inSize, outSize, outSizeMax;
1017 char *inData, *outData;
1018 pioctlFunction *pioctlSw;
1020 struct afs_fakestat_state fakestate;
1022 avc = avp ? VTOAFS(avp) : NULL;
1023 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1024 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1025 AFS_STATCNT(HandlePioctl);
1026 if ((code = afs_InitReq(&treq, *acred)))
1028 afs_InitFakeStat(&fakestate);
1030 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1032 afs_PutFakeStat(&fakestate);
1036 device = (acom & 0xff00) >> 8;
1038 case 'V': /* Original pioctls */
1039 pioctlSw = VpioctlSw;
1040 pioctlSwSize = sizeof(VpioctlSw);
1042 case 'C': /* Coordinated/common pioctls */
1043 pioctlSw = CpioctlSw;
1044 pioctlSwSize = sizeof(CpioctlSw);
1046 case 'O': /* Coordinated/common pioctls */
1047 pioctlSw = OpioctlSw;
1048 pioctlSwSize = sizeof(OpioctlSw);
1051 afs_PutFakeStat(&fakestate);
1054 function = acom & 0xff;
1055 if (function >= (pioctlSwSize / sizeof(char *))) {
1056 afs_PutFakeStat(&fakestate);
1057 return EINVAL; /* out of range */
1059 inSize = ablob->in_size;
1061 /* Do all range checking before continuing */
1062 if (inSize > MAXPIOCTLTOKENLEN || inSize < 0 || ablob->out_size < 0)
1065 /* Note that we use osi_Alloc for large allocs and osi_AllocLargeSpace for small ones */
1066 if (inSize > AFS_LRALLOCSIZ) {
1067 inData = osi_Alloc(inSize + 1);
1069 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1074 AFS_COPYIN(ablob->in, inData, inSize, code);
1075 inData[inSize] = '\0';
1079 if (inSize > AFS_LRALLOCSIZ) {
1080 osi_Free(inData, inSize + 1);
1082 osi_FreeLargeSpace(inData);
1084 afs_PutFakeStat(&fakestate);
1087 if (function == 8 && device == 'V') { /* PGetTokens */
1088 outSizeMax = MAXPIOCTLTOKENLEN;
1089 outData = osi_Alloc(outSizeMax);
1091 outSizeMax = AFS_LRALLOCSIZ;
1092 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1095 if (inSize > AFS_LRALLOCSIZ) {
1096 osi_Free(inData, inSize + 1);
1098 osi_FreeLargeSpace(inData);
1100 afs_PutFakeStat(&fakestate);
1105 (*pioctlSw[function]) (avc, function, &treq, inData, outData, inSize,
1107 if (inSize > AFS_LRALLOCSIZ) {
1108 osi_Free(inData, inSize + 1);
1110 osi_FreeLargeSpace(inData);
1112 if (code == 0 && ablob->out_size > 0) {
1113 if (outSize > ablob->out_size) {
1114 code = E2BIG; /* data wont fit in user buffer */
1115 } else if (outSize) {
1116 AFS_COPYOUT(outData, ablob->out, outSize, code);
1119 if (outSizeMax > AFS_LRALLOCSIZ) {
1120 osi_Free(outData, outSizeMax);
1122 osi_FreeLargeSpace(outData);
1124 afs_PutFakeStat(&fakestate);
1125 return afs_CheckCode(code, &treq, 41);
1129 * VIOCGETFID (22) - Get file ID quickly
1133 * \param[in] ain not in use
1134 * \param[out] aout fid of requested file
1136 * \retval EINVAL Error if some of the initial arguments aren't set
1138 * \post get the file id of some file
1140 DECL_PIOCTL(PGetFID)
1142 AFS_STATCNT(PGetFID);
1145 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1146 *aoutSize = sizeof(struct VenusFid);
1151 * VIOCSETAL (1) - Set access control list
1155 * \param[in] ain the ACL being set
1156 * \param[out] aout the ACL being set returned
1158 * \retval EINVAL Error if some of the standard args aren't set
1160 * \post Changed ACL, via direct writing to the wire
1162 int dummy_PSetAcl(char *ain, char *aout)
1167 DECL_PIOCTL(PSetAcl)
1169 register afs_int32 code;
1171 struct AFSOpaque acl;
1172 struct AFSVolSync tsync;
1173 struct AFSFetchStatus OutStatus;
1176 AFS_STATCNT(PSetAcl);
1179 if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1024 /* AFSOPAQUEMAX */)
1182 acl.AFSOpaque_val = ain;
1184 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1186 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1189 RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
1190 &acl, &OutStatus, &tsync);
1195 } while (afs_Analyze
1196 (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
1197 SHARED_LOCK, NULL));
1199 /* now we've forgotten all of the access info */
1200 ObtainWriteLock(&afs_xcbhash, 455);
1202 afs_DequeueCallback(avc);
1203 avc->states &= ~(CStatd | CUnique);
1204 ReleaseWriteLock(&afs_xcbhash);
1205 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1206 osi_dnlc_purgedp(avc);
1210 int afs_defaultAsynchrony = 0;
1213 * VIOC_STOREBEHIND (47) Adjust store asynchrony
1217 * \param[in] ain sbstruct (store behind structure) input
1218 * \param[out] aout resulting sbstruct
1220 * \retval EPERM Error if the user doesn't have super-user credentials
1221 * \retval EACCES Error if there isn't enough access to not check the mode bits
1223 * \post sets asynchrony based on a file, from a struct sbstruct "I THINK"
1225 DECL_PIOCTL(PStoreBehind)
1228 struct sbstruct *sbr;
1230 sbr = (struct sbstruct *)ain;
1231 if (sbr->sb_default != -1) {
1232 if (afs_osi_suser(*acred))
1233 afs_defaultAsynchrony = sbr->sb_default;
1238 if (avc && (sbr->sb_thisfile != -1)) {
1240 (avc, PRSFS_WRITE | PRSFS_ADMINISTER, areq, DONT_CHECK_MODE_BITS))
1241 avc->asynchrony = sbr->sb_thisfile;
1246 *aoutSize = sizeof(struct sbstruct);
1247 sbr = (struct sbstruct *)aout;
1248 sbr->sb_default = afs_defaultAsynchrony;
1250 sbr->sb_thisfile = avc->asynchrony;
1257 * VIOC_GCPAGS (48) - Disable automatic PAG gc'ing
1261 * \param[in] ain not in use
1262 * \param[out] aout not in use
1264 * \retval EACCES Error if the user doesn't have super-user credentials
1266 * \post set the gcpags to GCPAGS_USERDISABLED
1268 DECL_PIOCTL(PGCPAGs)
1270 if (!afs_osi_suser(*acred)) {
1273 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1278 * VIOCGETAL (2) - Get access control list
1282 * \param[in] ain not in use
1283 * \param[out] aout the ACL
1285 * \retval EINVAL Error if some of the standard args aren't set
1286 * \retval ERANGE Error if the vnode of the file id is too large
1287 * \retval -1 Error if getting the ACL failed
1289 * \post Obtain the ACL, based on file ID
1291 * \notes there is a hack to tell which type of ACL is being returned, checks the top 2-bytes to judge what type of ACL it is, only for dfs xlat or ACLs
1293 DECL_PIOCTL(PGetAcl)
1295 struct AFSOpaque acl;
1296 struct AFSVolSync tsync;
1297 struct AFSFetchStatus OutStatus;
1303 AFS_STATCNT(PGetAcl);
1306 Fid.Volume = avc->fid.Fid.Volume;
1307 Fid.Vnode = avc->fid.Fid.Vnode;
1308 Fid.Unique = avc->fid.Fid.Unique;
1309 if (avc->states & CForeign) {
1311 * For a dfs xlator acl we have a special hack so that the
1312 * xlator will distinguish which type of acl will return. So
1313 * we currently use the top 2-bytes (vals 0-4) to tell which
1314 * type of acl to bring back. Horrible hack but this will
1315 * cause the least number of changes to code size and interfaces.
1317 if (Fid.Vnode & 0xc0000000)
1319 Fid.Vnode |= (ainSize << 30);
1321 acl.AFSOpaque_val = aout;
1323 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1326 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1328 code = RXAFS_FetchACL(tconn->id, &Fid, &acl, &OutStatus, &tsync);
1333 } while (afs_Analyze
1334 (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHACL,
1335 SHARED_LOCK, NULL));
1338 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1344 * PNoop returns success. Used for functions which are not implemented or are no longer in use.
1348 * \notes Functions involved in this: 17 (VIOCENGROUP) -- used to be enable group; 18 (VIOCDISGROUP) -- used to be disable group; 2 (?) -- get/set cache-bypass size threshold
1357 * PBogus returns fail. Used for functions which are not implemented or are no longer in use.
1361 * \retval EINVAL Error if some of the standard args aren't set
1363 * \notes Functions involved in this: 0 (?); 4 (?); 6 (?); 7 (VIOCSTAT); 8 (?); 13 (VIOCGETTIME) -- used to be quick check time; 15 (VIOCPREFETCH) -- prefetch is now special-cased; see pioctl code!; 16 (VIOCNOP) -- used to be testing code; 19 (VIOCLISTGROUPS) -- used to be list group; 23 (VIOCWAITFOREVER) -- used to be waitforever; 57 (VIOC_FPRIOSTATUS) -- arla: set file prio; 58 (VIOC_FHGET) -- arla: fallback getfh; 59 (VIOC_FHOPEN) -- arla: fallback fhopen; 60 (VIOC_XFSDEBUG) -- arla: controls xfsdebug; 61 (VIOC_ARLADEBUG) -- arla: controls arla debug; 62 (VIOC_AVIATOR) -- arla: debug interface; 63 (VIOC_XFSDEBUG_PRINT) -- arla: print xfs status; 64 (VIOC_CALCULATE_CACHE) -- arla: force cache check; 65 (VIOC_BREAKCELLBACK) -- arla: break callback; 68 (?) -- arla: fetch stats;
1367 AFS_STATCNT(PBogus);
1372 * VIOC_FILE_CELL_NAME (30) - Get cell in which file lives
1376 * \param[in] ain not in use (avc used to pass in file id)
1377 * \param[out] aout cell name
1379 * \retval EINVAL Error if some of the standard args aren't set
1380 * \retval ESRCH Error if the file isn't part of a cell
1382 * \post Get a cell based on a passed in file id
1384 DECL_PIOCTL(PGetFileCell)
1386 register struct cell *tcell;
1388 AFS_STATCNT(PGetFileCell);
1391 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1394 strcpy(aout, tcell->cellName);
1395 afs_PutCell(tcell, READ_LOCK);
1396 *aoutSize = strlen(aout) + 1;
1401 * VIOC_GET_WS_CELL (31) - Get cell in which workstation lives
1405 * \param[in] ain not in use
1406 * \param[out] aout cell name
1408 * \retval EIO Error if the afs daemon hasn't started yet
1409 * \retval ESRCH Error if the machine isn't part of a cell, for whatever reason
1411 * \post Get the primary cell that the machine is a part of.
1413 DECL_PIOCTL(PGetWSCell)
1415 struct cell *tcell = NULL;
1417 AFS_STATCNT(PGetWSCell);
1418 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1419 return EIO; /* Inappropriate ioctl for device */
1421 tcell = afs_GetPrimaryCell(READ_LOCK);
1422 if (!tcell) /* no primary cell? */
1424 strcpy(aout, tcell->cellName);
1425 *aoutSize = strlen(aout) + 1;
1426 afs_PutCell(tcell, READ_LOCK);
1431 * VIOC_GET_PRIMARY_CELL (33) - Get primary cell for caller
1435 * \param[in] ain not in use (user id found via areq)
1436 * \param[out] aout cell name
1438 * \retval ESRCH Error if the user id doesn't have a primary cell specified
1440 * \post Get the primary cell for a certain user, based on the user's uid
1442 DECL_PIOCTL(PGetUserCell)
1444 register afs_int32 i;
1445 register struct unixuser *tu;
1446 register struct cell *tcell;
1448 AFS_STATCNT(PGetUserCell);
1449 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1450 return EIO; /* Inappropriate ioctl for device */
1452 /* return the cell name of the primary cell for this user */
1453 i = UHash(areq->uid);
1454 ObtainWriteLock(&afs_xuser, 224);
1455 for (tu = afs_users[i]; tu; tu = tu->next) {
1456 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1458 ReleaseWriteLock(&afs_xuser);
1463 tcell = afs_GetCell(tu->cell, READ_LOCK);
1464 afs_PutUser(tu, WRITE_LOCK);
1468 strcpy(aout, tcell->cellName);
1469 afs_PutCell(tcell, READ_LOCK);
1470 *aoutSize = strlen(aout) + 1; /* 1 for the null */
1473 ReleaseWriteLock(&afs_xuser);
1481 * VIOCSETTOK (3) - Set authentication tokens
1485 * \param[in] ain the krb tickets from which to set the afs tokens
1486 * \param[out] aout not in use
1488 * \retval EINVAL Error if the ticket is either too long or too short
1489 * \retval EIO Error if the AFS initState is below 101
1490 * \retval ESRCH Error if the cell for which the Token is being set can't be found
1492 * \post Set the Tokens for a specific cell name, unless there is none set, then default to primary
1495 DECL_PIOCTL(PSetTokens)
1498 register struct unixuser *tu;
1499 struct ClearToken clear;
1500 register struct cell *tcell;
1503 struct vrequest treq;
1504 afs_int32 flag, set_parent_pag = 0;
1506 AFS_STATCNT(PSetTokens);
1507 if (!afs_resourceinit_flag) {
1510 memcpy((char *)&i, ain, sizeof(afs_int32));
1511 ain += sizeof(afs_int32);
1512 stp = ain; /* remember where the ticket is */
1513 if (i < 0 || i > MAXKTCTICKETLEN)
1514 return EINVAL; /* malloc may fail */
1516 ain += i; /* skip over ticket */
1517 memcpy((char *)&i, ain, sizeof(afs_int32));
1518 ain += sizeof(afs_int32);
1519 if (i != sizeof(struct ClearToken)) {
1522 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1523 if (clear.AuthHandle == -1)
1524 clear.AuthHandle = 999; /* more rxvab compat stuff */
1525 ain += sizeof(struct ClearToken);
1526 if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1527 /* still stuff left? we've got primary flag and cell name. Set these */
1528 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1529 ain += sizeof(afs_int32); /* skip id field */
1530 /* rest is cell name, look it up */
1531 /* some versions of gcc appear to need != 0 in order to get this right */
1532 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1536 tcell = afs_GetCellByName(ain, READ_LOCK);
1540 /* default to primary cell, primary id */
1541 flag = 1; /* primary id */
1542 tcell = afs_GetPrimaryCell(READ_LOCK);
1547 afs_PutCell(tcell, READ_LOCK);
1548 if (set_parent_pag) {
1550 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1551 #if defined(AFS_DARWIN_ENV)
1552 struct proc *p = current_proc(); /* XXX */
1554 struct proc *p = curproc; /* XXX */
1556 #ifndef AFS_DARWIN80_ENV
1557 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1558 p->p_pid, p->p_comm);
1560 if (!setpag(p, acred, -1, &pag, 1)) {
1563 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1565 if (!setpag(acred, -1, &pag, 1)) {
1568 afs_InitReq(&treq, *acred);
1572 /* now we just set the tokens */
1573 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1574 tu->vid = clear.ViceId;
1575 if (tu->stp != NULL) {
1576 afs_osi_Free(tu->stp, tu->stLen);
1578 tu->stp = (char *)afs_osi_Alloc(stLen);
1579 if (tu->stp == NULL) {
1583 memcpy(tu->stp, stp, stLen);
1586 afs_stats_cmfullperf.authent.TicketUpdates++;
1587 afs_ComputePAGStats();
1588 #endif /* AFS_NOSTATS */
1589 tu->states |= UHasTokens;
1590 tu->states &= ~UTokensBad;
1591 afs_SetPrimary(tu, flag);
1592 tu->tokenTime = osi_Time();
1593 afs_ResetUserConns(tu);
1594 afs_PutUser(tu, WRITE_LOCK);
1610 * VIOCGETVOLSTAT (4) - Get volume status
1614 * \param[in] ain not in use
1615 * \param[out] aout status of the volume
1617 * \retval EINVAL Error if some of the standard args aren't set
1619 * \post The status of a volume (based on the FID of the volume), or an offline message /motd
1621 DECL_PIOCTL(PGetVolumeStatus)
1624 char *offLineMsg = afs_osi_Alloc(256);
1625 char *motd = afs_osi_Alloc(256);
1626 register struct conn *tc;
1627 register afs_int32 code = 0;
1628 struct AFSFetchVolumeStatus volstat;
1630 char *Name, *OfflineMsg, *MOTD;
1633 AFS_STATCNT(PGetVolumeStatus);
1639 OfflineMsg = offLineMsg;
1642 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1644 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1647 RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1648 &Name, &OfflineMsg, &MOTD);
1653 } while (afs_Analyze
1654 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1655 SHARED_LOCK, NULL));
1659 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1661 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1662 cp += sizeof(VolumeStatus);
1663 strcpy(cp, volName);
1664 cp += strlen(volName) + 1;
1665 strcpy(cp, offLineMsg);
1666 cp += strlen(offLineMsg) + 1;
1668 cp += strlen(motd) + 1;
1669 *aoutSize = (cp - aout);
1671 afs_osi_Free(offLineMsg, 256);
1672 afs_osi_Free(motd, 256);
1677 * VIOCSETVOLSTAT (5) - Set volume status
1681 * \param[in] ain values to set the status at, offline message, message of the day, volume name, minimum quota, maximum quota
1682 * \param[out] aout status of a volume, offlines messages, minimum quota, maximumm quota
1684 * \retval EINVAL Error if some of the standard args aren't set
1685 * \retval EROFS Error if the volume is read only, or a backup volume
1686 * \retval ENODEV Error if the volume can't be accessed
1687 * \retval E2BIG Error if the volume name, offline message, and motd are too big
1689 * \post Set the status of a volume, including any offline messages, a minimum quota, and a maximum quota
1691 DECL_PIOCTL(PSetVolumeStatus)
1694 char *offLineMsg = afs_osi_Alloc(256);
1695 char *motd = afs_osi_Alloc(256);
1696 register struct conn *tc;
1697 register afs_int32 code = 0;
1698 struct AFSFetchVolumeStatus volstat;
1699 struct AFSStoreVolumeStatus storeStat;
1700 register struct volume *tvp;
1704 AFS_STATCNT(PSetVolumeStatus);
1710 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1712 if (tvp->states & (VRO | VBackup)) {
1713 afs_PutVolume(tvp, READ_LOCK);
1717 afs_PutVolume(tvp, READ_LOCK);
1722 /* Copy the junk out, using cp as a roving pointer. */
1724 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1725 cp += sizeof(AFSFetchVolumeStatus);
1726 if (strlen(cp) >= sizeof(volName)) {
1730 strcpy(volName, cp);
1731 cp += strlen(volName) + 1;
1732 if (strlen(cp) >= sizeof(offLineMsg)) {
1736 strcpy(offLineMsg, cp);
1737 cp += strlen(offLineMsg) + 1;
1738 if (strlen(cp) >= sizeof(motd)) {
1744 if (volstat.MinQuota != -1) {
1745 storeStat.MinQuota = volstat.MinQuota;
1746 storeStat.Mask |= AFS_SETMINQUOTA;
1748 if (volstat.MaxQuota != -1) {
1749 storeStat.MaxQuota = volstat.MaxQuota;
1750 storeStat.Mask |= AFS_SETMAXQUOTA;
1753 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1755 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1758 RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume, &storeStat,
1759 volName, offLineMsg, motd);
1764 } while (afs_Analyze
1765 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1766 SHARED_LOCK, NULL));
1770 /* we are sending parms back to make compat. with prev system. should
1771 * change interface later to not ask for current status, just set new status */
1773 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1774 cp += sizeof(VolumeStatus);
1775 strcpy(cp, volName);
1776 cp += strlen(volName) + 1;
1777 strcpy(cp, offLineMsg);
1778 cp += strlen(offLineMsg) + 1;
1780 cp += strlen(motd) + 1;
1781 *aoutSize = cp - aout;
1783 afs_osi_Free(offLineMsg, 256);
1784 afs_osi_Free(motd, 256);
1789 * VIOCFLUSH (6) - Invalidate cache entry
1793 * \param[in] ain not in use
1794 * \param[out] aout not in use
1796 * \retval EINVAL Error if some of the standard args aren't set
1798 * \post Flush any information the cache manager has on an entry
1802 AFS_STATCNT(PFlush);
1805 #ifdef AFS_BOZONLOCK_ENV
1806 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1808 ObtainWriteLock(&avc->lock, 225);
1809 ObtainWriteLock(&afs_xcbhash, 456);
1810 afs_DequeueCallback(avc);
1811 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1812 ReleaseWriteLock(&afs_xcbhash);
1813 /* now find the disk cache entries */
1814 afs_TryToSmush(avc, *acred, 1);
1815 osi_dnlc_purgedp(avc);
1816 if (avc->linkData && !(avc->states & CCore)) {
1817 afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
1818 avc->linkData = NULL;
1820 ReleaseWriteLock(&avc->lock);
1821 #ifdef AFS_BOZONLOCK_ENV
1822 afs_BozonUnlock(&avc->pvnLock, avc);
1828 * VIOC_AFS_STAT_MT_PT (29) - Stat mount point
1832 * \param[in] ain the last component in a path, related to mountpoint that we're looking for information about
1833 * \param[out] aout volume, cell, link data
1835 * \retval EINVAL Error if some of the standard args aren't set
1836 * \retval ENOTDIR Error if the 'mount point' argument isn't a directory
1837 * \retval EIO Error if the link data can't be accessed
1839 * \post Get the volume, and cell, as well as the link data for a mount point
1841 DECL_PIOCTL(PNewStatMount)
1843 register afs_int32 code;
1844 register struct vcache *tvc;
1845 register struct dcache *tdc;
1846 struct VenusFid tfid;
1848 struct sysname_info sysState;
1849 afs_size_t offset, len;
1851 AFS_STATCNT(PNewStatMount);
1854 code = afs_VerifyVCache(avc, areq);
1857 if (vType(avc) != VDIR) {
1860 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1863 Check_AtSys(avc, ain, &sysState, areq);
1864 ObtainReadLock(&tdc->lock);
1866 code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
1867 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1868 ReleaseReadLock(&tdc->lock);
1869 afs_PutDCache(tdc); /* we're done with the data */
1870 bufp = sysState.name;
1874 tfid.Cell = avc->fid.Cell;
1875 tfid.Fid.Volume = avc->fid.Fid.Volume;
1876 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1877 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1879 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1885 if (tvc->mvstat != 1) {
1890 ObtainWriteLock(&tvc->lock, 226);
1891 code = afs_HandleLink(tvc, areq);
1893 if (tvc->linkData) {
1894 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1897 /* we have the data */
1898 strcpy(aout, tvc->linkData);
1899 *aoutSize = strlen(tvc->linkData) + 1;
1904 ReleaseWriteLock(&tvc->lock);
1907 if (sysState.allocked)
1908 osi_FreeLargeSpace(bufp);
1913 * VIOCGETTOK (8) - Get authentication tokens
1917 * \param[in] ain userid
1918 * \param[out] aout token
1920 * \retval EIO Error if the afs daemon hasn't started yet
1921 * \retval EDOM Error if the input parameter is out of the bounds of the available tokens
1922 * \retval ENOTCONN Error if there aren't tokens for this cell
1924 * \post If the input paramater exists, get the token that corresponds to the parameter value, if there is no token at this value, get the token for the first cell
1926 * \notes "it's a weird interface (from comments in the code)"
1929 DECL_PIOCTL(PGetTokens)
1931 register struct cell *tcell;
1932 register afs_int32 i;
1933 register struct unixuser *tu;
1938 AFS_STATCNT(PGetTokens);
1939 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1940 return EIO; /* Inappropriate ioctl for device */
1942 /* weird interface. If input parameter is present, it is an integer and
1943 * we're supposed to return the parm'th tokens for this unix uid.
1944 * If not present, we just return tokens for cell 1.
1945 * If counter out of bounds, return EDOM.
1946 * If no tokens for the particular cell, return ENOTCONN.
1947 * Also, if this mysterious parm is present, we return, along with the
1948 * tokens, the primary cell indicator (an afs_int32 0) and the cell name
1949 * at the end, in that order.
1951 if ((newStyle = (ainSize > 0))) {
1952 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1954 i = UHash(areq->uid);
1955 ObtainReadLock(&afs_xuser);
1956 for (tu = afs_users[i]; tu; tu = tu->next) {
1958 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1959 if (iterator-- == 0)
1960 break; /* are we done yet? */
1963 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell))
1969 * No need to hold a read lock on each user entry
1973 ReleaseReadLock(&afs_xuser);
1978 if (((tu->states & UHasTokens) == 0)
1979 || (tu->ct.EndTimestamp < osi_Time())) {
1980 tu->states |= (UTokensBad | UNeedsReset);
1981 afs_PutUser(tu, READ_LOCK);
1984 /* use iterator for temp */
1986 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1988 iterator = 56; /* # of bytes we're returning */
1989 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1990 cp += sizeof(afs_int32);
1991 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1993 iterator = sizeof(struct ClearToken);
1994 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1995 cp += sizeof(afs_int32);
1996 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1997 cp += sizeof(struct ClearToken);
1999 /* put out primary id and cell name, too */
2000 iterator = (tu->states & UPrimary ? 1 : 0);
2001 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
2002 cp += sizeof(afs_int32);
2003 tcell = afs_GetCell(tu->cell, READ_LOCK);
2005 strcpy(cp, tcell->cellName);
2006 cp += strlen(tcell->cellName) + 1;
2007 afs_PutCell(tcell, READ_LOCK);
2011 *aoutSize = cp - aout;
2012 afs_PutUser(tu, READ_LOCK);
2017 * VIOCUNLOG (9) - Invalidate tokens
2021 * \param[in] ain not in use
2022 * \param[out] aout not in use
2024 * \retval EIO Error if the afs daemon hasn't been started yet
2026 * \post remove tokens from a user, specified by the user id
2028 * \notes sets the token's time to 0, which then causes it to be removed
2029 * \notes Unlog is the same as un-pag in OpenAFS
2033 register afs_int32 i;
2034 register struct unixuser *tu;
2036 AFS_STATCNT(PUnlog);
2037 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2038 return EIO; /* Inappropriate ioctl for device */
2040 i = UHash(areq->uid);
2041 ObtainWriteLock(&afs_xuser, 227);
2042 for (tu = afs_users[i]; tu; tu = tu->next) {
2043 if (tu->uid == areq->uid) {
2045 tu->states &= ~UHasTokens;
2046 /* security is not having to say you're sorry */
2047 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
2049 ReleaseWriteLock(&afs_xuser);
2050 /* We have to drop the lock over the call to afs_ResetUserConns, since
2051 * it obtains the afs_xvcache lock. We could also keep the lock, and
2052 * modify ResetUserConns to take parm saying we obtained the lock
2053 * already, but that is overkill. By keeping the "tu" pointer
2054 * held over the released lock, we guarantee that we won't lose our
2055 * place, and that we'll pass over every user conn that existed when
2056 * we began this call.
2058 afs_ResetUserConns(tu);
2060 ObtainWriteLock(&afs_xuser, 228);
2062 /* set the expire times to 0, causes
2063 * afs_GCUserData to remove this entry
2065 tu->ct.EndTimestamp = 0;
2067 #endif /* UKERNEL */
2070 ReleaseWriteLock(&afs_xuser);
2075 * VIOC_AFS_MARINER_HOST (32) - Get/set mariner (cache manager monitor) host
2079 * \param[in] ain host address to be set
2080 * \param[out] aout old host address
2082 * \post depending on whether or not a variable is set, either get the host for the cache manager monitor, or set the old address and give it a new address
2084 * \notes Errors turn off mariner
2086 DECL_PIOCTL(PMariner)
2088 afs_int32 newHostAddr;
2089 afs_int32 oldHostAddr;
2091 AFS_STATCNT(PMariner);
2093 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost,
2096 oldHostAddr = 0xffffffff; /* disabled */
2098 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
2099 if (newHostAddr == 0xffffffff) {
2100 /* disable mariner operations */
2102 } else if (newHostAddr) {
2104 afs_marinerHost = newHostAddr;
2106 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
2107 *aoutSize = sizeof(afs_int32);
2112 * VIOCCKSERV (10) - Check that servers are up
2116 * \param[in] ain name of the cell
2117 * \param[out] aout current down server list
2119 * \retval EIO Error if the afs daemon hasn't started yet
2120 * \retval EACCES Error if the user doesn't have super-user credentials
2121 * \retval ENOENT Error if we are unable to obtain the cell
2123 * \post Either a fast check (where it doesn't contact servers) or a local check (checks local cell only)
2125 DECL_PIOCTL(PCheckServers)
2127 register char *cp = 0;
2129 register struct server *ts;
2130 afs_int32 temp, *lp = (afs_int32 *) ain, havecell = 0;
2132 struct chservinfo *pcheck;
2134 AFS_STATCNT(PCheckServers);
2136 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2137 return EIO; /* Inappropriate ioctl for device */
2139 if (*lp == 0x12345678) { /* For afs3.3 version */
2140 pcheck = (struct chservinfo *)ain;
2141 if (pcheck->tinterval >= 0) {
2143 memcpy(cp, (char *)&afs_probe_interval, sizeof(afs_int32));
2144 *aoutSize = sizeof(afs_int32);
2145 if (pcheck->tinterval > 0) {
2146 if (!afs_osi_suser(*acred))
2148 afs_probe_interval = pcheck->tinterval;
2154 temp = pcheck->tflags;
2155 cp = pcheck->tbuffer;
2156 } else { /* For pre afs3.3 versions */
2157 memcpy((char *)&temp, ain, sizeof(afs_int32));
2158 cp = ain + sizeof(afs_int32);
2159 if (ainSize > sizeof(afs_int32))
2164 * 1: fast check, don't contact servers.
2165 * 2: local cell only.
2168 /* have cell name, too */
2169 cellp = afs_GetCellByName(cp, READ_LOCK);
2174 if (!cellp && (temp & 2)) {
2175 /* use local cell */
2176 cellp = afs_GetPrimaryCell(READ_LOCK);
2178 if (!(temp & 1)) { /* if not fast, call server checker routine */
2179 afs_CheckServers(1, cellp); /* check down servers */
2180 afs_CheckServers(0, cellp); /* check up servers */
2182 /* now return the current down server list */
2184 ObtainReadLock(&afs_xserver);
2185 for (i = 0; i < NSERVERS; i++) {
2186 for (ts = afs_servers[i]; ts; ts = ts->next) {
2187 if (cellp && ts->cell != cellp)
2188 continue; /* cell spec'd and wrong */
2189 if ((ts->flags & SRVR_ISDOWN)
2190 && ts->addr->sa_portal != ts->cell->vlport) {
2191 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2192 cp += sizeof(afs_int32);
2196 ReleaseReadLock(&afs_xserver);
2198 afs_PutCell(cellp, READ_LOCK);
2199 *aoutSize = cp - aout;
2204 * VIOCCKBACK (11) - Check backup volume mappings
2208 * \param[in] ain not in use
2209 * \param[out] aout not in use
2211 * \retval EIO Error if the afs daemon hasn't started yet
2213 * \post Check the root volume, and then check the names if the volume check variable is set to force, has expired, is busy, or if the mount points variable is set
2215 DECL_PIOCTL(PCheckVolNames)
2217 AFS_STATCNT(PCheckVolNames);
2218 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2219 return EIO; /* Inappropriate ioctl for device */
2221 afs_CheckRootVolume();
2222 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE | AFS_VOLCHECK_EXPIRED |
2223 AFS_VOLCHECK_BUSY | AFS_VOLCHECK_MTPTS);
2228 * VIOCCKCONN (12) - Check connections for a user
2232 * \param[in] ain not in use
2233 * \param[out] aout not in use
2235 * \retval EACCESS Error if no user is specififed, the user has no tokens set, or if the user's tokens are bad
2237 * \post check to see if a user has the correct authentication. If so, allow access.
2239 * \notes Check the connections to all the servers specified
2241 DECL_PIOCTL(PCheckAuth)
2246 struct unixuser *tu;
2249 AFS_STATCNT(PCheckAuth);
2250 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2251 return EIO; /* Inappropriate ioctl for device */
2254 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2258 /* we have a user */
2259 ObtainReadLock(&afs_xsrvAddr);
2260 ObtainReadLock(&afs_xconn);
2262 /* any tokens set? */
2263 if ((tu->states & UHasTokens) == 0)
2265 /* all connections in cell 1 working? */
2266 for (i = 0; i < NSERVERS; i++) {
2267 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2268 for (tc = sa->conns; tc; tc = tc->next) {
2269 if (tc->user == tu && (tu->states & UTokensBad))
2274 ReleaseReadLock(&afs_xsrvAddr);
2275 ReleaseReadLock(&afs_xconn);
2276 afs_PutUser(tu, READ_LOCK);
2278 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
2279 *aoutSize = sizeof(afs_int32);
2284 Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
2285 struct AFS_UCRED *acred)
2288 register afs_int32 code;
2289 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2295 AFS_STATCNT(Prefetch);
2298 tp = osi_AllocLargeSpace(1024);
2299 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2301 osi_FreeLargeSpace(tp);
2304 if (afs_BBusy()) { /* do this as late as possible */
2305 osi_FreeLargeSpace(tp);
2306 return EWOULDBLOCK; /* pretty close */
2308 afs_BQueue(BOP_PATH, (struct vcache *)0, 0, 0, acred, (afs_size_t) 0,
2309 (afs_size_t) 0, tp);
2314 * VIOCWHEREIS (14) - Find out where a volume is located
2318 * \param[in] ain not in use
2319 * \param[out] aout volume location
2321 * \retval EINVAL Error if some of the default arguments don't exist
2322 * \retval ENODEV Error if there is no such volume
2324 * \post fine a volume, based on a volume file id
2326 * \notes check each of the servers specified
2328 DECL_PIOCTL(PFindVolume)
2330 register struct volume *tvp;
2331 register struct server *ts;
2332 register afs_int32 i;
2335 AFS_STATCNT(PFindVolume);
2338 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2341 for (i = 0; i < MAXHOSTS; i++) {
2342 ts = tvp->serverHost[i];
2345 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2346 cp += sizeof(afs_int32);
2349 /* still room for terminating NULL, add it on */
2350 ainSize = 0; /* reuse vbl */
2351 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2352 cp += sizeof(afs_int32);
2354 *aoutSize = cp - aout;
2355 afs_PutVolume(tvp, READ_LOCK);
2362 * VIOCACCESS (20) - Access using PRS_FS bits
2366 * \param[in] ain PRS_FS bits
2367 * \param[out] aout not in use
2369 * \retval EINVAL Error if some of the initial arguments aren't set
2370 * \retval EACCES Error if access is denied
2372 * \post check to make sure access is allowed
2374 DECL_PIOCTL(PViceAccess)
2376 register afs_int32 code;
2379 AFS_STATCNT(PViceAccess);
2382 code = afs_VerifyVCache(avc, areq);
2385 memcpy((char *)&temp, ain, sizeof(afs_int32));
2386 code = afs_AccessOK(avc, temp, areq, CHECK_MODE_BITS);
2393 DECL_PIOCTL(PPrecache)
2397 /*AFS_STATCNT(PPrecache);*/
2398 if (!afs_osi_suser(*acred))
2400 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2401 afs_preCache = newValue*1024;
2406 * VIOCSETCACHESIZE (24) - Set venus cache size in 1000 units
2410 * \param[in] ain the size the venus cache should be set to
2411 * \param[out] aout not in use
2413 * \retval EACCES Error if the user doesn't have super-user credentials
2414 * \retval EROFS Error if the cache is set to be in memory
2416 * \post Set the cache size based on user input. If no size is given, set it to the default OpenAFS cache size.
2418 * \notes recompute the general cache parameters for every single block allocated
2420 DECL_PIOCTL(PSetCacheSize)
2425 AFS_STATCNT(PSetCacheSize);
2426 if (!afs_osi_suser(*acred))
2428 /* too many things are setup initially in mem cache version */
2429 if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
2431 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2433 afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2435 if (newValue < afs_min_cache)
2436 afs_cacheBlocks = afs_min_cache;
2438 afs_cacheBlocks = newValue;
2440 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2441 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2442 afs_MaybeWakeupTruncateDaemon();
2443 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2444 afs_osi_Wait(1000, 0, 0);
2445 afs_MaybeWakeupTruncateDaemon();
2450 #define MAXGCSTATS 16
2452 * VIOCGETCACHEPARMS (40) - Get cache stats
2456 * \param[in] ain afs index flags
2457 * \param[out] aout cache blocks, blocks used, blocks files (in an array)
2459 * \post Get the cache blocks, and how many of the cache blocks there are
2461 DECL_PIOCTL(PGetCacheSize)
2463 afs_int32 results[MAXGCSTATS];
2465 register struct dcache * tdc;
2468 AFS_STATCNT(PGetCacheSize);
2470 if (sizeof(afs_int32) == ainSize){
2471 memcpy((char *)&flags, ain, sizeof(afs_int32));
2472 } else if (0 == ainSize){
2478 memset((char *)results, 0, sizeof(results));
2479 results[0] = afs_cacheBlocks;
2480 results[1] = afs_blocksUsed;
2481 results[2] = afs_cacheFiles;
2484 for (i = 0; i < afs_cacheFiles; i++) {
2485 if (afs_indexFlags[i] & IFFree) results[3]++;
2487 } else if (2 == flags){
2488 for (i = 0; i < afs_cacheFiles; i++) {
2489 if (afs_indexFlags[i] & IFFree) results[3]++;
2490 if (afs_indexFlags[i] & IFEverUsed) results[4]++;
2491 if (afs_indexFlags[i] & IFDataMod) results[5]++;
2492 if (afs_indexFlags[i] & IFDirtyPages) results[6]++;
2493 if (afs_indexFlags[i] & IFAnyPages) results[7]++;
2494 if (afs_indexFlags[i] & IFDiscarded) results[8]++;
2496 tdc = afs_indexTable[i];
2499 size = tdc->validPos;
2500 if ( 0 < size && size < (1<<12) ) results[10]++;
2501 else if (size < (1<<14) ) results[11]++;
2502 else if (size < (1<<16) ) results[12]++;
2503 else if (size < (1<<18) ) results[13]++;
2504 else if (size < (1<<20) ) results[14]++;
2505 else if (size >= (1<<20) ) results[15]++;
2509 memcpy(aout, (char *)results, sizeof(results));
2510 *aoutSize = sizeof(results);
2515 * VIOCFLUSHCB (25) - Flush callback only
2519 * \param[in] ain not in use
2520 * \param[out] aout not in use
2522 * \retval EINVAL Error if some of the standard args aren't set
2523 * \retval 0 0 returned if the volume is set to read-only
2525 * \post Flushes callbacks, by setting the length of callbacks to one, setting the next callback to be sent to the CB_DROPPED value, and then dequeues everything else.
2527 DECL_PIOCTL(PRemoveCallBack)
2529 register struct conn *tc;
2530 register afs_int32 code = 0;
2531 struct AFSCallBack CallBacks_Array[1];
2532 struct AFSCBFids theFids;
2533 struct AFSCBs theCBs;
2536 AFS_STATCNT(PRemoveCallBack);
2539 if (avc->states & CRO)
2540 return 0; /* read-only-ness can't change */
2541 ObtainWriteLock(&avc->lock, 229);
2542 theFids.AFSCBFids_len = 1;
2543 theCBs.AFSCBs_len = 1;
2544 theFids.AFSCBFids_val = (struct AFSFid *)&avc->fid.Fid;
2545 theCBs.AFSCBs_val = CallBacks_Array;
2546 CallBacks_Array[0].CallBackType = CB_DROPPED;
2547 if (avc->callback) {
2549 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2551 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2553 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2557 /* don't set code on failure since we wouldn't use it */
2558 } while (afs_Analyze
2559 (tc, code, &avc->fid, areq,
2560 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
2562 ObtainWriteLock(&afs_xcbhash, 457);
2563 afs_DequeueCallback(avc);
2565 avc->states &= ~(CStatd | CUnique);
2566 ReleaseWriteLock(&afs_xcbhash);
2567 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2568 osi_dnlc_purgedp(avc);
2570 ReleaseWriteLock(&avc->lock);
2575 * VIOCNEWCELL (26) - Configure new cell
2579 * \param[in] ain the name of the cell, the hosts that will be a part of the cell, whether or not it's linked with another cell, the other cell it's linked with, the file server port, and the volume server port
2580 * \param[out] aout not in use
2582 * \retval EIO Error if the afs daemon hasn't started yet
2583 * \retval EACCES Error if the user doesn't have super-user cedentials
2584 * \retval EINVAL Error if some 'magic' var doesn't have a certain bit set
2586 * \post creates a new cell
2588 DECL_PIOCTL(PNewCell)
2590 /* create a new cell */
2591 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic = 0;
2592 char *newcell = 0, *linkedcell = 0, *tp = ain;
2593 register afs_int32 code, linkedstate = 0, ls;
2594 u_short fsport = 0, vlport = 0;
2597 AFS_STATCNT(PNewCell);
2598 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2599 return EIO; /* Inappropriate ioctl for device */
2601 if (!afs_osi_suser(*acred))
2604 memcpy((char *)&magic, tp, sizeof(afs_int32));
2605 tp += sizeof(afs_int32);
2606 if (magic != 0x12345678)
2609 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2610 * server addresses while the 3.5 fs newcell command passes
2611 * MAXHOSTS. To figure out which is which, check if the cellname
2614 newcell = tp + (MAXCELLHOSTS + 3) * sizeof(afs_int32);
2615 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2617 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2618 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2619 tp += (scount * sizeof(afs_int32));
2621 lp = (afs_int32 *) tp;
2625 fsport = 0; /* Privileged ports not allowed */
2627 vlport = 0; /* Privileged ports not allowed */
2628 tp += (3 * sizeof(afs_int32));
2630 if ((ls = *lp) & 1) {
2631 linkedcell = tp + strlen(newcell) + 1;
2632 linkedstate |= CLinkedCell;
2635 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2637 afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2642 DECL_PIOCTL(PNewAlias)
2644 /* create a new cell alias */
2646 register afs_int32 code;
2647 char *realName, *aliasName;
2649 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2650 return EIO; /* Inappropriate ioctl for device */
2652 if (!afs_osi_suser(*acred))
2656 tp += strlen(aliasName) + 1;
2659 code = afs_NewCellAlias(aliasName, realName);
2665 * VIOCGETCELL (27) - Get cell info
2669 * \param[in] ain The cell index of a specific cell
2670 * \param[out] aout list of servers in the cell
2672 * \retval EIO Error if the afs daemon hasn't started yet
2673 * \retval EDOM Error if there is no cell asked about
2675 * \post Lists the cell's server names and and addresses
2677 DECL_PIOCTL(PListCells)
2679 afs_int32 whichCell;
2680 register struct cell *tcell = 0;
2681 register afs_int32 i;
2682 register char *cp, *tp = ain;
2684 AFS_STATCNT(PListCells);
2685 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2686 return EIO; /* Inappropriate ioctl for device */
2688 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2689 tp += sizeof(afs_int32);
2690 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2693 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2694 for (i = 0; i < MAXCELLHOSTS; i++) {
2695 if (tcell->cellHosts[i] == 0)
2697 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip,
2699 cp += sizeof(afs_int32);
2701 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2702 strcpy(cp, tcell->cellName);
2703 cp += strlen(tcell->cellName) + 1;
2704 *aoutSize = cp - aout;
2705 afs_PutCell(tcell, READ_LOCK);
2713 DECL_PIOCTL(PListAliases)
2715 afs_int32 whichAlias;
2716 register struct cell_alias *tcalias = 0;
2717 register char *cp, *tp = ain;
2719 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2720 return EIO; /* Inappropriate ioctl for device */
2721 if (ainSize < sizeof(afs_int32))
2724 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2725 tp += sizeof(afs_int32);
2727 tcalias = afs_GetCellAlias(whichAlias);
2730 strcpy(cp, tcalias->alias);
2731 cp += strlen(tcalias->alias) + 1;
2732 strcpy(cp, tcalias->cell);
2733 cp += strlen(tcalias->cell) + 1;
2734 *aoutSize = cp - aout;
2735 afs_PutCellAlias(tcalias);
2744 * VIOC_AFS_DELETE_MT_PT (28) - Delete mount point
2748 * \param[in] ain the name of the file in this dir to remove
2749 * \param[out] aout not in use
2751 * \retval EINVAL Error if some of the standard args aren't set
2752 * \retval ENOTDIR Error if the argument to remove is not a directory
2753 * \retval ENOENT Error if there is no cache to remove the mount point from or if a vcache doesn't exist
2755 * \post Ensure that everything is OK before deleting the mountpoint. If not, don't delete. Delete a mount point based on a file id.
2757 DECL_PIOCTL(PRemoveMount)
2759 register afs_int32 code;
2761 struct sysname_info sysState;
2762 afs_size_t offset, len;
2763 register struct conn *tc;
2764 register struct dcache *tdc;
2765 register struct vcache *tvc;
2766 struct AFSFetchStatus OutDirStatus;
2767 struct VenusFid tfid;
2768 struct AFSVolSync tsync;
2772 /* "ain" is the name of the file in this dir to remove */
2774 AFS_STATCNT(PRemoveMount);
2777 code = afs_VerifyVCache(avc, areq);
2780 if (vType(avc) != VDIR)
2783 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2786 Check_AtSys(avc, ain, &sysState, areq);
2787 ObtainReadLock(&tdc->lock);
2789 code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
2790 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2791 ReleaseReadLock(&tdc->lock);
2792 bufp = sysState.name;
2797 tfid.Cell = avc->fid.Cell;
2798 tfid.Fid.Volume = avc->fid.Fid.Volume;
2799 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2800 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2802 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2809 if (tvc->mvstat != 1) {
2815 ObtainWriteLock(&tvc->lock, 230);
2816 code = afs_HandleLink(tvc, areq);
2818 if (tvc->linkData) {
2819 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2824 ReleaseWriteLock(&tvc->lock);
2825 osi_dnlc_purgedp(tvc);
2831 ObtainWriteLock(&avc->lock, 231);
2832 osi_dnlc_remove(avc, bufp, tvc);
2834 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2836 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2839 RXAFS_RemoveFile(tc->id, (struct AFSFid *)&avc->fid.Fid, bufp,
2840 &OutDirStatus, &tsync);
2845 } while (afs_Analyze
2846 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE,
2847 SHARED_LOCK, NULL));
2852 ReleaseWriteLock(&avc->lock);
2856 /* we have the thing in the cache */
2857 ObtainWriteLock(&tdc->lock, 661);
2858 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2859 /* we can do it locally */
2860 code = afs_dir_Delete(tdc, bufp);
2862 ZapDCE(tdc); /* surprise error -- invalid value */
2866 ReleaseWriteLock(&tdc->lock);
2867 afs_PutDCache(tdc); /* drop ref count */
2869 avc->states &= ~CUnique; /* For the dfs xlator */
2870 ReleaseWriteLock(&avc->lock);
2873 if (sysState.allocked)
2874 osi_FreeLargeSpace(bufp);
2879 * VIOC_VENUSLOG (34) - Enable/Disable venus logging
2883 * \retval EINVAL Error if some of the standard args aren't set
2885 * \notes Obsoleted, perhaps should be PBogus
2887 DECL_PIOCTL(PVenusLogging)
2889 return EINVAL; /* OBSOLETE */
2893 * VIOC_GETCELLSTATUS (35) - Get cell status info
2897 * \param[in] ain The cell you want status information on
2898 * \param[out] aout cell state (as a struct)
2900 * \retval EIO Error if the afs daemon hasn't started yet
2901 * \retval ENOENT Error if the cell doesn't exist
2903 * \post Returns the state of the cell as defined in a struct cell
2905 DECL_PIOCTL(PGetCellStatus)
2907 register struct cell *tcell;
2910 AFS_STATCNT(PGetCellStatus);
2911 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2912 return EIO; /* Inappropriate ioctl for device */
2914 tcell = afs_GetCellByName(ain, READ_LOCK);
2917 temp = tcell->states;
2918 afs_PutCell(tcell, READ_LOCK);
2919 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2920 *aoutSize = sizeof(afs_int32);
2925 * VIOC_SETCELLSTATUS (36) - Set corresponding info
2929 * \param[in] ain The cell you want to set information about, and the values you want to set
2930 * \param[out] aout not in use
2932 * \retval EIO Error if the afs daemon hasn't started yet
2933 * \retval EACCES Error if the user doesn't have super-user credentials
2935 * \post Set the state of the cell in a defined struct cell, based on whether or not SetUID is allowed
2937 DECL_PIOCTL(PSetCellStatus)
2939 register struct cell *tcell;
2942 if (!afs_osi_suser(*acred))
2944 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2945 return EIO; /* Inappropriate ioctl for device */
2947 tcell = afs_GetCellByName(ain + 2 * sizeof(afs_int32), WRITE_LOCK);
2950 memcpy((char *)&temp, ain, sizeof(afs_int32));
2952 tcell->states |= CNoSUID;
2954 tcell->states &= ~CNoSUID;
2955 afs_PutCell(tcell, WRITE_LOCK);
2960 * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
2964 * \param[in] ain not in use (args in avc)
2965 * \param[out] aout not in use
2967 * \retval EINVAL Error if some of the standard args aren't set
2968 * \retval EIO Error if the afs daemon hasn't started yet
2970 * \post Wipe everything on the volume. This is done dependent on which platform this is for.
2972 * \notes Does not flush a file that a user has open and is using, because it will be re-created on next write. Also purges the dnlc, because things are screwed up.
2974 DECL_PIOCTL(PFlushVolumeData)
2976 register afs_int32 i;
2977 register struct dcache *tdc;
2978 register struct vcache *tvc;
2979 register struct volume *tv;
2980 afs_int32 cell, volume;
2981 struct afs_q *tq, *uq;
2982 #ifdef AFS_DARWIN80_ENV
2986 AFS_STATCNT(PFlushVolumeData);
2989 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2990 return EIO; /* Inappropriate ioctl for device */
2992 volume = avc->fid.Fid.Volume; /* who to zap */
2993 cell = avc->fid.Cell;
2996 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2997 * the vcaches associated with the volume.
3000 ObtainReadLock(&afs_xvcache);
3001 i = VCHashV(&avc->fid);
3002 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
3005 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
3006 if (tvc->states & CVInit) {
3007 ReleaseReadLock(&afs_xvcache);
3008 afs_osi_Sleep(&tvc->states);
3011 #ifdef AFS_DARWIN80_ENV
3012 if (tvc->states & CDeadVnode) {
3013 ReleaseReadLock(&afs_xvcache);
3014 afs_osi_Sleep(&tvc->states);
3018 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
3019 VN_HOLD(AFSTOV(tvc));
3021 #ifdef AFS_DARWIN80_ENV
3025 if (vnode_ref(vp)) {
3032 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
3035 VREFCOUNT_INC(tvc); /* AIX, apparently */
3039 ReleaseReadLock(&afs_xvcache);
3040 #ifdef AFS_BOZONLOCK_ENV
3041 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3043 ObtainWriteLock(&tvc->lock, 232);
3045 ObtainWriteLock(&afs_xcbhash, 458);
3046 afs_DequeueCallback(tvc);
3047 tvc->states &= ~(CStatd | CDirty);
3048 ReleaseWriteLock(&afs_xcbhash);
3049 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
3050 osi_dnlc_purgedp(tvc);
3051 afs_TryToSmush(tvc, *acred, 1);
3052 ReleaseWriteLock(&tvc->lock);
3053 #ifdef AFS_BOZONLOCK_ENV
3054 afs_BozonUnlock(&tvc->pvnLock, tvc);
3056 #ifdef AFS_DARWIN80_ENV
3057 vnode_put(AFSTOV(tvc));
3059 ObtainReadLock(&afs_xvcache);
3061 /* our tvc ptr is still good until now */
3065 ReleaseReadLock(&afs_xvcache);
3068 MObtainWriteLock(&afs_xdcache, 328); /* needed if you're going to flush any stuff */
3069 for (i = 0; i < afs_cacheFiles; i++) {
3070 if (!(afs_indexFlags[i] & IFEverUsed))
3071 continue; /* never had any data */
3072 tdc = afs_GetDSlot(i, NULL);
3073 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
3074 ReleaseReadLock(&tdc->tlock);
3075 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
3076 if (!(afs_indexFlags[i] & IFDataMod)) {
3077 /* if the file is modified, but has a ref cnt of only 1, then
3078 * someone probably has the file open and is writing into it.
3079 * Better to skip flushing such a file, it will be brought back
3080 * immediately on the next write anyway.
3082 * If we *must* flush, then this code has to be rearranged to call
3083 * afs_storeAllSegments() first */
3084 afs_FlushDCache(tdc);
3088 ReleaseReadLock(&tdc->tlock);
3090 afs_PutDCache(tdc); /* bumped by getdslot */
3092 MReleaseWriteLock(&afs_xdcache);
3094 ObtainReadLock(&afs_xvolume);
3095 for (i = 0; i < NVOLS; i++) {
3096 for (tv = afs_volumes[i]; tv; tv = tv->next) {
3097 if (tv->volume == volume) {
3098 afs_ResetVolumeInfo(tv);
3103 ReleaseReadLock(&afs_xvolume);
3105 /* probably, a user is doing this, probably, because things are screwed up.
3106 * maybe it's the dnlc's fault? */
3113 * VIOCGETVCXSTATUS (41) - gets vnode x status
3117 * \param[in] ain not in use (avc used)
3118 * \param[out] aout vcxstat: the file id, the data version, any lock, the parent vnode, the parent unique id, the trunc position, the callback, cbExpires, what access is being made, what files are open, any users executing/writing, the flock ount, the states, the move stat
3120 * \retval EINVAL Error if some of the initial default arguments aren't set
3121 * \retval EACCES Error if access to check the mode bits is denied
3123 * \post gets stats for the vnode, a struct listed in vcxstat
3125 DECL_PIOCTL(PGetVnodeXStatus)
3127 register afs_int32 code;
3128 struct vcxstat stat;
3131 /* AFS_STATCNT(PGetVnodeXStatus); */
3134 code = afs_VerifyVCache(avc, areq);
3137 if (vType(avc) == VDIR)
3138 mode = PRSFS_LOOKUP;
3141 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
3144 memset(&stat, 0, sizeof(struct vcxstat));
3145 stat.fid = avc->fid;
3146 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
3147 stat.lock = avc->lock;
3148 stat.parentVnode = avc->parentVnode;
3149 stat.parentUnique = avc->parentUnique;
3150 hset(stat.flushDV, avc->flushDV);
3151 hset(stat.mapDV, avc->mapDV);
3152 stat.truncPos = avc->truncPos;
3153 { /* just grab the first two - won't break anything... */
3154 struct axscache *ac;
3156 for (i = 0, ac = avc->Access; ac && i < CPSIZE; i++, ac = ac->next) {
3157 stat.randomUid[i] = ac->uid;
3158 stat.randomAccess[i] = ac->axess;
3161 stat.callback = afs_data_pointer_to_int32(avc->callback);
3162 stat.cbExpires = avc->cbExpires;
3163 stat.anyAccess = avc->anyAccess;
3164 stat.opens = avc->opens;
3165 stat.execsOrWriters = avc->execsOrWriters;
3166 stat.flockCount = avc->flockCount;
3167 stat.mvstat = avc->mvstat;
3168 stat.states = avc->states;
3169 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
3170 *aoutSize = sizeof(struct vcxstat);
3175 DECL_PIOCTL(PGetVnodeXStatus2)
3177 register afs_int32 code;
3178 struct vcxstat2 stat;
3183 code = afs_VerifyVCache(avc, areq);
3186 if (vType(avc) == VDIR)
3187 mode = PRSFS_LOOKUP;
3190 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
3193 memset(&stat, 0, sizeof(struct vcxstat2));
3195 stat.cbExpires = avc->cbExpires;
3196 stat.anyAccess = avc->anyAccess;
3197 stat.mvstat = avc->mvstat;
3198 stat.callerAccess = afs_GetAccessBits(avc, ~0, areq);
3200 memcpy(aout, (char *)&stat, sizeof(struct vcxstat2));
3201 *aoutSize = sizeof(struct vcxstat2);
3207 * VIOC_AFS_SYSNAME (38) - Change @sys value
3211 * \param[in] ain new value for @sys
3212 * \param[out] aout count, entry, list (debug values?)
3214 * \retval EINVAL Error if afsd isn't running, the new sysname is too large, the new sysname causes issues (starts with a .0 or ..0), there is no PAG set in the credentials, the user of a PAG can't be found, (!(exporter = au->exporter)) "NOT SURE ON THIS"
3215 * \retval ENODEV Error if there isn't already a system named that ("I THINK")
3216 * \retval EACCES Error if the user doesn't have super-user credentials
3218 * \post Set the value of @sys if these things work: if the input isn't too long or if input doesn't start with .0 or ..0
3220 * \notes We require root for local sysname changes, but not for remote (since we don't really believe remote uids anyway) outname[] shouldn't really be needed- this is left as an exercise for the reader.
3222 DECL_PIOCTL(PSetSysName)
3224 char *cp, *cp2 = NULL, inname[MAXSYSNAME], outname[MAXSYSNAME];
3225 afs_int32 setsysname;
3227 register struct afs_exporter *exporter;
3228 register struct unixuser *au;
3229 register afs_int32 pag, error;
3230 int t, count, num = 0, allpags = 0;
3233 AFS_STATCNT(PSetSysName);
3234 if (!afs_globalVFS) {
3235 /* Afsd is NOT running; disable it */
3236 #if defined(KERNEL_HAVE_UERROR)
3237 return (setuerror(EINVAL), EINVAL);
3242 memset(inname, 0, MAXSYSNAME);
3243 memcpy(&setsysname, ain, sizeof(afs_int32));
3244 ain += sizeof(afs_int32);
3245 if (setsysname & 0x8000) {
3247 setsysname &= ~0x8000;
3252 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
3255 for (cp = ain, count = 0; count < setsysname; count++) {
3256 /* won't go past end of ain since maxsysname*num < ain length */
3258 if (t >= MAXSYSNAME || t <= 0)
3260 /* check for names that can shoot us in the foot */
3261 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
3267 /* inname gets first entry in case we're being a translator */
3269 memcpy(inname, ain, t + 1); /* include terminating null */
3273 if ((*acred)->cr_gid == RMTUSER_REQ ||
3274 (*acred)->cr_gid == RMTUSER_REQ_PRIV) { /* Handles all exporters */
3275 if (allpags && (*acred)->cr_gid != RMTUSER_REQ_PRIV) {
3278 pag = PagInCred(*acred);
3280 return EINVAL; /* Better than panicing */
3282 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
3283 return EINVAL; /* Better than panicing */
3285 if (!(exporter = au->exporter)) {
3286 afs_PutUser(au, READ_LOCK);
3287 return EINVAL; /* Better than panicing */
3289 error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), &sysnamelist,
3292 if (error == ENODEV)
3293 foundname = 0; /* sysname not set yet! */
3295 afs_PutUser(au, READ_LOCK);
3300 strcpy(outname, sysnamelist[0]);
3302 afs_PutUser(au, READ_LOCK);
3306 /* Not xlating, so local case */
3308 osi_Panic("PSetSysName: !afs_sysname\n");
3309 if (!setsysname) { /* user just wants the info */
3310 strcpy(outname, afs_sysname);
3311 foundname = afs_sysnamecount;
3312 sysnamelist = afs_sysnamelist;
3313 } else { /* Local guy; only root can change sysname */
3314 if (!afs_osi_suser(*acred))
3317 /* allpags makes no sense for local use */
3321 /* clear @sys entries from the dnlc, once afs_lookup can
3322 * do lookups of @sys entries and thinks it can trust them */
3323 /* privs ok, store the entry, ... */
3324 strcpy(afs_sysname, inname);
3325 if (setsysname > 1) { /* ... or list */
3327 for (count = 1; count < setsysname; ++count) {
3328 if (!afs_sysnamelist[count])
3330 ("PSetSysName: no afs_sysnamelist entry to write\n");
3332 memcpy(afs_sysnamelist[count], cp, t + 1); /* include null */
3336 afs_sysnamecount = setsysname;
3341 cp = aout; /* not changing so report back the count and ... */
3342 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
3343 cp += sizeof(afs_int32);
3345 strcpy(cp, outname); /* ... the entry, ... */
3346 cp += strlen(outname) + 1;
3347 for (count = 1; count < foundname; ++count) { /* ... or list. */
3348 if (!sysnamelist[count])
3350 ("PSetSysName: no afs_sysnamelist entry to read\n");
3351 t = strlen(sysnamelist[count]);
3352 if (t >= MAXSYSNAME)
3353 osi_Panic("PSetSysName: sysname entry garbled\n");
3354 strcpy(cp, sysnamelist[count]);
3358 *aoutSize = cp - aout;
3363 /* sequential search through the list of touched cells is not a good
3364 * long-term solution here. For small n, though, it should be just
3365 * fine. Should consider special-casing the local cell for large n.
3366 * Likewise for PSetSPrefs.
3368 * s - number of ids in array l[] -- NOT index of last id
3369 * l - array of cell ids which have volumes that need to be sorted
3370 * vlonly - sort vl servers or file servers?
3373 ReSortCells_cb(struct cell *cell, void *arg)
3375 afs_int32 *p = (afs_int32 *) arg;
3376 afs_int32 *l = p + 1;
3379 for (i = 0; i < s; i++) {
3380 if (l[i] == cell->cellNum) {
3381 ObtainWriteLock(&cell->lock, 690);
3382 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
3383 ReleaseWriteLock(&cell->lock);
3391 ReSortCells(int s, afs_int32 * l, int vlonly)
3399 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
3401 memcpy(p + 1, l, s * sizeof(afs_int32));
3402 afs_TraverseCells(&ReSortCells_cb, p);
3403 afs_osi_Free(p, sizeof(afs_int32) * (s + 1));
3407 ObtainReadLock(&afs_xvolume);
3408 for (i = 0; i < NVOLS; i++) {
3409 for (j = afs_volumes[i]; j; j = j->next) {
3410 for (k = 0; k < s; k++)
3411 if (j->cell == l[k]) {
3412 ObtainWriteLock(&j->lock, 233);
3413 afs_SortServers(j->serverHost, MAXHOSTS);
3414 ReleaseWriteLock(&j->lock);
3419 ReleaseReadLock(&afs_xvolume);
3423 static int debugsetsp = 0;
3425 afs_setsprefs(struct spref *sp, unsigned int num, unsigned int vlonly)
3428 int i, j, k, matches, touchedSize;
3429 struct server *srvr = NULL;
3430 afs_int32 touched[34];
3434 for (k = 0; k < num; sp++, k++) {
3436 printf("sp host=%x, rank=%d\n", sp->host.s_addr, sp->rank);
3439 ObtainReadLock(&afs_xserver);
3441 i = SHash(sp->host.s_addr);
3442 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
3443 if (sa->sa_ip == sp->host.s_addr) {
3445 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3446 || (sa->sa_portal == AFS_FSPORT);
3447 if ((!vlonly && isfs) || (vlonly && !isfs)) {
3454 if (sa && matches) { /* found one! */
3456 printf("sa ip=%x, ip_rank=%d\n", sa->sa_ip, sa->sa_iprank);
3458 sa->sa_iprank = sp->rank + afs_randomMod15();
3459 afs_SortOneServer(sa->server);
3462 /* if we don't know yet what cell it's in, this is moot */
3463 for (j = touchedSize - 1;
3464 j >= 0 && touched[j] != srvr->cell->cellNum; j--)
3465 /* is it in our list of touched cells ? */ ;
3466 if (j < 0) { /* no, it's not */
3467 touched[touchedSize++] = srvr->cell->cellNum;
3468 if (touchedSize >= 32) { /* watch for ovrflow */
3469 ReleaseReadLock(&afs_xserver);
3470 ReSortCells(touchedSize, touched, vlonly);
3472 ObtainReadLock(&afs_xserver);
3478 ReleaseReadLock(&afs_xserver);
3479 /* if we didn't find one, start to create one. */
3480 /* Note that it doesn't have a cell yet... */
3482 afs_uint32 temp = sp->host.s_addr;
3484 afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
3485 WRITE_LOCK, (afsUUID *) 0, 0);
3486 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
3487 afs_PutServer(srvr, WRITE_LOCK);
3489 } /* for all cited preferences */
3491 ReSortCells(touchedSize, touched, vlonly);
3496 * VIOC_SETPREFS (46) - Set server ranks
3498 * \param[in] ain the sprefs value you want the sprefs to be set to
3499 * \param[out] aout not in use
3501 * \retval EIO Error if the afs daemon hasn't started yet
3502 * \retval EACCES Error if the user doesn't have super-user credentials
3503 * \retval EINVAL Error if the struct setsprefs is too large or if it multiplied by the number of servers is too large
3505 * \post set the sprefs using the afs_setsprefs() function
3507 DECL_PIOCTL(PSetSPrefs)
3509 struct setspref *ssp;
3510 AFS_STATCNT(PSetSPrefs);
3512 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3513 return EIO; /* Inappropriate ioctl for device */
3515 if (!afs_osi_suser(*acred))
3518 if (ainSize < sizeof(struct setspref))
3521 ssp = (struct setspref *)ain;
3522 if (ainSize < sizeof(struct spref) * ssp->num_servers)
3525 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
3526 (ssp->flags & DBservers));
3531 * VIOC_SETPREFS33 (42) - Set server ranks (deprecated)
3533 * \param[in] ain the server preferences to be set
3534 * \param[out] aout not in use
3536 * \retval EIO Error if the afs daemon hasn't started yet
3537 * \retval EACCES Error if the user doesn't have super-user credentials
3539 * \post set the server preferences, calling a function
3541 * \notes this may only be performed by the local root user.
3543 DECL_PIOCTL(PSetSPrefs33)
3546 AFS_STATCNT(PSetSPrefs);
3547 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3548 return EIO; /* Inappropriate ioctl for device */
3551 if (!afs_osi_suser(*acred))
3554 sp = (struct spref *)ain;
3555 afs_setsprefs(sp, ainSize / (sizeof(struct spref)), 0 /*!vlonly */ );
3560 * VIOC_GETSPREFS (43) - Get server ranks
3564 * \param[in] ain the server preferences to get
3565 * \param[out] aout the server preferences information
3567 * \retval EIO Error if the afs daemon hasn't started yet
3568 * \retval ENOENT Error if the sprefrequest is too large
3570 * \post Get the sprefs
3572 * \notes in the hash table of server structs, all servers with the same IP address; will be on the same overflow chain; This could be sped slightly in some circumstances by having it cache the immediately previous slot in the hash table and some supporting information; Only reports file servers now.
3574 DECL_PIOCTL(PGetSPrefs)
3576 struct sprefrequest *spin; /* input */
3577 struct sprefinfo *spout; /* output */
3578 struct spref *srvout; /* one output component */
3579 int i, j; /* counters for hash table traversal */
3580 struct server *srvr; /* one of CM's server structs */
3582 int vlonly; /* just return vlservers ? */
3585 AFS_STATCNT(PGetSPrefs);
3586 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3587 return EIO; /* Inappropriate ioctl for device */
3590 if (ainSize < sizeof(struct sprefrequest_33)) {
3593 spin = ((struct sprefrequest *)ain);
3596 if (ainSize > sizeof(struct sprefrequest_33)) {
3597 vlonly = (spin->flags & DBservers);
3601 /* struct sprefinfo includes 1 server struct... that size gets added
3602 * in during the loop that follows.
3604 *aoutSize = sizeof(struct sprefinfo) - sizeof(struct spref);
3605 spout = (struct sprefinfo *)aout;
3606 spout->next_offset = spin->offset;
3607 spout->num_servers = 0;
3608 srvout = spout->servers;
3610 ObtainReadLock(&afs_xserver);
3611 for (i = 0, j = 0; j < NSERVERS; j++) { /* sift through hash table */
3612 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
3613 if (spin->offset > (unsigned short)i) {
3614 continue; /* catch up to where we left off */
3616 spout->next_offset++;
3619 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3620 || (sa->sa_portal == AFS_FSPORT);
3622 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3623 /* only report ranks for vl servers */
3627 srvout->host.s_addr = sa->sa_ip;
3628 srvout->rank = sa->sa_iprank;
3629 *aoutSize += sizeof(struct spref);
3630 spout->num_servers++;
3633 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3634 ReleaseReadLock(&afs_xserver); /* no more room! */
3639 ReleaseReadLock(&afs_xserver);
3641 spout->next_offset = 0; /* start over from the beginning next time */
3645 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3646 int afs_NFSRootOnly = 1;
3648 * VIOC_EXPORTAFS (39) - Export afs to nfs clients
3652 * \param[in] ain a struct Vic * EIOctl containing export values needed to change between nfs and afs
3653 * \param[out] aout a struct of the exporter states (exporter->exp_states)
3655 * \retval ENODEV Error if the exporter doesn't exist
3656 * \retval EACCES Error if the user doesn't have super-user credentials
3658 * \post Changes the state of various values to reflect the change of the export values between nfs and afs.
3660 * \notes Legacy code obtained from IBM.
3662 DECL_PIOCTL(PExportAfs)
3664 afs_int32 export, newint =
3665 0, type, changestate, handleValue, convmode, pwsync, smounts;
3666 afs_int32 rempags = 0, pagcb = 0;
3667 register struct afs_exporter *exporter;
3669 AFS_STATCNT(PExportAfs);
3670 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
3671 type = handleValue >> 24;
3676 exporter = exporter_find(type);
3678 export = handleValue & 3;
3679 changestate = handleValue & 0xfff;
3680 smounts = (handleValue >> 2) & 3;
3681 pwsync = (handleValue >> 4) & 3;
3682 convmode = (handleValue >> 6) & 3;
3683 rempags = (handleValue >> 8) & 3;
3684 pagcb = (handleValue >> 10) & 3;
3686 changestate = (handleValue >> 16) & 0x1;
3687 convmode = (handleValue >> 16) & 0x2;
3688 pwsync = (handleValue >> 16) & 0x4;
3689 smounts = (handleValue >> 16) & 0x8;
3690 export = handleValue & 0xff;
3693 /* Failed finding desired exporter; */
3697 handleValue = exporter->exp_states;
3698 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3699 *aoutSize = sizeof(afs_int32);
3701 if (!afs_osi_suser(*acred))
3702 return EACCES; /* Only superuser can do this */
3706 exporter->exp_states |= EXP_EXPORTED;
3708 exporter->exp_states &= ~EXP_EXPORTED;
3712 exporter->exp_states |= EXP_UNIXMODE;
3714 exporter->exp_states &= ~EXP_UNIXMODE;