6bdf32bfaa3557dd3afbf7f96e233b12aaa1868f
[openafs.git] / src / afs / DUX / 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  * DUX 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 #include <ufs/ufsmount.h>
22
23 /* given a vnode, return the `inode number'; if it's a UFS vnode just
24    return the i_number from the in kernel inode struct, if not stat
25    the file to get the inumber from there */
26 afs_uint32
27 osi_vnodeToInumber(struct vnode *vnode)
28 {
29     int error;
30     struct vattr attr;
31
32     /* use faster version with UFS */
33     if(vnode->v_tag == VT_UFS)
34         return VTOI(vnode)->i_number;
35     /* otherwise stat the file */
36     VOP_GETATTR(vnode, &attr, NULL, error);
37     if(error)
38         osi_Panic("VOP_GETATTR = %d", error);
39     return attr.va_fileid;
40 }
41
42 /* return the id of the device containing the file */
43 afs_uint32
44 osi_vnodeToDev(struct vnode *vnode)
45 {
46     int error;
47     struct vattr attr;
48
49     /* use faster version with UFS */
50     if(vnode->v_tag == VT_UFS)
51         return VTOI(vnode)->i_dev;
52     /* otherwise stat the file */
53     VOP_GETATTR(vnode, &attr, NULL, error);
54     if(error)
55         osi_Panic("VOP_GETATTR = %d", error);
56     return attr.va_rdev;
57 }
58
59 getinode(fs, dev, inode, ipp, perror)
60      struct mount *fs;
61      struct inode **ipp;
62      dev_t dev;
63      ino_t inode;
64      int *perror;
65 {
66     register struct vnode *vp;
67     char fake_vnode[FAKE_INODE_SIZE];
68     struct inode *ip;
69     int code;
70
71     *ipp = 0;
72     *perror = 0;
73     if (!fs) {
74         register struct ufsmount *ump;
75         register struct vnode *vp;
76         register struct mount *mp;
77         
78         MOUNTLIST_LOCK();
79         if (mp = rootfs) do {
80             /*
81              * XXX Also do the test for MFS 
82              */
83 #undef m_data
84 #undef m_next
85             if (mp->m_stat.f_type == MOUNT_UFS) {       
86                 MOUNTLIST_UNLOCK();
87                 ump = VFSTOUFS(mp);
88                 if (ump->um_fs == NULL)
89                     break;
90                 if (ump->um_dev == dev) {
91                     fs = ump->um_mountp;
92                 }
93                 MOUNTLIST_LOCK();
94             }
95 #ifdef AFS_DUX50_ENV
96 #define m_next m_nxt
97 #endif
98             mp = mp->m_next;
99         } while (mp != rootfs);
100         MOUNTLIST_UNLOCK();
101         if (!fs)
102             return(ENXIO);
103     }
104     vp = (struct vnode *) fake_vnode;
105     fake_inode_init(vp, fs);
106     code = iget(VTOI(vp), inode, &ip, 0);
107     if (code != 0) {
108         *perror = BAD_IGET;
109         return code;
110     } else {
111         *ipp = ip;
112         return(0);
113     }
114 }
115
116 igetinode(vfsp, dev, inode, ipp, perror)
117      struct inode **ipp;
118      struct mount *vfsp;
119      dev_t dev;
120      ino_t inode;
121      int *perror;
122 {
123     struct inode *pip, *ip;
124     extern struct osi_dev cacheDev;
125     register int code = 0;
126
127     *perror = 0;
128
129     AFS_STATCNT(igetinode);
130
131     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
132         return(code);
133     }
134
135     if (ip->i_mode == 0) {
136         /* Not an allocated inode */
137         iforget(ip);        
138         return(ENOENT);
139     }
140
141     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
142         iput(ip);
143         return(ENOENT);
144     }
145
146     *ipp = ip;
147     return(0);
148 }
149
150 iforget(ip)
151 struct inode *ip;
152 {
153     struct vnode *vp = ITOV(ip);
154
155     AFS_STATCNT(iforget);
156
157     VN_LOCK(vp);
158     /* this whole thing is too wierd.  Why??? XXX */
159     if (vp->v_usecount == 1) {
160         VN_UNLOCK(vp);
161         idrop(ip);
162     } else {
163         VN_UNLOCK(vp);
164     }
165 }
166
167 /*
168  * icreate system call -- create an inode
169  */
170 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
171      long *retval;
172      long dev, near_inode, param1, param2, param3, param4;
173 {
174     int dummy, err=0;
175     struct inode *ip, *newip;
176     register int code;
177     struct vnode *vp;
178     
179     AFS_STATCNT(afs_syscall_icreate);
180     
181     if (!afs_suser())
182         return(EPERM);
183
184     code = getinode(0, (dev_t)dev, 2, &ip, &dummy);
185     if (code) {
186         return(ENOENT);
187     }
188     code = ialloc(ip, (ino_t)near_inode, 0, &newip);
189     iput(ip);
190     if (code) {
191         return(code);
192     }
193     IN_LOCK(newip);
194     newip->i_flag |= IACC|IUPD|ICHG;
195     
196     newip->i_nlink = 1;
197
198     newip->i_mode = IFREG;
199     
200     IN_UNLOCK(newip);
201     vp = ITOV(newip);
202     VN_LOCK(vp);
203     vp->v_type = VREG;
204     VN_UNLOCK(vp);
205     
206     if ( !vp->v_object)
207         {
208             extern struct vfs_ubcops ufs_ubcops;
209             extern struct vm_ubc_object* ubc_object_allocate();
210             struct vm_ubc_object* vop;
211             vop = ubc_object_allocate(&vp, &ufs_ubcops,
212                                       vp->v_mount->m_funnel);
213             VN_LOCK(vp);
214             vp->v_object = vop;
215             VN_UNLOCK(vp);
216         }
217     
218     
219     IN_LOCK(newip);
220     newip->i_flags |= IC_XUID|IC_XGID;
221     newip->i_flags &= ~IC_PROPLIST;
222     newip->i_vicep1 = param1;
223     if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
224         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
225         newip->i_vicep3a = (u_short)(param3 >> 16);
226         newip->i_vicep3b = (u_short)param3;
227     } else {
228         newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
229             (((param4 >> 16) & 0x1f) << 22) + 
230                 (param3 & 0x3fffff);        
231         newip->i_vicep3a = (u_short)param4;
232         newip->i_vicep3b = (u_short)param2;
233     }
234     newip->i_vicemagic = VICEMAGIC;
235     
236     *retval = newip->i_number;
237     IN_UNLOCK(newip);
238     iput(newip);
239     return(code);
240 }
241
242
243 afs_syscall_iopen(dev, inode, usrmod, retval)
244      long *retval;
245      int dev, inode, usrmod;
246 {
247     struct file *fp;
248     struct inode *ip;
249     struct vnode *vp = (struct vnode *)0;
250     int dummy;
251     int fd;
252     extern struct fileops vnops;
253     register int code;
254 #ifdef AFS_DUX50_ENV
255     struct ufile_entry *fe;
256 #endif
257     
258     AFS_STATCNT(afs_syscall_iopen);
259     
260     if (!afs_suser())
261         return(EPERM);
262
263     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
264     if (code) {
265         return(code);
266     }
267 #ifdef AFS_DUX50_ENV
268     if ((code = falloc(&fp, &fd, &fe)) != 0) {
269         iput(ip);
270         return(code);
271     }
272 #else
273     if ((code = falloc(&fp, &fd)) != 0) {
274         iput(ip);
275         return(code);
276     }
277 #endif
278     IN_UNLOCK(ip);
279     
280     FP_LOCK(fp);
281     fp->f_flag = (usrmod-FOPEN) & FMASK;
282     fp->f_type = DTYPE_VNODE;
283     fp->f_ops = &vnops;
284     fp->f_data = (caddr_t)ITOV(ip);
285     
286     FP_UNLOCK(fp);
287 #ifdef AFS_DUX50_ENV
288     u_set_fe(fd, fe, fp, &u.u_file_state);
289 #else
290     U_FD_SET(fd, fp, &u.u_file_state);
291 #endif
292     *retval = fd;
293     return(0);
294 }
295
296
297 /*
298  * Support for iinc() and idec() system calls--increment or decrement
299  * count on inode.
300  * Restricted to super user.
301  * Only VICEMAGIC type inodes.
302  */
303 afs_syscall_iincdec(dev, inode, inode_p1, amount)
304      int dev, inode, inode_p1, amount;
305 {
306     int dummy;
307     struct inode *ip;
308     register int code;
309     
310     if (!afs_suser())
311         return(EPERM);
312
313     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
314     if (code) {
315         return(code);
316     }
317     if (!IS_VICEMAGIC(ip)) {
318         return(EPERM);
319     } else if (ip->i_vicep1 != inode_p1) {
320         return(ENXIO);
321     }
322     ip->i_nlink += amount;
323     if (ip->i_nlink == 0) {
324         CLEAR_VICEMAGIC(ip);
325     }
326     ip->i_flag |= ICHG;
327     iput(ip);
328     return(0);
329 }