Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / VNOPS / afs_vnop_fid.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10 /*
11 * Implements:
12 * afs_fid
13 *
14 */
15
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19
20 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_OBSD_ENV) && !defined(AFS_NBSD_ENV)
21 #include "afs/sysincludes.h" /* Standard vendor system headers */
22 #include "afsincludes.h" /* Afs-based standard headers */
23 #include "afs/afs_stats.h" /* statistics */
24 #include "afs/afs_cbqueue.h"
25 #include "afs/nfsclient.h"
26 #include "afs/afs_osidnlc.h"
27
28
29
30 int afs_fid_vnodeoverflow = 0, afs_fid_uniqueoverflow = 0;
31
32 /*
33 * afs_fid
34 *
35 * afs_fid can return two flavors of NFS fid, depending on if submounts are
36 * allowed. The reason for this is that we can't guarantee that we found all
37 * the entry points any OS might use to get the fid for the NFS mountd.
38 * Hence we return a "magic" fid for all but /afs. If it goes through the
39 * translator code, it will get transformed into a SmallFid that we recognize.
40 * So, if submounts are disallowed, and an NFS client tries a submount, it will
41 * get a fid which we don't recognize and the mount will either fail or we
42 * will ignore subsequent requests for that mount.
43 *
44 * The Alpha fid is organized differently than for other platforms. Their
45 * intention was to have the data portion of the fid aligned on a 4 byte
46 * boundary. To do so, the fid is organized as:
47 * u_short reserved
48 * u_short len
49 * char data[8]
50 * The len field is the length of the entire fid, from reserved through data.
51 * This length is used by fid_copy to include copying the reserved field.
52 * Alpha's zero the reserved field before handing us the fid, but they use
53 * it in fid_cmp. We use the reserved field to store the 16 bits of the Vnode.
54 *
55 * Note that the SmallFid only allows for 8 bits of the cell index and
56 * 16 bits of the vnode.
57 */
58
59 #ifdef AFS_AIX41_ENV
60 int afs_iauth_initd = 0;
61 #define USE_SMALLFID(C) (afs_iauth_initd && AFS_NFSXLATORREQ(C))
62 #endif
63
64
65 extern int afs_NFSRootOnly; /* 1 => only allow NFS mounts of /afs. */
66
67 int
68 #ifdef AFS_AIX41_ENV
69 afs_fid(OSI_VC_DECL(avc), struct fid *fidpp, struct ucred *credp)
70 #elif defined(AFS_SUN5_ENV)
71 afs_fid(OSI_VC_DECL(avc), struct fid *fidpp)
72 #else
73 afs_fid(OSI_VC_DECL(avc), struct fid **fidpp)
74 #endif /* AFS_AIX41_ENV */
75 {
76 struct SmallFid Sfid;
77 long addr[2];
78 struct cell *tcell;
79 extern struct vcache *afs_globalVp;
80 int SizeOfSmallFid = SIZEOF_SMALLFID;
81 int rootvp = 0;
82 OSI_VC_CONVERT(avc);
83
84 AFS_STATCNT(afs_fid);
85
86 if (afs_shuttingdown != AFS_RUNNING)
87 return EIO;
88
89 if (afs_NFSRootOnly && (avc == afs_globalVp))
90 rootvp = 1;
91 if (!afs_NFSRootOnly || rootvp
92 #ifdef AFS_AIX41_ENV
93 || USE_SMALLFID(credp)
94 #endif
95 ) {
96 tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
97 Sfid.Volume = avc->f.fid.Fid.Volume;
98 Sfid.Vnode = avc->f.fid.Fid.Vnode;
99 Sfid.CellAndUnique =
100 ((tcell->cellIndex << 24) + (avc->f.fid.Fid.Unique & 0xffffff));
101 afs_PutCell(tcell, READ_LOCK);
102 if (avc->f.fid.Fid.Vnode > 0xffff)
103 afs_fid_vnodeoverflow++;
104 if (avc->f.fid.Fid.Unique > 0xffffff)
105 afs_fid_uniqueoverflow++;
106 } else {
107 #if defined(AFS_SUN5_64BIT_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64))
108 addr[1] = (long)AFS_XLATOR_MAGIC << 48;
109 #else /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
110 addr[1] = AFS_XLATOR_MAGIC;
111 SizeOfSmallFid = sizeof(addr);
112 #endif /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
113 addr[0] = (long)avc;
114 #ifndef AFS_AIX41_ENV
115 /* No post processing, so don't hold ref count. */
116 AFS_FAST_HOLD(avc);
117 #endif
118 }
119 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
120 /* Use the fid pointer passed to us. */
121 fidpp->fid_len = SizeOfSmallFid;
122
123 if (afs_NFSRootOnly) {
124 if (rootvp
125 #ifdef AFS_AIX41_ENV
126 || USE_SMALLFID(credp)
127 #endif
128 ) {
129 memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
130 } else {
131 memcpy(fidpp->fid_data, (caddr_t) addr, SizeOfSmallFid);
132 }
133 } else {
134 memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
135 }
136 #else
137 /* malloc a fid pointer ourselves. */
138 *fidpp = (struct fid *)AFS_KALLOC(SizeOfSmallFid + 2);
139 (*fidpp)->fid_len = SizeOfSmallFid;
140 if (afs_NFSRootOnly) {
141 if (rootvp) {
142 memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
143 } else {
144 memcpy((*fidpp)->fid_data, (char *)addr, SizeOfSmallFid);
145 }
146 } else {
147 memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
148 }
149 #endif
150 return (0);
151 }
152
153
154 #endif /* !AFS_LINUX20_ENV */