42bdc89dc6ecc6872cb0bb7257f450928744ee93
[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_iputp)(), (*ufs_iallocp)(), (*ufs_iupdatp)(),  (*ufs_igetp)();
23
24 getinode(vfsp, dev, inode, ipp, credp,perror)
25      struct vfs *vfsp;
26      struct AFS_UCRED *credp;
27      struct inode **ipp;
28      dev_t dev;
29      ino_t inode;
30      int *perror;
31 {
32     struct inode *ip;
33     register afs_int32 code;
34     struct vnode *vp;
35     struct fs *fs;
36     struct inode *pip;
37     
38     AFS_STATCNT(getinode);
39     
40     *perror = 0;
41     
42     if (!vfsp 
43 #if !defined(AFS_SUN58_ENV)
44         && !(vfsp = vfs_devsearch(dev))
45 #else
46         && !(vfsp = vfs_dev2vfsp(dev))
47 #endif
48         ) {
49         return (ENODEV);
50     }
51     if (code = (*ufs_igetp)(vfsp, inode, &ip, credp)) {
52         *perror = BAD_IGET;
53         return code;
54     }
55     *ipp = ip;
56     return code;
57 }
58
59 /* get an existing inode.  Common code for iopen, iread/write, iinc/dec. */
60 igetinode(vfsp, dev, inode, ipp, credp,perror)
61      struct AFS_UCRED *credp;
62      struct inode **ipp;
63      struct vfs *vfsp;
64      dev_t dev;
65      ino_t inode;
66      int *perror;
67 {
68     struct inode *pip, *ip;
69     extern struct osi_dev cacheDev;
70     register int code = 0;
71     
72     *perror = 0;
73     
74     AFS_STATCNT(igetinode);
75     
76     code = getinode(vfsp, dev, inode, &ip, credp,perror);
77     if (code) 
78         return code;
79     
80     rw_enter(&ip->i_contents, RW_READER);
81     
82     if (ip->i_mode == 0) {
83         /* Not an allocated inode */
84         rw_exit(&ip->i_contents);
85         (*ufs_iputp)(ip);
86         return (ENOENT);
87     }
88     
89     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
90         rw_exit(&ip->i_contents);
91         (*ufs_iputp)(ip);
92         return (ENOENT);
93     }
94     
95     /* On VFS40 systems, iput does major synchronous write action, but only
96        when the reference count on the vnode goes to 0.  Normally, Sun users
97        don't notice this because the DNLC keep references for them, but we
98        notice 'cause we don't.  So, we make a fake dnlc entry which gets
99        cleaned up by iget when it needs the space. */
100     if (dev != cacheDev.dev) {
101         /* 
102          * Don't call dnlc for the cm inodes since it's a big performance 
103          * penalty there!
104          */
105         dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *) 0);
106     }
107     
108     *ipp = ip;
109     rw_exit(&ip->i_contents);
110     return (code);
111 }
112
113 int CrSync = 1;
114
115 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
116      rval_t *rvp;
117      struct AFS_UCRED *credp;
118      long near_inode, param1, param2, param3, param4;
119      dev_t dev;
120 {
121     int dummy, err=0;
122     struct inode *ip, *newip;
123     register int code;
124     dev_t newdev;
125
126     AFS_STATCNT(afs_syscall_icreate);
127     
128     if (!afs_suser(credp))
129         return (EPERM);
130     
131     /** Code to convert a 32 bit dev_t into a 64 bit dev_t
132       * This conversion is needed only for the 64 bit OS.
133       */
134     
135 #ifdef AFS_SUN57_64BIT_ENV
136     newdev = expldev( (dev32_t) dev);
137 #else
138     newdev = dev;
139 #endif
140
141     code = getinode(0, (dev_t)newdev, 2, &ip, credp,&dummy);
142     if (code) {
143         return (code);
144     }
145     if (code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp)) {      
146         (*ufs_iputp)(ip);
147         return (code);
148     }
149     (*ufs_iputp)(ip);
150     rw_enter(&newip->i_contents, RW_WRITER);
151     mutex_enter(&newip->i_tlock);
152     newip->i_flag |= IACC|IUPD|ICHG;
153     mutex_exit(&newip->i_tlock);
154     
155     
156 #if     defined(AFS_SUN56_ENV)
157     newip->i_vicemagic = VICEMAGIC;
158 #else
159     newip->i_uid = 0;
160     newip->i_gid = -2;
161 #endif
162     newip->i_nlink = 1;
163     newip->i_mode = IFREG;
164     newip->i_vnode.v_type = VREG;
165     
166     newip->i_vicep1 = param1;
167     if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
168         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
169         newip->i_vicep3 = param3;
170     } else {
171         newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
172             (((param4 >> 16) & 0x1f) << 22) + 
173                 (param3 & 0x3fffff);        
174         newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
175     }
176 #ifdef AFS_SUN57_64BIT_ENV
177     rvp->r_vals = newip->i_number;
178 #else
179     rvp->r_val1 = newip->i_number;
180 #endif
181     
182     /* 
183      * We're being conservative and sync to the disk
184      */
185     if (CrSync)
186         (*ufs_iupdatp)(newip, 1);
187     rw_exit(&newip->i_contents);
188     (*ufs_iputp)(newip);
189     return (code);
190 }
191
192 afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
193      rval_t *rvp;
194      struct AFS_UCRED *credp;
195      int  inode, usrmod;
196      dev_t dev;
197 {
198     struct file *fp;
199     struct inode *ip;
200     struct vnode *vp = (struct vnode *)0;
201     int dummy;
202     int fd;
203     register int code;
204     dev_t newdev;
205
206     AFS_STATCNT(afs_syscall_iopen);
207
208     if (!afs_suser(credp))
209         return (EPERM);
210
211     /** Code to convert a 32 bit dev_t into a 64 bit dev_t
212       * This conversion is needed only for the 64 bit OS.
213       */
214     
215 #ifdef AFS_SUN57_64BIT_ENV
216     newdev = expldev( (dev32_t) dev);
217 #else
218     newdev = dev;
219 #endif
220
221     code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
222     if (code) {
223         return (code);
224     }
225     code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
226     if (code) {
227         (*ufs_iputp)(ip);
228         return (code);
229     }
230     
231     /* fp->f_count, f_audit_data are set by falloc */
232     fp->f_vnode = ITOV(ip);
233     
234     fp->f_flag = (usrmod+1) & (FMASK);
235     
236     /* fp->f_count, f_msgcount are set by falloc */
237     
238     /* fp->f_offset zeroed by falloc */
239     /* f_cred set by falloc */
240     /*
241      * falloc returns the fp write locked 
242      */
243     mutex_exit(&fp->f_tlock);
244     /*
245      * XXX We should set the fp to null since we don't need it in the icalls
246      */
247     setf(fd, fp);
248 #ifdef AFS_SUN57_64BIT_ENV
249     rvp->r_val2 = fd;
250 #else
251     rvp->r_val1 = fd;
252 #endif
253
254     return code;
255 }
256
257 int IncSync = 1;
258
259 afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
260      rval_t *rvp;
261      struct AFS_UCRED *credp;
262      int inode, inode_p1, amount;
263      dev_t dev;
264 {
265     int dummy;
266     struct inode *ip;
267     register afs_int32 code;
268     dev_t newdev;
269
270     if (!afs_suser(credp))
271         return (EPERM);
272
273         /** Code to convert a 32 bit dev_t into a 64 bit dev_t
274       * This conversion is needed only for the 64 bit OS.
275       */
276     
277 #ifdef AFS_SUN57_64BIT_ENV
278     newdev = expldev( (dev32_t) dev);
279 #else
280     newdev = dev;
281 #endif
282
283     code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
284     if (code) {
285         return (code);
286     }
287     if (!IS_VICEMAGIC(ip))
288         code = EPERM;
289     else {
290         rw_enter(&ip->i_contents, RW_WRITER);
291         ip->i_nlink += amount;
292         if (ip->i_nlink == 0) {
293             /* remove the "a" name added by igetinode so that the space is reclaimed. */
294             dnlc_remove(ITOV(ip), "a");
295             CLEAR_VICEMAGIC(ip);
296         }
297         mutex_enter(&ip->i_tlock);
298         ip->i_flag |= ICHG;
299         mutex_exit(&ip->i_tlock);
300         /* We may want to force the inode to the disk in case of crashes, other references, etc. */
301         if (IncSync)
302             (*ufs_iupdatp)(ip, 1);
303         rw_exit(&ip->i_contents);
304     }
305     (*ufs_iputp)(ip);
306     return (code);
307 }
308