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)
46 register afs_int32 code;
50 struct ufsvfs *ufsvfsp;
52 AFS_STATCNT(getinode);
57 #if !defined(AFS_SUN58_ENV)
58 && !(vfsp = vfs_devsearch(dev))
60 && !(vfsp = vfs_dev2vfsp(dev))
65 ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
67 #ifdef HAVE_VFS_DQRWLOCK
68 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
70 code = (*ufs_igetp) (vfsp, inode, &ip, credp);
71 #ifdef HAVE_VFS_DQRWLOCK
72 rw_exit(&ufsvfsp->vfs_dqrwlock);
83 /* get an existing inode. Common code for iopen, iread/write, iinc/dec. */
84 igetinode(vfsp, dev, inode, ipp, credp, perror)
92 struct inode *pip, *ip;
93 extern struct osi_dev cacheDev;
94 register int code = 0;
98 AFS_STATCNT(igetinode);
100 code = getinode(vfsp, dev, inode, &ip, credp, perror);
104 rw_enter(&ip->i_contents, RW_READER);
106 if (ip->i_mode == 0) {
107 /* Not an allocated inode */
108 rw_exit(&ip->i_contents);
113 if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
115 rw_exit(&ip->i_contents);
120 /* On VFS40 systems, iput does major synchronous write action, but only
121 * when the reference count on the vnode goes to 0. Normally, Sun users
122 * don't notice this because the DNLC keep references for them, but we
123 * notice 'cause we don't. So, we make a fake dnlc entry which gets
124 * cleaned up by iget when it needs the space. */
125 if (dev != cacheDev.dev) {
127 * Don't call dnlc for the cm inodes since it's a big performance
130 #ifdef AFS_SUN510_ENV
131 dnlc_enter(ITOV(ip), "a", ITOV(ip));
133 dnlc_enter(ITOV(ip), "a", ITOV(ip), (afs_ucred_t *)0);
138 rw_exit(&ip->i_contents);
144 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp,
148 long near_inode, param1, param2, param3, param4;
152 struct inode *ip, *newip;
155 struct ufsvfs *ufsvfsp;
157 AFS_STATCNT(afs_syscall_icreate);
159 if (!afs_osi_suser(credp))
162 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
163 * This conversion is needed only for the 64 bit OS.
166 #ifdef AFS_SUN57_64BIT_ENV
167 newdev = expldev((dev32_t) dev);
172 code = getinode(0, (dev_t) newdev, 2, &ip, credp, &dummy);
177 ufsvfsp = ip->i_ufsvfs;
178 rw_enter(&ip->i_rwlock, RW_WRITER);
179 #ifdef HAVE_VFS_DQRWLOCK
180 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
182 rw_enter(&ip->i_contents, RW_WRITER);
183 code = (*ufs_iallocp) (ip, near_inode, 0, &newip, credp);
184 AFS_ITIMES_NOLOCK(ip);
185 rw_exit(&ip->i_contents);
186 #ifdef HAVE_VFS_DQRWLOCK
187 rw_exit(&ufsvfsp->vfs_dqrwlock);
189 rw_exit(&ip->i_rwlock);
195 rw_enter(&newip->i_contents, RW_WRITER);
196 newip->i_flag |= IACC | IUPD | ICHG;
198 #if defined(AFS_SUN56_ENV)
199 newip->i_vicemagic = VICEMAGIC;
205 newip->i_mode = IFREG;
206 #ifdef AFS_SUN510_ENV
207 newip->i_vnode->v_type = VREG;
209 newip->i_vnode.v_type = VREG;
212 newip->i_vicep1 = param1;
213 if (param2 == 0x1fffffff /*INODESPECIAL*/) {
214 newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
215 newip->i_vicep3 = param3;
218 (((param2 >> 16) & 0x1f) << 27) +
219 (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
220 newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
222 #ifdef AFS_SUN57_64BIT_ENV
223 rvp->r_vals = newip->i_number;
225 rvp->r_val1 = newip->i_number;
229 * We're being conservative and sync to the disk
232 (*ufs_iupdatp) (newip, 1);
233 AFS_ITIMES_NOLOCK(newip);
234 rw_exit(&newip->i_contents);
235 VN_RELE(ITOV(newip));
239 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
247 struct vnode *vp = NULL;
253 AFS_STATCNT(afs_syscall_iopen);
255 if (!afs_osi_suser(credp))
258 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
259 * This conversion is needed only for the 64 bit OS.
262 #ifdef AFS_SUN57_64BIT_ENV
263 newdev = expldev((dev32_t) dev);
268 code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
272 code = falloc((struct vnode *)NULL, FWRITE | FREAD, &fp, &fd);
274 rw_enter(&ip->i_contents, RW_READER);
276 rw_exit(&ip->i_contents);
281 /* fp->f_count, f_audit_data are set by falloc */
282 fp->f_vnode = ITOV(ip);
284 fp->f_flag = (usrmod + 1) & (FMASK);
286 /* fp->f_count, f_msgcount are set by falloc */
288 /* fp->f_offset zeroed by falloc */
289 /* f_cred set by falloc */
291 * falloc returns the fp write locked
293 mutex_exit(&fp->f_tlock);
295 * XXX We should set the fp to null since we don't need it in the icalls
298 #ifdef AFS_SUN57_64BIT_ENV
309 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
312 int inode, inode_p1, amount;
317 register afs_int32 code;
320 if (!afs_osi_suser(credp))
323 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
324 * This conversion is needed only for the 64 bit OS.
327 #ifdef AFS_SUN57_64BIT_ENV
328 newdev = expldev((dev32_t) dev);
333 code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
337 if (!IS_VICEMAGIC(ip)) {
339 rw_enter(&ip->i_contents, RW_READER);
341 rw_exit(&ip->i_contents);
344 rw_enter(&ip->i_contents, RW_WRITER);
345 ip->i_nlink += amount;
346 if (ip->i_nlink == 0) {
347 /* remove the "a" name added by igetinode so that the space is reclaimed. */
348 dnlc_remove(ITOV(ip), "a");
352 /* We may want to force the inode to the disk in case of crashes, other references, etc. */
354 (*ufs_iupdatp) (ip, 1);
355 AFS_ITIMES_NOLOCK(ip);
356 rw_exit(&ip->i_contents);