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 "../afs/param.h" /* Should be always first */
17 #include "../afs/sysincludes.h" /* Standard vendor system headers */
18 #include "../afs/afsincludes.h" /* Afs-based standard headers */
19 #include "../afs/osi_inode.h"
20 #include "../afs/afs_stats.h" /* statistics stuff */
22 extern int (*ufs_iallocp)(), (*ufs_iupdatp)(), (*ufs_igetp)(),
23 (*ufs_itimes_nolockp)();
25 #define AFS_ITIMES(ip) { \
26 mutex_enter(&(ip)->i_tlock); \
27 (*ufs_itimes_nolockp)(ip); \
28 mutex_exit(&(ip)->i_tlock); \
31 getinode(vfsp, dev, inode, ipp, credp,perror)
33 struct AFS_UCRED *credp;
40 register afs_int32 code;
44 struct ufsvfs *ufsvfsp;
46 AFS_STATCNT(getinode);
51 #if !defined(AFS_SUN58_ENV)
52 && !(vfsp = vfs_devsearch(dev))
54 && !(vfsp = vfs_dev2vfsp(dev))
59 ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
61 #if defined(AFS_SUN57_ENV)
62 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
64 code = (*ufs_igetp)(vfsp, inode, &ip, credp);
65 #if defined(AFS_SUN57_ENV)
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)
79 struct AFS_UCRED *credp;
86 struct inode *pip, *ip;
87 extern struct osi_dev cacheDev;
88 register int code = 0;
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 */
103 rw_exit(&ip->i_contents);
108 if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
110 rw_exit(&ip->i_contents);
115 /* On VFS40 systems, iput does major synchronous write action, but only
116 when the reference count on the vnode goes to 0. Normally, Sun users
117 don't notice this because the DNLC keep references for them, but we
118 notice 'cause we don't. So, we make a fake dnlc entry which gets
119 cleaned up by iget when it needs the space. */
120 if (dev != cacheDev.dev) {
122 * Don't call dnlc for the cm inodes since it's a big performance
125 dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *) 0);
129 rw_exit(&ip->i_contents);
135 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
137 struct AFS_UCRED *credp;
138 long near_inode, param1, param2, param3, param4;
142 struct inode *ip, *newip;
145 struct ufsvfs *ufsvfsp;
147 AFS_STATCNT(afs_syscall_icreate);
149 if (!afs_suser(credp))
152 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
153 * This conversion is needed only for the 64 bit OS.
156 #ifdef AFS_SUN57_64BIT_ENV
157 newdev = expldev( (dev32_t) dev);
162 code = getinode(0, (dev_t)newdev, 2, &ip, credp,&dummy);
167 ufsvfsp = ip->i_ufsvfs;
168 rw_enter(&ip->i_rwlock, RW_WRITER);
169 #if defined(AFS_SUN57_ENV)
170 rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
172 rw_enter(&ip->i_contents, RW_WRITER);
173 code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp);
174 #if defined(AFS_SUN57_ENV)
175 rw_exit(&ufsvfsp->vfs_dqrwlock);
177 rw_exit(&ip->i_rwlock);
180 rw_exit(&ip->i_contents);
186 rw_enter(&newip->i_contents, RW_WRITER);
187 mutex_enter(&newip->i_tlock);
188 newip->i_flag |= IACC|IUPD|ICHG;
189 mutex_exit(&newip->i_tlock);
192 #if defined(AFS_SUN56_ENV)
193 newip->i_vicemagic = VICEMAGIC;
199 newip->i_mode = IFREG;
200 newip->i_vnode.v_type = VREG;
202 newip->i_vicep1 = param1;
203 if (param2 == 0x1fffffff/*INODESPECIAL*/) {
204 newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
205 newip->i_vicep3 = param3;
207 newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
208 (((param4 >> 16) & 0x1f) << 22) +
210 newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
212 #ifdef AFS_SUN57_64BIT_ENV
213 rvp->r_vals = newip->i_number;
215 rvp->r_val1 = newip->i_number;
219 * We're being conservative and sync to the disk
222 (*ufs_iupdatp)(newip, 1);
224 rw_exit(&newip->i_contents);
225 VN_RELE(ITOV(newip));
229 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
231 struct AFS_UCRED *credp;
237 struct vnode *vp = (struct vnode *)0;
243 AFS_STATCNT(afs_syscall_iopen);
245 if (!afs_suser(credp))
248 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
249 * This conversion is needed only for the 64 bit OS.
252 #ifdef AFS_SUN57_64BIT_ENV
253 newdev = expldev( (dev32_t) dev);
258 code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
262 code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
264 rw_enter(&ip->i_contents, RW_READER);
266 rw_exit(&ip->i_contents);
271 /* fp->f_count, f_audit_data are set by falloc */
272 fp->f_vnode = ITOV(ip);
274 fp->f_flag = (usrmod+1) & (FMASK);
276 /* fp->f_count, f_msgcount are set by falloc */
278 /* fp->f_offset zeroed by falloc */
279 /* f_cred set by falloc */
281 * falloc returns the fp write locked
283 mutex_exit(&fp->f_tlock);
285 * XXX We should set the fp to null since we don't need it in the icalls
288 #ifdef AFS_SUN57_64BIT_ENV
299 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
301 struct AFS_UCRED *credp;
302 int inode, inode_p1, amount;
307 register afs_int32 code;
310 if (!afs_suser(credp))
313 /** Code to convert a 32 bit dev_t into a 64 bit dev_t
314 * This conversion is needed only for the 64 bit OS.
317 #ifdef AFS_SUN57_64BIT_ENV
318 newdev = expldev( (dev32_t) dev);
323 code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
327 if (!IS_VICEMAGIC(ip)) {
329 rw_enter(&ip->i_contents, RW_READER);
331 rw_exit(&ip->i_contents);
334 rw_enter(&ip->i_contents, RW_WRITER);
335 ip->i_nlink += amount;
336 if (ip->i_nlink == 0) {
337 /* remove the "a" name added by igetinode so that the space is reclaimed. */
338 dnlc_remove(ITOV(ip), "a");
341 mutex_enter(&ip->i_tlock);
343 mutex_exit(&ip->i_tlock);
344 /* We may want to force the inode to the disk in case of crashes, other references, etc. */
346 (*ufs_iupdatp)(ip, 1);
348 rw_exit(&ip->i_contents);