Remove the RCSID macro
[openafs.git] / src / afs / AIX / osi_inode.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  * AIX inode operations
12  *
13  * Implements:
14  *
15  */
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19
20 #include "afs/sysincludes.h"    /* Standard vendor system headers */
21 #include "afsincludes.h"        /* Afs-based standard headers */
22 #include "afs/osi_inode.h"
23 #include "afs/afs_stats.h"      /* statistics stuff */
24 #include "sys/syspest.h"
25
26 #if !defined(offsetof)
27 #include <stddef.h>             /* for definition of offsetof() */
28 #endif
29
30 extern Simple_lock jfs_icache_lock;
31 #define ICACHE_LOCK()           simple_lock(&jfs_icache_lock)
32 #define ICACHE_UNLOCK()         simple_unlock(&jfs_icache_lock)
33
34 /*
35  * In AIX 4.2.0, the inode member to lock is i_rdwrlock.  The inode
36  * structure conditionally contains a member called i_nodelock which we
37  * do NOT want to use.
38  *
39  * In AIX 4.2.1 and later, the inode member to lock is i_nodelock, which
40  * was relocated to coincide with the AIX 4.2.0 position of i_rdwrlock.
41  * The AIX 4.2.1 and later inode structure does not contain a field
42  * named i_rdwrlock.
43  *
44  * We use an accident of the system header files to distinguish between
45  * AIX 4.2.0 and AIX 4.2.1 and later.  This allows this part of the code
46  * to compile on AIX 4.2.1 and later without introducing a new system
47  * type.
48  *
49  * The macro IACTIVITY is 0x0020 on AIX 4.2.0, and 0x0010 on AIX 4.2.1
50  * and later (at least through AIX 4.3.3).  If IACTIVITY is undefined,
51  * or has an unknown value, then the system header files are different
52  * than what we've seen and we'll need to take a look at them anyway to
53  * get AFS to work.
54  *
55  * The osi_Assert() statement in igetinode() checks that the lock field
56  * is at an expected offset.
57  */
58
59 #if IACTIVITY == 0x0020         /* in <jfs/inode.h> on AIX 4.2.0 */
60 #define afs_inode_lock  i_rdwrlock
61 #endif
62
63 #if IACTIVITY == 0x0010         /* in <jfs/inode.h> on AIX 4.2.1 and later */
64 #define afs_inode_lock  i_nodelock
65 #endif
66
67 #define IREAD_LOCK(ip)          simple_lock(&((ip)->afs_inode_lock))
68 #define IREAD_UNLOCK(ip)        simple_unlock(&((ip)->afs_inode_lock))
69 #define IWRITE_LOCK(ip)         simple_lock(&((ip)->afs_inode_lock))
70 #define IWRITE_UNLOCK(ip)       simple_unlock(&((ip)->afs_inode_lock))
71
72 #define SYSENT(name, arglist, decls)                    \
73 name decls                                              \
74 {                                                       \
75         lock_t lockt;                                   \
76         int rval1 = 0;                                  \
77         label_t jmpbuf;                                 \
78         int rc;                                         \
79                                                         \
80                                                         \
81         setuerror(0);                                   \
82                                                         \
83         if ((rc = setjmpx(&jmpbuf)) == 0) {             \
84                 rval1 = afs_syscall_ ## name arglist;   \
85                 clrjmpx(&jmpbuf);                       \
86         } else  {                                       \
87                 if (rc != EINTR) {                      \
88                         longjmpx(rc);                   \
89                 }                                       \
90                 setuerror(rc);                          \
91         }                                               \
92                                                         \
93                                                         \
94         return(getuerror() ? -1 : rval1);               \
95 }                                                       \
96 afs_syscall_ ## name decls                              \
97
98
99 /*
100  * This structure is used to pass information between devtovfs() and
101  * devtovfs_func() via vfs_search().
102  */
103
104 struct devtovfs_args {
105     dev_t dev;
106     struct vfs *ans;
107 };
108
109 /*
110  * If the given vfs matches rock->dev, set rock->ans to vfsp and return
111  * nonzero.  Otherwise return zero.
112  *
113  * (Returning nonzero causes vfs_search() to terminate the search.)
114  */
115
116 static int
117 devtovfs_func(struct vfs *vfsp, struct devtovfs_args *rock)
118 {
119     if (vfsp->vfs_mntd != NULL && vfsp->vfs_type == MNT_JFS
120         && (vfsp->vfs_flag & VFS_DEVMOUNT)) {
121         struct inode *ip = VTOIP(vfsp->vfs_mntd);
122         if (brdev(ip->i_dev) == brdev(rock->dev)) {
123             rock->ans = vfsp;
124             return 1;
125         }
126     }
127
128     return 0;
129 }
130
131 /*
132  * Return the vfs entry for the given device.
133  */
134
135 static struct vfs *
136 devtovfs(dev_t dev)
137 {
138     struct devtovfs_args a;
139
140     AFS_STATCNT(devtovfs);
141
142     a.dev = dev;
143     a.ans = NULL;
144     vfs_search(devtovfs_func, (caddr_t) &a);
145     return a.ans;
146 }
147
148 /* Keep error values around in case iget fails. UFSOpen panics when
149  * igetinode fails.
150  */
151 int IGI_error;
152 ino_t IGI_inode;
153 int IGI_nlink;
154 int IGI_mode;
155 /* get an existing inode.  Common code for iopen, iread/write, iinc/dec. */
156 /* Also used by rmt_remote to support passing of inode number from venus */
157 extern int iget();
158 extern struct vnode *filevp;
159 struct inode *
160 igetinode(dev, vfsp, inode, vpp, perror)
161      struct vfs *vfsp;
162      struct vnode **vpp;        /* vnode associated with the inode */
163      dev_t dev;
164      ino_t inode;
165      int *perror;
166 {
167     struct inode *ip;
168     register was_locked;
169     struct vfs *nvfsp = NULL;
170     int code;
171     *perror = 0;
172     *vpp = NULL;
173     AFS_STATCNT(igetinode);
174
175     /*
176      * Double check that the inode lock is at a known offset.
177      *
178      * If it isn't, then we need to reexamine our code to make
179      * sure that it is still okay.
180      */
181 #ifdef __64BIT__
182 /*      osi_Assert(offsetof(struct inode, afs_inode_lock) == 208); */
183 #else
184     osi_Assert(offsetof(struct inode, afs_inode_lock) == 128);
185 #endif
186
187     if (!vfsp && !(vfsp = devtovfs((dev_t) dev))) {
188         afs_warn("Dev=%d not mounted!!; quitting\n", dev);
189         setuerror(ENODEV);
190         ip = 0;
191         goto out;
192     }
193     if (vfsp->vfs_flag & VFS_DEVMOUNT)
194         nvfsp = vfsp;
195
196     /* Check if inode 0. This is the mount inode for the device
197      * and will panic the aix system if removed: defect 11434.
198      * No file should ever point to this inode.
199      */
200     if (inode == 0) {
201         afs_warn("Dev=%d zero inode.\n", dev);
202         setuerror(ENOENT);
203         ip = 0;
204         goto out;
205     }
206
207     ICACHE_LOCK();
208 #ifdef __64BIT__
209     if ((code = iget(dev, inode, &ip, (afs_size_t) 1, nvfsp))) {
210 #else
211     if ((code = iget(dev, inode, &ip, 1, nvfsp))) {
212 #endif
213         IGI_error = code;
214         IGI_inode = inode;
215         *perror = BAD_IGET;
216         ICACHE_UNLOCK();
217         setuerror(ENOENT);      /* Well... */
218         ip = 0;
219         goto out;
220     }
221     ICACHE_UNLOCK();
222     IREAD_LOCK(ip);
223     if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
224         IGI_error = 0;
225         IGI_inode = inode;
226         IGI_nlink = ip->i_nlink;
227         IGI_mode = ip->i_mode;
228         IREAD_UNLOCK(ip);
229         ICACHE_LOCK();
230         iput(ip, NULL);
231         ICACHE_UNLOCK();
232         setuerror(ENOENT);
233         ip = 0;
234         goto out;
235     }
236     if (vpp) {
237         if (nvfsp)
238             *vpp = ip->i_gnode.gn_vnode;
239         else
240             setuerror(iptovp(vfsp, ip, vpp));
241     }
242     IREAD_UNLOCK(ip);
243   out:
244     return ip;
245 }
246
247
248 #ifndef INODESPECIAL
249 /*
250  * `INODESPECIAL' type inodes are ones that describe volumes.  These are
251  * marked as journalled.  We would also like to journal inodes corresponding
252  * to directory information...
253  */
254 #define INODESPECIAL    0xffffffff      /* ... from ../vol/viceonode.h  */
255 #endif
256
257 SYSENT(icreate, (dev, near_inode, param1, param2, param3, param4), (long dev, long near_inode, long param1, long param2, long param3, long param4))
258 {
259     struct inode *ip, *newip, *pip;
260     register int err, rval1, rc = 0;
261     struct vnode *vp = NULL;
262     register struct vfs *vfsp;
263     struct vfs *nvfsp = NULL;
264     char error;
265     ino_t ino = near_inode;
266
267     AFS_STATCNT(afs_syscall_icreate);
268     if (!suser(&error)) {
269         setuerror(error);
270         return -1;
271     }
272
273     if ((vfsp = devtovfs((dev_t) dev)) == 0) {
274         afs_warn("Dev=%d not mounted!!; quitting\n", dev);
275         setuerror(ENODEV);
276         return -1;
277     }
278     if (vfsp->vfs_flag & VFS_DEVMOUNT)
279         nvfsp = vfsp;
280     ICACHE_LOCK();
281     rc = iget(dev, 0, &pip, 1, nvfsp);
282     if (!rc) {
283         /*
284          * this is the mount inode, and thus we should be
285          * safe putting it back.
286          */
287         iput(pip, nvfsp);
288     }
289     ICACHE_UNLOCK();
290
291     if (rc) {
292         setuerror(EINVAL);
293         return -1;
294     }
295
296     if (setuerror(dev_ialloc(pip, ino, IFREG, nvfsp, &newip)))
297         return -1;
298     newip->i_flag |= IACC | IUPD | ICHG;
299     newip->i_gid = -2;          /* Put special gid flag */
300     newip->i_vicemagic = VICEMAGIC;
301     newip->i_vicep1 = param1;
302     newip->i_vicep2 = param2;
303     newip->i_vicep3 = param3;
304     newip->i_vicep4 = param4;
305     IWRITE_UNLOCK(newip);
306     if (nvfsp) {
307         vp = newip->i_gnode.gn_vnode;
308     } else {
309         rc = iptovp(vfsp, newip, &vp);
310     }
311     setuerror(rc);
312
313     rval1 = newip->i_number;
314     if (vp) {
315         VNOP_RELE(vp);
316     }
317     return getuerror()? -1 : rval1;
318 }
319
320 SYSENT(iopen, (dev, inode, usrmod),(int dev, int inode, int usrmod))
321 {
322     struct file *fp;
323     register struct inode *ip;
324     struct vnode *vp = NULL;
325     extern struct fileops vnodefops;
326     register struct vfs *vfsp;
327     int fd;
328     char error;
329     struct ucred *credp;
330     int dummy;
331
332     AFS_STATCNT(afs_syscall_iopen);
333     if (!suser(&error)) {
334         setuerror(error);
335         return -1;
336     }
337
338     if ((vfsp = devtovfs((dev_t) dev)) == 0) {
339         afs_warn("Dev=%d not mounted!!; quitting\n", dev);
340         setuerror(ENODEV);
341         return -1;
342     }
343     ip = igetinode((dev_t) dev, vfsp, (ino_t) inode, &vp, &dummy);
344     if (getuerror())
345         return -1;
346
347     credp = crref();
348     if (setuerror
349         (ufdcreate
350          ((usrmod - FOPEN) & FMASK, &vnodefops, vp, DTYPE_VNODE, &fd,
351           credp))) {
352         crfree(credp);
353         VNOP_RELE(vp);
354         return -1;
355     }
356
357     if (setuerror(VNOP_OPEN(vp, (usrmod - FOPEN) & FMASK, 0, 0, credp))) {
358         close(fd);
359         crfree(credp);
360         return -1;
361     }
362     crfree(credp);
363     return fd;
364 }
365
366
367 /*
368  * Support for iinc() and idec() system calls--increment or decrement
369  * count on inode.
370  * Restricted to super user.
371  * Only VICEMAGIC type inodes.
372  */
373 iinc(dev, inode, inode_p1)
374 {
375
376     AFS_STATCNT(iinc);
377     return iincdec(dev, inode, inode_p1, 1);
378 }
379
380 idec(dev, inode, inode_p1)
381 {
382
383     AFS_STATCNT(idec);
384     return iincdec(dev, inode, inode_p1, -1);
385 }
386
387
388 SYSENT(iincdec, (dev, inode, inode_p1, amount),(int dev, int inode, int inode_p1, int amount))
389 {
390     register struct inode *ip;
391     char error;
392     struct vnode *vp = NULL;
393     int dummy;
394
395     AFS_STATCNT(afs_syscall_iincdec);
396     if (!suser(&error)) {
397         setuerror(error);
398         return -1;
399     }
400
401     ip = igetinode((dev_t) dev, 0, (ino_t) inode, &vp, &dummy);
402     if (getuerror()) {
403         return -1;
404     }
405     IWRITE_LOCK(ip);
406     if (ip->i_vicemagic != VICEMAGIC)
407         setuerror(EPERM);
408     else if (ip->i_vicep1 != inode_p1)
409         setuerror(ENXIO);
410     else {
411         ip->i_nlink += amount;
412         if (ip->i_nlink == 0) {
413             ip->i_vicemagic = 0;
414             ip->i_cflag &= ~CMNEW;
415         }
416         ip->i_flag |= ICHG;
417         commit(1, ip);          /* always commit */
418     }
419     IWRITE_UNLOCK(ip);
420     VNOP_RELE(vp);
421 /*
422         ICACHE_LOCK();
423         iput(ip, 0);
424         ICACHE_UNLOCK();
425 */
426     return getuerror()? -1 : 0;
427 }