Remove support for Solaris pre-8
[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 <afsconfig.h>
17 #include "afs/param.h"
18
19
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 */
24
25 extern int (*ufs_iallocp) (), (*ufs_iupdatp) (), (*ufs_igetp) (),
26     (*ufs_itimes_nolockp) ();
27
28 #define AFS_ITIMES(ip) { \
29         mutex_enter(&(ip)->i_tlock); \
30         (*ufs_itimes_nolockp)(ip); \
31         mutex_exit(&(ip)->i_tlock); \
32 }
33
34 #define AFS_ITIMES_NOLOCK(ip) \
35         (*ufs_itimes_nolockp)(ip);
36
37 getinode(vfsp, dev, inode, ipp, credp, perror)
38      struct vfs *vfsp;
39      afs_ucred_t *credp;
40      struct inode **ipp;
41      dev_t dev;
42      ino_t inode;
43      int *perror;
44 {
45     struct inode *ip;
46     afs_int32 code;
47     struct vnode *vp;
48     struct fs *fs;
49     struct inode *pip;
50     struct ufsvfs *ufsvfsp;
51
52     AFS_STATCNT(getinode);
53
54     *perror = 0;
55
56     if (!vfsp && !(vfsp = vfs_dev2vfsp(dev))) {
57         return (ENODEV);
58     }
59     ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
60
61 #ifdef HAVE_VFS_DQRWLOCK
62     rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
63 #endif
64     code = (*ufs_igetp) (vfsp, inode, &ip, credp);
65 #ifdef HAVE_VFS_DQRWLOCK
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      afs_ucred_t *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     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         rw_exit(&ip->i_contents);
103         VN_RELE(ITOV(ip));
104         return (ENOENT);
105     }
106
107     if (ip->i_nlink == 0 || (ip->i_mode & IFMT) != IFREG) {
108         AFS_ITIMES(ip);
109         rw_exit(&ip->i_contents);
110         VN_RELE(ITOV(ip));
111         return (ENOENT);
112     }
113
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) {
120         /* 
121          * Don't call dnlc for the cm inodes since it's a big performance 
122          * penalty there!
123          */
124 #ifdef AFS_SUN510_ENV
125         dnlc_enter(ITOV(ip), "a", ITOV(ip));
126 #else
127         dnlc_enter(ITOV(ip), "a", ITOV(ip), (afs_ucred_t *)0);
128 #endif
129     }
130
131     *ipp = ip;
132     rw_exit(&ip->i_contents);
133     return (code);
134 }
135
136 int CrSync = 1;
137
138 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp,
139                     credp)
140      rval_t *rvp;
141      afs_ucred_t *credp;
142      long near_inode, param1, param2, param3, param4;
143      dev_t dev;
144 {
145     int dummy, err = 0;
146     struct inode *ip, *newip;
147     int code;
148     dev_t newdev;
149     struct ufsvfs *ufsvfsp;
150
151     AFS_STATCNT(afs_syscall_icreate);
152
153     if (!afs_osi_suser(credp))
154         return (EPERM);
155
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.
158       */
159
160 #ifdef AFS_SUN5_64BIT_ENV
161     newdev = expldev((dev32_t) dev);
162 #else
163     newdev = dev;
164 #endif
165
166     code = getinode(0, (dev_t) newdev, 2, &ip, credp, &dummy);
167     if (code) {
168         return (code);
169     }
170
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);
175 #endif
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);
182 #endif
183     rw_exit(&ip->i_rwlock);
184     VN_RELE(ITOV(ip));
185
186     if (code) {
187         return (code);
188     }
189     rw_enter(&newip->i_contents, RW_WRITER);
190     newip->i_flag |= IACC | IUPD | ICHG;
191
192     newip->i_vicemagic = VICEMAGIC;
193     newip->i_nlink = 1;
194     newip->i_mode = IFREG;
195 #ifdef AFS_SUN510_ENV
196     newip->i_vnode->v_type = VREG;
197 #else
198     newip->i_vnode.v_type = VREG;
199 #endif
200
201     newip->i_vicep1 = param1;
202     if (param2 == 0x1fffffff /*INODESPECIAL*/) {
203         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
204         newip->i_vicep3 = param3;
205     } else {
206         newip->i_vicep2 =
207             (((param2 >> 16) & 0x1f) << 27) +
208             (((param4 >> 16) & 0x1f) << 22) + (param3 & 0x3fffff);
209         newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
210     }
211 #ifdef AFS_SUN5_64BIT_ENV
212     rvp->r_vals = newip->i_number;
213 #else
214     rvp->r_val1 = newip->i_number;
215 #endif
216
217     /* 
218      * We're being conservative and sync to the disk
219      */
220     if (CrSync)
221         (*ufs_iupdatp) (newip, 1);
222     AFS_ITIMES_NOLOCK(newip);
223     rw_exit(&newip->i_contents);
224     VN_RELE(ITOV(newip));
225     return (code);
226 }
227
228 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
229      rval_t *rvp;
230      afs_ucred_t *credp;
231      int inode, usrmod;
232      dev_t dev;
233 {
234     struct file *fp;
235     struct inode *ip;
236     struct vnode *vp = NULL;
237     int dummy;
238     int fd;
239     int code;
240     dev_t newdev;
241
242     AFS_STATCNT(afs_syscall_iopen);
243
244     if (!afs_osi_suser(credp))
245         return (EPERM);
246
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.
249       */
250
251 #ifdef AFS_SUN5_64BIT_ENV
252     newdev = expldev((dev32_t) dev);
253 #else
254     newdev = dev;
255 #endif
256
257     code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
258     if (code) {
259         return (code);
260     }
261     code = falloc((struct vnode *)NULL, FWRITE | FREAD, &fp, &fd);
262     if (code) {
263         rw_enter(&ip->i_contents, RW_READER);
264         AFS_ITIMES(ip);
265         rw_exit(&ip->i_contents);
266         VN_RELE(ITOV(ip));
267         return (code);
268     }
269
270     /* fp->f_count, f_audit_data are set by falloc */
271     fp->f_vnode = ITOV(ip);
272
273     fp->f_flag = (usrmod + 1) & (FMASK);
274
275     /* fp->f_count, f_msgcount are set by falloc */
276
277     /* fp->f_offset zeroed by falloc */
278     /* f_cred set by falloc */
279     /*
280      * falloc returns the fp write locked 
281      */
282     mutex_exit(&fp->f_tlock);
283     /*
284      * XXX We should set the fp to null since we don't need it in the icalls
285      */
286     setf(fd, fp);
287
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
292      * second one. */
293 #if defined(AFS_SUN5_64BIT_ENV) && !defined(AFSLITTLE_ENDIAN)
294     rvp->r_val2 = fd;
295 #else
296     rvp->r_val1 = fd;
297 #endif
298
299     return code;
300 }
301
302 int IncSync = 1;
303
304 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
305      rval_t *rvp;
306      afs_ucred_t *credp;
307      int inode, inode_p1, amount;
308      dev_t dev;
309 {
310     int dummy;
311     struct inode *ip;
312     afs_int32 code;
313     dev_t newdev;
314
315     if (!afs_osi_suser(credp))
316         return (EPERM);
317
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.
320       */
321
322 #ifdef AFS_SUN5_64BIT_ENV
323     newdev = expldev((dev32_t) dev);
324 #else
325     newdev = dev;
326 #endif
327
328     code = igetinode(0, (dev_t) newdev, (ino_t) inode, &ip, credp, &dummy);
329     if (code) {
330         return (code);
331     }
332     if (!IS_VICEMAGIC(ip)) {
333         code = EPERM;
334         rw_enter(&ip->i_contents, RW_READER);
335         AFS_ITIMES(ip);
336         rw_exit(&ip->i_contents);
337         VN_RELE(ITOV(ip));
338     } else {
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");
344             CLEAR_VICEMAGIC(ip);
345         }
346         ip->i_flag |= ICHG;
347         /* We may want to force the inode to the disk in case of crashes, other references, etc. */
348         if (IncSync)
349             (*ufs_iupdatp) (ip, 1);
350         AFS_ITIMES_NOLOCK(ip);
351         rw_exit(&ip->i_contents);
352         VN_RELE(ITOV(ip));
353     }
354     return (code);
355 }