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
11 * AIX inode operations
16 #include <afsconfig.h>
17 #include "afs/param.h"
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"
26 #if !defined(offsetof)
27 #include <stddef.h> /* for definition of offsetof() */
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)
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
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
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
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
55 * The osi_Assert() statement in igetinode() checks that the lock field
56 * is at an expected offset.
59 #if IACTIVITY == 0x0020 /* in <jfs/inode.h> on AIX 4.2.0 */
60 #define afs_inode_lock i_rdwrlock
63 #if IACTIVITY == 0x0010 /* in <jfs/inode.h> on AIX 4.2.1 and later */
64 #define afs_inode_lock i_nodelock
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))
72 #define SYSENT(name, arglist, decls) \
83 if ((rc = setjmpx(&jmpbuf)) == 0) { \
84 rval1 = afs_syscall_ ## name arglist; \
94 return(getuerror() ? -1 : rval1); \
96 afs_syscall_ ## name decls \
100 * This structure is used to pass information between devtovfs() and
101 * devtovfs_func() via vfs_search().
104 struct devtovfs_args {
110 * If the given vfs matches rock->dev, set rock->ans to vfsp and return
111 * nonzero. Otherwise return zero.
113 * (Returning nonzero causes vfs_search() to terminate the search.)
117 devtovfs_func(struct vfs *vfsp, struct devtovfs_args *rock)
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)) {
132 * Return the vfs entry for the given device.
138 struct devtovfs_args a;
140 AFS_STATCNT(devtovfs);
144 vfs_search(devtovfs_func, (caddr_t) &a);
148 /* Keep error values around in case iget fails. UFSOpen panics when
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 */
158 extern struct vnode *filevp;
160 igetinode(dev, vfsp, inode, vpp, perror)
162 struct vnode **vpp; /* vnode associated with the inode */
169 struct vfs *nvfsp = NULL;
173 AFS_STATCNT(igetinode);
176 * Double check that the inode lock is at a known offset.
178 * If it isn't, then we need to reexamine our code to make
179 * sure that it is still okay.
182 /* osi_Assert(offsetof(struct inode, afs_inode_lock) == 208); */
184 osi_Assert(offsetof(struct inode, afs_inode_lock) == 128);
187 if (!vfsp && !(vfsp = devtovfs((dev_t) dev))) {
188 afs_warn("Dev=%d not mounted!!; quitting\n", dev);
193 if (vfsp->vfs_flag & VFS_DEVMOUNT)
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.
201 afs_warn("Dev=%d zero inode.\n", dev);
209 if ((code = iget(dev, inode, &ip, (afs_size_t) 1, nvfsp))) {
211 if ((code = iget(dev, inode, &ip, 1, nvfsp))) {
217 setuerror(ENOENT); /* Well... */
223 if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
226 IGI_nlink = ip->i_nlink;
227 IGI_mode = ip->i_mode;
238 *vpp = ip->i_gnode.gn_vnode;
240 setuerror(iptovp(vfsp, ip, vpp));
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...
254 #define INODESPECIAL 0xffffffff /* ... from ../vol/viceonode.h */
257 SYSENT(icreate, (dev, near_inode, param1, param2, param3, param4), (long dev, long near_inode, long param1, long param2, long param3, long param4))
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;
265 ino_t ino = near_inode;
267 AFS_STATCNT(afs_syscall_icreate);
268 if (!suser(&error)) {
273 if ((vfsp = devtovfs((dev_t) dev)) == 0) {
274 afs_warn("Dev=%d not mounted!!; quitting\n", dev);
278 if (vfsp->vfs_flag & VFS_DEVMOUNT)
281 rc = iget(dev, 0, &pip, 1, nvfsp);
284 * this is the mount inode, and thus we should be
285 * safe putting it back.
296 if (setuerror(dev_ialloc(pip, ino, IFREG, nvfsp, &newip)))
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);
307 vp = newip->i_gnode.gn_vnode;
309 rc = iptovp(vfsp, newip, &vp);
313 rval1 = newip->i_number;
317 return getuerror()? -1 : rval1;
320 SYSENT(iopen, (dev, inode, usrmod),(int dev, int inode, int usrmod))
323 register struct inode *ip;
324 struct vnode *vp = NULL;
325 extern struct fileops vnodefops;
326 register struct vfs *vfsp;
332 AFS_STATCNT(afs_syscall_iopen);
333 if (!suser(&error)) {
338 if ((vfsp = devtovfs((dev_t) dev)) == 0) {
339 afs_warn("Dev=%d not mounted!!; quitting\n", dev);
343 ip = igetinode((dev_t) dev, vfsp, (ino_t) inode, &vp, &dummy);
350 ((usrmod - FOPEN) & FMASK, &vnodefops, vp, DTYPE_VNODE, &fd,
357 if (setuerror(VNOP_OPEN(vp, (usrmod - FOPEN) & FMASK, 0, 0, credp))) {
368 * Support for iinc() and idec() system calls--increment or decrement
370 * Restricted to super user.
371 * Only VICEMAGIC type inodes.
373 iinc(dev, inode, inode_p1)
377 return iincdec(dev, inode, inode_p1, 1);
380 idec(dev, inode, inode_p1)
384 return iincdec(dev, inode, inode_p1, -1);
388 SYSENT(iincdec, (dev, inode, inode_p1, amount),(int dev, int inode, int inode_p1, int amount))
390 register struct inode *ip;
392 struct vnode *vp = NULL;
395 AFS_STATCNT(afs_syscall_iincdec);
396 if (!suser(&error)) {
401 ip = igetinode((dev_t) dev, 0, (ino_t) inode, &vp, &dummy);
406 if (ip->i_vicemagic != VICEMAGIC)
408 else if (ip->i_vicep1 != inode_p1)
411 ip->i_nlink += amount;
412 if (ip->i_nlink == 0) {
414 ip->i_cflag &= ~CMNEW;
417 commit(1, ip); /* always commit */
426 return getuerror()? -1 : 0;