vfs-dqrwlock-doesnt-exist-before-solaris7-20010420
[openafs.git] / src / afs / SOLARIS / osi_inode.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * SOLARIS inode operations
12  *
13  * Implements:
14  *
15  */
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 */
21
22 extern int (*ufs_iallocp)(), (*ufs_iupdatp)(), (*ufs_igetp)(),
23            (*ufs_itimes_nolockp)();
24
25 #define AFS_ITIMES(ip) { \
26         mutex_enter(&(ip)->i_tlock); \
27         (*ufs_itimes_nolockp)(ip); \
28         mutex_exit(&(ip)->i_tlock); \
29 }
30
31 getinode(vfsp, dev, inode, ipp, credp,perror)
32      struct vfs *vfsp;
33      struct AFS_UCRED *credp;
34      struct inode **ipp;
35      dev_t dev;
36      ino_t inode;
37      int *perror;
38 {
39     struct inode *ip;
40     register afs_int32 code;
41     struct vnode *vp;
42     struct fs *fs;
43     struct inode *pip;
44     struct ufsvfs *ufsvfsp;
45     
46     AFS_STATCNT(getinode);
47     
48     *perror = 0;
49     
50     if (!vfsp 
51 #if !defined(AFS_SUN58_ENV)
52         && !(vfsp = vfs_devsearch(dev))
53 #else
54         && !(vfsp = vfs_dev2vfsp(dev))
55 #endif
56         ) {
57         return (ENODEV);
58     }
59     ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
60
61 #if defined(AFS_SUN57_ENV)
62     rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
63 #endif
64     code = (*ufs_igetp)(vfsp, inode, &ip, credp);
65 #if defined(AFS_SUN57_ENV)
66     rw_exit(&ufsvfsp->vfs_dqrwlock);
67 #endif
68
69     if (code) {
70         *perror = BAD_IGET;
71         return code;
72     }
73     *ipp = ip;
74     return code;
75 }
76
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;
80      struct inode **ipp;
81      struct vfs *vfsp;
82      dev_t dev;
83      ino_t inode;
84      int *perror;
85 {
86     struct inode *pip, *ip;
87     extern struct osi_dev cacheDev;
88     register int code = 0;
89     
90     *perror = 0;
91     
92     AFS_STATCNT(igetinode);
93     
94     code = getinode(vfsp, dev, inode, &ip, credp,perror);
95     if (code) 
96         return code;
97     
98     rw_enter(&ip->i_contents, RW_READER);
99     
100     if (ip->i_mode == 0) {
101         /* Not an allocated inode */
102         AFS_ITIMES(ip);
103         rw_exit(&ip->i_contents);
104         VN_RELE(ITOV(ip));
105         return (ENOENT);
106     }
107     
108     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
109         AFS_ITIMES(ip);
110         rw_exit(&ip->i_contents);
111         VN_RELE(ITOV(ip));
112         return (ENOENT);
113     }
114     
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) {
121         /* 
122          * Don't call dnlc for the cm inodes since it's a big performance 
123          * penalty there!
124          */
125         dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *) 0);
126     }
127     
128     *ipp = ip;
129     rw_exit(&ip->i_contents);
130     return (code);
131 }
132
133 int CrSync = 1;
134
135 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
136      rval_t *rvp;
137      struct AFS_UCRED *credp;
138      long near_inode, param1, param2, param3, param4;
139      dev_t dev;
140 {
141     int dummy, err=0;
142     struct inode *ip, *newip;
143     register int code;
144     dev_t newdev;
145     struct ufsvfs *ufsvfsp;
146
147     AFS_STATCNT(afs_syscall_icreate);
148     
149     if (!afs_suser(credp))
150         return (EPERM);
151     
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.
154       */
155     
156 #ifdef AFS_SUN57_64BIT_ENV
157     newdev = expldev( (dev32_t) dev);
158 #else
159     newdev = dev;
160 #endif
161
162     code = getinode(0, (dev_t)newdev, 2, &ip, credp,&dummy);
163     if (code) {
164         return (code);
165     }
166
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);
171 #endif
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);
176 #endif
177     rw_exit(&ip->i_rwlock);
178
179     AFS_ITIMES(ip);
180     rw_exit(&ip->i_contents);
181     VN_RELE(ITOV(ip));
182
183     if (code) {
184         return (code);
185     }
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);
190     
191     
192 #if     defined(AFS_SUN56_ENV)
193     newip->i_vicemagic = VICEMAGIC;
194 #else
195     newip->i_uid = 0;
196     newip->i_gid = -2;
197 #endif
198     newip->i_nlink = 1;
199     newip->i_mode = IFREG;
200     newip->i_vnode.v_type = VREG;
201     
202     newip->i_vicep1 = param1;
203     if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
204         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
205         newip->i_vicep3 = param3;
206     } else {
207         newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
208             (((param4 >> 16) & 0x1f) << 22) + 
209                 (param3 & 0x3fffff);        
210         newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
211     }
212 #ifdef AFS_SUN57_64BIT_ENV
213     rvp->r_vals = newip->i_number;
214 #else
215     rvp->r_val1 = newip->i_number;
216 #endif
217     
218     /* 
219      * We're being conservative and sync to the disk
220      */
221     if (CrSync)
222         (*ufs_iupdatp)(newip, 1);
223     AFS_ITIMES(newip);
224     rw_exit(&newip->i_contents);
225     VN_RELE(ITOV(newip));
226     return (code);
227 }
228
229 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
230      rval_t *rvp;
231      struct AFS_UCRED *credp;
232      int  inode, usrmod;
233      dev_t dev;
234 {
235     struct file *fp;
236     struct inode *ip;
237     struct vnode *vp = (struct vnode *)0;
238     int dummy;
239     int fd;
240     register int code;
241     dev_t newdev;
242
243     AFS_STATCNT(afs_syscall_iopen);
244
245     if (!afs_suser(credp))
246         return (EPERM);
247
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.
250       */
251     
252 #ifdef AFS_SUN57_64BIT_ENV
253     newdev = expldev( (dev32_t) dev);
254 #else
255     newdev = dev;
256 #endif
257
258     code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
259     if (code) {
260         return (code);
261     }
262     code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
263     if (code) {
264         rw_enter(&ip->i_contents, RW_READER);
265         AFS_ITIMES(ip);
266         rw_exit(&ip->i_contents);
267         VN_RELE(ITOV(ip));
268         return (code);
269     }
270     
271     /* fp->f_count, f_audit_data are set by falloc */
272     fp->f_vnode = ITOV(ip);
273     
274     fp->f_flag = (usrmod+1) & (FMASK);
275     
276     /* fp->f_count, f_msgcount are set by falloc */
277     
278     /* fp->f_offset zeroed by falloc */
279     /* f_cred set by falloc */
280     /*
281      * falloc returns the fp write locked 
282      */
283     mutex_exit(&fp->f_tlock);
284     /*
285      * XXX We should set the fp to null since we don't need it in the icalls
286      */
287     setf(fd, fp);
288 #ifdef AFS_SUN57_64BIT_ENV
289     rvp->r_val2 = fd;
290 #else
291     rvp->r_val1 = fd;
292 #endif
293
294     return code;
295 }
296
297 int IncSync = 1;
298
299 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
300      rval_t *rvp;
301      struct AFS_UCRED *credp;
302      int inode, inode_p1, amount;
303      dev_t dev;
304 {
305     int dummy;
306     struct inode *ip;
307     register afs_int32 code;
308     dev_t newdev;
309
310     if (!afs_suser(credp))
311         return (EPERM);
312
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.
315       */
316     
317 #ifdef AFS_SUN57_64BIT_ENV
318     newdev = expldev( (dev32_t) dev);
319 #else
320     newdev = dev;
321 #endif
322
323     code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
324     if (code) {
325         return (code);
326     }
327     if (!IS_VICEMAGIC(ip)) {
328         code = EPERM;
329         rw_enter(&ip->i_contents, RW_READER);
330         AFS_ITIMES(ip);
331         rw_exit(&ip->i_contents);
332         VN_RELE(ITOV(ip));
333     } else {
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");
339             CLEAR_VICEMAGIC(ip);
340         }
341         mutex_enter(&ip->i_tlock);
342         ip->i_flag |= ICHG;
343         mutex_exit(&ip->i_tlock);
344         /* We may want to force the inode to the disk in case of crashes, other references, etc. */
345         if (IncSync)
346             (*ufs_iupdatp)(ip, 1);
347         AFS_ITIMES(ip);
348         rw_exit(&ip->i_contents);
349         VN_RELE(ITOV(ip));
350     }
351     return (code);
352 }
353