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"
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 */
25 extern int (*ufs_iallocp
) (), (*ufs_iupdatp
) (), (*ufs_igetp
) (),
26 (*ufs_itimes_nolockp
) ();
28 #define AFS_ITIMES(ip) { \
29 mutex_enter(&(ip)->i_tlock); \
30 (*ufs_itimes_nolockp)(ip); \
31 mutex_exit(&(ip)->i_tlock); \
34 #define AFS_ITIMES_NOLOCK(ip) \
35 (*ufs_itimes_nolockp)(ip);
37 getinode(vfsp
, dev
, inode
, ipp
, credp
, perror
)
50 struct ufsvfs
*ufsvfsp
;
52 AFS_STATCNT(getinode
);
56 if (!vfsp
&& !(vfsp
= vfs_dev2vfsp(dev
))) {
59 ufsvfsp
= (struct ufsvfs
*)vfsp
->vfs_data
;
61 #ifdef HAVE_VFS_DQRWLOCK
62 rw_enter(&ufsvfsp
->vfs_dqrwlock
, RW_READER
);
64 code
= (*ufs_igetp
) (vfsp
, inode
, &ip
, credp
);
65 #ifdef HAVE_VFS_DQRWLOCK
66 rw_exit(&ufsvfsp
->vfs_dqrwlock
);
77 /* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
78 igetinode(vfsp
, dev
, inode
, ipp
, credp
, perror
)
86 struct inode
*pip
, *ip
;
87 extern struct osi_dev cacheDev
;
92 AFS_STATCNT(igetinode
);
94 code
= getinode(vfsp
, dev
, inode
, &ip
, credp
, perror
);
98 rw_enter(&ip
->i_contents
, RW_READER
);
100 if (ip
->i_mode
== 0) {
101 /* Not an allocated inode */
102 rw_exit(&ip
->i_contents
);
107 if (ip
->i_nlink
== 0 || (ip
->i_mode
& IFMT
) != IFREG
) {
109 rw_exit(&ip
->i_contents
);
114 /* On VFS40 systems, iput does major synchronous write action, but only
115 * when the reference count on the vnode goes to 0. Normally, Sun users
116 * don't notice this because the DNLC keep references for them, but we
117 * notice 'cause we don't. So, we make a fake dnlc entry which gets
118 * cleaned up by iget when it needs the space. */
119 if (dev
!= cacheDev
.dev
) {
121 * Don't call dnlc for the cm inodes since it's a big performance
124 #ifdef AFS_SUN510_ENV
125 dnlc_enter(ITOV(ip
), "a", ITOV(ip
));
127 dnlc_enter(ITOV(ip
), "a", ITOV(ip
), (afs_ucred_t
*)0);
132 rw_exit(&ip
->i_contents
);
138 afs_syscall_icreate(dev
, near_inode
, param1
, param2
, param3
, param4
, rvp
,
142 long near_inode
, param1
, param2
, param3
, param4
;
146 struct inode
*ip
, *newip
;
149 struct ufsvfs
*ufsvfsp
;
151 AFS_STATCNT(afs_syscall_icreate
);
153 if (!afs_osi_suser(credp
))
156 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
157 * This conversion is needed only for the 64 bit OS.
160 #ifdef AFS_SUN5_64BIT_ENV
161 newdev
= expldev((dev32_t
) dev
);
166 code
= getinode(0, (dev_t
) newdev
, 2, &ip
, credp
, &dummy
);
171 ufsvfsp
= ip
->i_ufsvfs
;
172 rw_enter(&ip
->i_rwlock
, RW_WRITER
);
173 #ifdef HAVE_VFS_DQRWLOCK
174 rw_enter(&ufsvfsp
->vfs_dqrwlock
, RW_READER
);
176 rw_enter(&ip
->i_contents
, RW_WRITER
);
177 code
= (*ufs_iallocp
) (ip
, near_inode
, 0, &newip
, credp
);
178 AFS_ITIMES_NOLOCK(ip
);
179 rw_exit(&ip
->i_contents
);
180 #ifdef HAVE_VFS_DQRWLOCK
181 rw_exit(&ufsvfsp
->vfs_dqrwlock
);
183 rw_exit(&ip
->i_rwlock
);
189 rw_enter(&newip
->i_contents
, RW_WRITER
);
190 newip
->i_flag
|= IACC
| IUPD
| ICHG
;
192 newip
->i_vicemagic
= VICEMAGIC
;
194 newip
->i_mode
= IFREG
;
195 #ifdef AFS_SUN510_ENV
196 newip
->i_vnode
->v_type
= VREG
;
198 newip
->i_vnode
.v_type
= VREG
;
201 newip
->i_vicep1
= param1
;
202 if (param2
== 0x1fffffff /*INODESPECIAL*/) {
203 newip
->i_vicep2
= ((0x1fffffff << 3) + (param4
& 0x3));
204 newip
->i_vicep3
= param3
;
207 (((param2
>> 16) & 0x1f) << 27) +
208 (((param4
>> 16) & 0x1f) << 22) + (param3
& 0x3fffff);
209 newip
->i_vicep3
= ((param4
<< 16) + (param2
& 0xffff));
211 #ifdef AFS_SUN5_64BIT_ENV
212 rvp
->r_vals
= newip
->i_number
;
214 rvp
->r_val1
= newip
->i_number
;
218 * We're being conservative and sync to the disk
221 (*ufs_iupdatp
) (newip
, 1);
222 AFS_ITIMES_NOLOCK(newip
);
223 rw_exit(&newip
->i_contents
);
224 VN_RELE(ITOV(newip
));
228 afs_syscall_iopen(dev
, inode
, usrmod
, rvp
, credp
)
236 struct vnode
*vp
= NULL
;
242 AFS_STATCNT(afs_syscall_iopen
);
244 if (!afs_osi_suser(credp
))
247 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
248 * This conversion is needed only for the 64 bit OS.
251 #ifdef AFS_SUN5_64BIT_ENV
252 newdev
= expldev((dev32_t
) dev
);
257 code
= igetinode(0, (dev_t
) newdev
, (ino_t
) inode
, &ip
, credp
, &dummy
);
261 code
= falloc(NULL
, FWRITE
| FREAD
, &fp
, &fd
);
263 rw_enter(&ip
->i_contents
, RW_READER
);
265 rw_exit(&ip
->i_contents
);
270 /* fp->f_count, f_audit_data are set by falloc */
271 fp
->f_vnode
= ITOV(ip
);
273 fp
->f_flag
= (usrmod
+ 1) & (FMASK
);
275 /* fp->f_count, f_msgcount are set by falloc */
277 /* fp->f_offset zeroed by falloc */
278 /* f_cred set by falloc */
280 * falloc returns the fp write locked
282 mutex_exit(&fp
->f_tlock
);
284 * XXX We should set the fp to null since we don't need it in the icalls
288 /* rvp->r_val{1,2} are really members into a union and are re-extracted
289 * later by solaris. If we're not 64-bit, they appear to just be the same
290 * thing, but on 64-bit they point to two different 32-bit locations that
291 * make up one 64-bit int; so on 64-bit big-endian we need to set the
293 #if defined(AFS_SUN5_64BIT_ENV) && !defined(AFSLITTLE_ENDIAN)
304 afs_syscall_iincdec(dev
, inode
, inode_p1
, amount
, rvp
, credp
)
307 int inode
, inode_p1
, amount
;
315 if (!afs_osi_suser(credp
))
318 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
319 * This conversion is needed only for the 64 bit OS.
322 #ifdef AFS_SUN5_64BIT_ENV
323 newdev
= expldev((dev32_t
) dev
);
328 code
= igetinode(0, (dev_t
) newdev
, (ino_t
) inode
, &ip
, credp
, &dummy
);
332 if (!IS_VICEMAGIC(ip
)) {
334 rw_enter(&ip
->i_contents
, RW_READER
);
336 rw_exit(&ip
->i_contents
);
339 rw_enter(&ip
->i_contents
, RW_WRITER
);
340 ip
->i_nlink
+= amount
;
341 if (ip
->i_nlink
== 0) {
342 /* remove the "a" name added by igetinode so that the space is reclaimed. */
343 dnlc_remove(ITOV(ip
), "a");
347 /* We may want to force the inode to the disk in case of crashes, other references, etc. */
349 (*ufs_iupdatp
) (ip
, 1);
350 AFS_ITIMES_NOLOCK(ip
);
351 rw_exit(&ip
->i_contents
);