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"
22 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs/osi_inode.h"
25 #include "afs/afs_stats.h" /* statistics stuff */
27 extern int (*ufs_iallocp) (), (*ufs_iupdatp) (), (*ufs_igetp) (),
28 (*ufs_itimes_nolockp) ();
30 #define AFS_ITIMES(ip) { \
31 mutex_enter(&(ip)->i_tlock); \
32 (*ufs_itimes_nolockp)(ip); \
33 mutex_exit(&(ip)->i_tlock); \
36 #define AFS_ITIMES_NOLOCK(ip) \
37 (*ufs_itimes_nolockp)(ip);
39 getinode(vfsp, dev, inode, ipp, credp, perror)
41 struct AFS_UCRED *credp;
48 register afs_int32 code;
52 struct ufsvfs *ufsvfsp;
54 AFS_STATCNT(getinode);
59 #if !defined(AFS_SUN58_ENV)
60 && !(vfsp = vfs_devsearch(dev))
62 && !(vfsp = vfs_dev2vfsp(dev))
67 ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
69 #ifdef HAVE_VFS_DQRWLOCK
70 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
72 code = (*ufs_igetp) (vfsp, inode, &ip, credp);
73 #ifdef HAVE_VFS_DQRWLOCK
74 rw_exit(&ufsvfsp->vfs_dqrwlock);
85 /* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
86 igetinode(vfsp, dev, inode, ipp, credp, perror)
87 struct AFS_UCRED *credp;
94 struct inode *pip, *ip;
95 extern struct osi_dev cacheDev;
96 register int code = 0;
100 AFS_STATCNT(igetinode);
102 code = getinode(vfsp, dev, inode, &ip, credp, perror);
106 rw_enter(&ip->i_contents, RW_READER);
108 if (ip->i_mode == 0) {
109 /* Not an allocated inode */
110 rw_exit(&ip->i_contents);
115 if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
117 rw_exit(&ip->i_contents);
122 /* On VFS40 systems, iput does major synchronous write action, but only
123 * when the reference count on the vnode goes to 0. Normally, Sun users
124 * don't notice this because the DNLC keep references for them, but we
125 * notice 'cause we don't. So, we make a fake dnlc entry which gets
126 * cleaned up by iget when it needs the space. */
127 if (dev != cacheDev.dev) {
129 * Don't call dnlc for the cm inodes since it's a big performance
132 dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *)0);
136 rw_exit(&ip->i_contents);
142 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp,
145 struct AFS_UCRED *credp;
146 long near_inode, param1, param2, param3, param4;
150 struct inode *ip, *newip;
153 struct ufsvfs *ufsvfsp;
155 AFS_STATCNT(afs_syscall_icreate);
157 if (!afs_suser(credp))
160 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
161 * This conversion is needed only for the 64 bit OS.
164 #ifdef AFS_SUN57_64BIT_ENV
165 newdev = expldev((dev32_t) dev);
170 code = getinode(0, (dev_t) newdev, 2, &ip, credp, &dummy);
175 ufsvfsp = ip->i_ufsvfs;
176 rw_enter(&ip->i_rwlock, RW_WRITER);
177 #ifdef HAVE_VFS_DQRWLOCK
178 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
180 rw_enter(&ip->i_contents, RW_WRITER);
181 code = (*ufs_iallocp) (ip, near_inode, 0, &newip, credp);
182 AFS_ITIMES_NOLOCK(ip);
183 rw_exit(&ip->i_contents);
184 #ifdef HAVE_VFS_DQRWLOCK
185 rw_exit(&ufsvfsp->vfs_dqrwlock);
187 rw_exit(&ip->i_rwlock);
193 rw_enter(&newip->i_contents, RW_WRITER);
194 newip->i_flag |= IACC | IUPD | ICHG;
196 #if defined(AFS_SUN56_ENV)
197 newip->i_vicemagic = VICEMAGIC;
203 newip->i_mode = IFREG;
204 newip->i_vnode.v_type = VREG;
206 newip->i_vicep1 = param1;
207 if (param2 == 0x1fffffff /*INODESPECIAL*/) {
208 newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
209 newip->i_vicep3 = param3;
212 (((param2 >> 16) & 0x1f) << 27) +
213 (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
214 newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
216 #ifdef AFS_SUN57_64BIT_ENV
217 rvp->r_vals = newip->i_number;
219 rvp->r_val1 = newip->i_number;
223 * We're being conservative and sync to the disk
226 (*ufs_iupdatp) (newip, 1);
227 AFS_ITIMES_NOLOCK(newip);
228 rw_exit(&newip->i_contents);
229 VN_RELE(ITOV(newip));
233 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
235 struct AFS_UCRED *credp;
241 struct vnode *vp = NULL;
247 AFS_STATCNT(afs_syscall_iopen);
249 if (!afs_suser(credp))
252 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
253 * This conversion is needed only for the 64 bit OS.
256 #ifdef AFS_SUN57_64BIT_ENV
257 newdev = expldev((dev32_t) dev);
262 code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
266 code = falloc((struct vnode *)NULL, FWRITE | FREAD, &fp, &fd);
268 rw_enter(&ip->i_contents, RW_READER);
270 rw_exit(&ip->i_contents);
275 /* fp->f_count, f_audit_data are set by falloc */
276 fp->f_vnode = ITOV(ip);
278 fp->f_flag = (usrmod + 1) & (FMASK);
280 /* fp->f_count, f_msgcount are set by falloc */
282 /* fp->f_offset zeroed by falloc */
283 /* f_cred set by falloc */
285 * falloc returns the fp write locked
287 mutex_exit(&fp->f_tlock);
289 * XXX We should set the fp to null since we don't need it in the icalls
292 #ifdef AFS_SUN57_64BIT_ENV
303 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
305 struct AFS_UCRED *credp;
306 int inode, inode_p1, amount;
311 register afs_int32 code;
314 if (!afs_suser(credp))
317 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
318 * This conversion is needed only for the 64 bit OS.
321 #ifdef AFS_SUN57_64BIT_ENV
322 newdev = expldev((dev32_t) dev);
327 code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
331 if (!IS_VICEMAGIC(ip)) {
333 rw_enter(&ip->i_contents, RW_READER);
335 rw_exit(&ip->i_contents);
338 rw_enter(&ip->i_contents, RW_WRITER);
339 ip->i_nlink += amount;
340 if (ip->i_nlink == 0) {
341 /* remove the "a" name added by igetinode so that the space is reclaimed. */
342 dnlc_remove(ITOV(ip), "a");
346 /* We may want to force the inode to the disk in case of crashes, other references, etc. */
348 (*ufs_iupdatp) (ip, 1);
349 AFS_ITIMES_NOLOCK(ip);
350 rw_exit(&ip->i_contents);