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