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