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