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