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 int err
, rval1
, rc
= 0;
261 struct vnode
*vp
= NULL
;
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
))
324 struct vnode
*vp
= NULL
;
325 extern struct fileops vnodefops
;
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
))
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;