cbf96beca862d5b372139c2aeb660f857594c9d1
[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 #if !defined(AFS_ATHENA_ENV)
68 int
69 #ifdef AFS_AIX41_ENV
70 afs_fid(OSI_VC_DECL(avc), struct fid *fidpp, struct ucred *credp)
71 #elif defined(AFS_SUN54_ENV)
72 afs_fid(OSI_VC_DECL(avc), struct fid *fidpp)
73 #else
74 afs_fid(OSI_VC_DECL(avc), struct fid **fidpp)
75 #endif                          /* AFS_AIX41_ENV */
76 {
77     struct SmallFid Sfid;
78     long addr[2];
79     register struct cell *tcell;
80     extern struct vcache *afs_globalVp;
81     int SizeOfSmallFid = SIZEOF_SMALLFID;
82     int rootvp = 0;
83     OSI_VC_CONVERT(avc);
84
85     AFS_STATCNT(afs_fid);
86
87     if (afs_shuttingdown)
88         return EIO;
89
90     if (afs_NFSRootOnly && (avc == afs_globalVp))
91         rootvp = 1;
92     if (!afs_NFSRootOnly || rootvp
93 #ifdef AFS_AIX41_ENV
94         || USE_SMALLFID(credp)
95 #endif
96         ) {
97         tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
98         Sfid.Volume = avc->f.fid.Fid.Volume;
99         Sfid.Vnode = avc->f.fid.Fid.Vnode;
100         Sfid.CellAndUnique =
101             ((tcell->cellIndex << 24) + (avc->f.fid.Fid.Unique & 0xffffff));
102         afs_PutCell(tcell, READ_LOCK);
103         if (avc->f.fid.Fid.Vnode > 0xffff)
104             afs_fid_vnodeoverflow++;
105         if (avc->f.fid.Fid.Unique > 0xffffff)
106             afs_fid_uniqueoverflow++;
107     } else {
108 #if defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64))
109         addr[1] = (long)AFS_XLATOR_MAGIC << 48;
110 #else /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
111         addr[1] = AFS_XLATOR_MAGIC;
112         SizeOfSmallFid = sizeof(addr);
113 #endif /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
114         addr[0] = (long)avc;
115 #ifndef AFS_AIX41_ENV
116         /* No post processing, so don't hold ref count. */
117         AFS_FAST_HOLD(avc);
118 #endif
119     }
120 #if     defined(AFS_AIX_ENV) || defined(AFS_SUN54_ENV)
121     /* Use the fid pointer passed to us. */
122     fidpp->fid_len = SizeOfSmallFid;
123
124     if (afs_NFSRootOnly) {
125         if (rootvp
126 #ifdef AFS_AIX41_ENV
127             || USE_SMALLFID(credp)
128 #endif
129             ) {
130             memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
131         } else {
132             memcpy(fidpp->fid_data, (caddr_t) addr, SizeOfSmallFid);
133         }
134     } else {
135         memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
136     }
137 #else
138     /* malloc a fid pointer ourselves. */
139     *fidpp = (struct fid *)AFS_KALLOC(SizeOfSmallFid + 2);
140     (*fidpp)->fid_len = SizeOfSmallFid;
141     if (afs_NFSRootOnly) {
142         if (rootvp) {
143             memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
144         } else {
145             memcpy((*fidpp)->fid_data, (char *)addr, SizeOfSmallFid);
146         }
147     } else {
148         memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
149     }
150 #endif
151     return (0);
152 }
153 #endif
154
155
156 #endif /* !AFS_LINUX20_ENV */