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 * SOLARIS inode operations
16 #include <afsconfig.h>
17 #include "../afs/param.h"
21 #include "../afs/sysincludes.h" /* Standard vendor system headers */
22 #include "../afs/afsincludes.h" /* Afs-based standard headers */
23 #include "../afs/osi_inode.h"
24 #include "../afs/afs_stats.h" /* statistics stuff */
26 extern int (*ufs_iallocp)(), (*ufs_iupdatp)(), (*ufs_igetp)(),
27 (*ufs_itimes_nolockp)();
29 #define AFS_ITIMES(ip) { \
30 mutex_enter(&(ip)->i_tlock); \
31 (*ufs_itimes_nolockp)(ip); \
32 mutex_exit(&(ip)->i_tlock); \
35 #define AFS_ITIMES_NOLOCK(ip) \
36 (*ufs_itimes_nolockp)(ip);
38 getinode(vfsp, dev, inode, ipp, credp,perror)
40 struct AFS_UCRED *credp;
47 register afs_int32 code;
51 struct ufsvfs *ufsvfsp;
53 AFS_STATCNT(getinode);
58 #if !defined(AFS_SUN58_ENV)
59 && !(vfsp = vfs_devsearch(dev))
61 && !(vfsp = vfs_dev2vfsp(dev))
66 ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
68 #ifdef HAVE_VFS_DQRWLOCK
69 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
71 code = (*ufs_igetp)(vfsp, inode, &ip, credp);
72 #ifdef HAVE_VFS_DQRWLOCK
73 rw_exit(&ufsvfsp->vfs_dqrwlock);
84 /* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
85 igetinode(vfsp, dev, inode, ipp, credp,perror)
86 struct AFS_UCRED *credp;
93 struct inode *pip, *ip;
94 extern struct osi_dev cacheDev;
95 register int code = 0;
99 AFS_STATCNT(igetinode);
101 code = getinode(vfsp, dev, inode, &ip, credp,perror);
105 rw_enter(&ip->i_contents, RW_READER);
107 if (ip->i_mode == 0) {
108 /* Not an allocated inode */
109 rw_exit(&ip->i_contents);
114 if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
116 rw_exit(&ip->i_contents);
121 /* On VFS40 systems, iput does major synchronous write action, but only
122 when the reference count on the vnode goes to 0. Normally, Sun users
123 don't notice this because the DNLC keep references for them, but we
124 notice 'cause we don't. So, we make a fake dnlc entry which gets
125 cleaned up by iget when it needs the space. */
126 if (dev != cacheDev.dev) {
128 * Don't call dnlc for the cm inodes since it's a big performance
131 dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *) 0);
135 rw_exit(&ip->i_contents);
141 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
143 struct AFS_UCRED *credp;
144 long near_inode, param1, param2, param3, param4;
148 struct inode *ip, *newip;
151 struct ufsvfs *ufsvfsp;
153 AFS_STATCNT(afs_syscall_icreate);
155 if (!afs_suser(credp))
158 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
159 * This conversion is needed only for the 64 bit OS.
162 #ifdef AFS_SUN57_64BIT_ENV
163 newdev = expldev( (dev32_t) dev);
168 code = getinode(0, (dev_t)newdev, 2, &ip, credp,&dummy);
173 ufsvfsp = ip->i_ufsvfs;
174 rw_enter(&ip->i_rwlock, RW_WRITER);
175 #ifdef HAVE_VFS_DQRWLOCK
176 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
178 rw_enter(&ip->i_contents, RW_WRITER);
179 code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp);
180 AFS_ITIMES_NOLOCK(ip);
181 rw_exit(&ip->i_contents);
182 #ifdef HAVE_VFS_DQRWLOCK
183 rw_exit(&ufsvfsp->vfs_dqrwlock);
185 rw_exit(&ip->i_rwlock);
191 rw_enter(&newip->i_contents, RW_WRITER);
192 newip->i_flag |= IACC|IUPD|ICHG;
194 #if defined(AFS_SUN56_ENV)
195 newip->i_vicemagic = VICEMAGIC;
201 newip->i_mode = IFREG;
202 newip->i_vnode.v_type = VREG;
204 newip->i_vicep1 = param1;
205 if (param2 == 0x1fffffff/*INODESPECIAL*/) {
206 newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
207 newip->i_vicep3 = param3;
209 newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
210 (((param4 >> 16) & 0x1f) << 22) +
212 newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
214 #ifdef AFS_SUN57_64BIT_ENV
215 rvp->r_vals = newip->i_number;
217 rvp->r_val1 = newip->i_number;
221 * We're being conservative and sync to the disk
224 (*ufs_iupdatp)(newip, 1);
225 AFS_ITIMES_NOLOCK(newip);
226 rw_exit(&newip->i_contents);
227 VN_RELE(ITOV(newip));
231 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
233 struct AFS_UCRED *credp;
239 struct vnode *vp = NULL;
245 AFS_STATCNT(afs_syscall_iopen);
247 if (!afs_suser(credp))
250 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
251 * This conversion is needed only for the 64 bit OS.
254 #ifdef AFS_SUN57_64BIT_ENV
255 newdev = expldev( (dev32_t) dev);
260 code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
264 code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
266 rw_enter(&ip->i_contents, RW_READER);
268 rw_exit(&ip->i_contents);
273 /* fp->f_count, f_audit_data are set by falloc */
274 fp->f_vnode = ITOV(ip);
276 fp->f_flag = (usrmod+1) & (FMASK);
278 /* fp->f_count, f_msgcount are set by falloc */
280 /* fp->f_offset zeroed by falloc */
281 /* f_cred set by falloc */
283 * falloc returns the fp write locked
285 mutex_exit(&fp->f_tlock);
287 * XXX We should set the fp to null since we don't need it in the icalls
290 #ifdef AFS_SUN57_64BIT_ENV
301 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
303 struct AFS_UCRED *credp;
304 int inode, inode_p1, amount;
309 register afs_int32 code;
312 if (!afs_suser(credp))
315 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
316 * This conversion is needed only for the 64 bit OS.
319 #ifdef AFS_SUN57_64BIT_ENV
320 newdev = expldev( (dev32_t) dev);
325 code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
329 if (!IS_VICEMAGIC(ip)) {
331 rw_enter(&ip->i_contents, RW_READER);
333 rw_exit(&ip->i_contents);
336 rw_enter(&ip->i_contents, RW_WRITER);
337 ip->i_nlink += amount;
338 if (ip->i_nlink == 0) {
339 /* remove the "a" name added by igetinode so that the space is reclaimed. */
340 dnlc_remove(ITOV(ip), "a");
344 /* We may want to force the inode to the disk in case of crashes, other references, etc. */
346 (*ufs_iupdatp)(ip, 1);
347 AFS_ITIMES_NOLOCK(ip);
348 rw_exit(&ip->i_contents);