no-copy-libafs-builds-20021015
[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("$Header$");
20
21 #include "afs/sysincludes.h"    /* Standard vendor system headers */
22 #include "afsincludes.h"        /* Afs-based standard headers */
23 #include "afs/osi_inode.h"
24 #include "afs/afs_stats.h" /* statistics stuff */
25 #include <ufs/ufsmount.h>
26
27 /* given a vnode, return the `inode number'; if it's a UFS vnode just
28    return the i_number from the in kernel inode struct, if not stat
29    the file to get the inumber from there */
30 afs_uint32
31 osi_vnodeToInumber(struct vnode *vnode)
32 {
33     int error;
34     struct vattr attr;
35
36     /* use faster version with UFS */
37     if(vnode->v_tag == VT_UFS)
38         return VTOI(vnode)->i_number;
39     /* otherwise stat the file */
40     VOP_GETATTR(vnode, &attr, NULL, error);
41     if(error)
42         osi_Panic("VOP_GETATTR = %d", error);
43     return attr.va_fileid;
44 }
45
46 /* return the id of the device containing the file */
47 afs_uint32
48 osi_vnodeToDev(struct vnode *vnode)
49 {
50     int error;
51     struct vattr attr;
52
53     /* use faster version with UFS */
54     if(vnode->v_tag == VT_UFS)
55         return VTOI(vnode)->i_dev;
56     /* otherwise stat the file */
57     VOP_GETATTR(vnode, &attr, NULL, error);
58     if(error)
59         osi_Panic("VOP_GETATTR = %d", error);
60     return attr.va_rdev;
61 }
62
63 getinode(fs, dev, inode, ipp, perror)
64      struct mount *fs;
65      struct inode **ipp;
66      dev_t dev;
67      ino_t inode;
68      int *perror;
69 {
70     register struct vnode *vp;
71     char fake_vnode[FAKE_INODE_SIZE];
72     struct inode *ip;
73     int code;
74
75     *ipp = 0;
76     *perror = 0;
77     if (!fs) {
78         register struct ufsmount *ump;
79         register struct vnode *vp;
80         register struct mount *mp;
81         
82         MOUNTLIST_LOCK();
83         if (mp = rootfs) do {
84             /*
85              * XXX Also do the test for MFS 
86              */
87 #undef m_data
88 #undef m_next
89             if (mp->m_stat.f_type == MOUNT_UFS) {       
90                 MOUNTLIST_UNLOCK();
91                 ump = VFSTOUFS(mp);
92                 if (ump->um_fs == NULL)
93                     break;
94                 if (ump->um_dev == dev) {
95                     fs = ump->um_mountp;
96                 }
97                 MOUNTLIST_LOCK();
98             }
99 #ifdef AFS_DUX50_ENV
100 #define m_next m_nxt
101 #endif
102             mp = mp->m_next;
103         } while (mp != rootfs);
104         MOUNTLIST_UNLOCK();
105         if (!fs)
106             return(ENXIO);
107     }
108     vp = (struct vnode *) fake_vnode;
109     fake_inode_init(vp, fs);
110     assert(vp->v_tag == VT_UFS);
111     code = iget(VTOI(vp), inode, &ip, 0);
112     if (code != 0) {
113         *perror = BAD_IGET;
114         return code;
115     } else {
116         *ipp = ip;
117         return(0);
118     }
119 }
120
121 igetinode(vfsp, dev, inode, ipp, perror)
122      struct inode **ipp;
123      struct mount *vfsp;
124      dev_t dev;
125      ino_t inode;
126      int *perror;
127 {
128     struct inode *pip, *ip;
129     extern struct osi_dev cacheDev;
130     register int code = 0;
131
132     *perror = 0;
133
134     AFS_STATCNT(igetinode);
135
136     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
137         return(code);
138     }
139
140     if (ip->i_mode == 0) {
141         /* Not an allocated inode */
142         iforget(ip);        
143         return(ENOENT);
144     }
145
146     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
147         iput(ip);
148         return(ENOENT);
149     }
150
151     *ipp = ip;
152     return(0);
153 }
154
155 iforget(ip)
156 struct inode *ip;
157 {
158     struct vnode *vp = ITOV(ip);
159
160     AFS_STATCNT(iforget);
161
162     VN_LOCK(vp);
163     /* this whole thing is too wierd.  Why??? XXX */
164     if (vp->v_usecount == 1) {
165         VN_UNLOCK(vp);
166         idrop(ip);
167     } else {
168         VN_UNLOCK(vp);
169     }
170 }
171
172 /*
173  * icreate system call -- create an inode
174  */
175 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
176      long *retval;
177      long dev, near_inode, param1, param2, param3, param4;
178 {
179     int dummy, err=0;
180     struct inode *ip, *newip;
181     register int code;
182     struct vnode *vp;
183     
184     AFS_STATCNT(afs_syscall_icreate);
185     
186     if (!afs_suser())
187         return(EPERM);
188
189     code = getinode(0, (dev_t)dev, 2, &ip, &dummy);
190     if (code) {
191         return(ENOENT);
192     }
193     code = ialloc(ip, (ino_t)near_inode, 0, &newip);
194     iput(ip);
195     if (code) {
196         return(code);
197     }
198     IN_LOCK(newip);
199     newip->i_flag |= IACC|IUPD|ICHG;
200     
201     newip->i_nlink = 1;
202
203     newip->i_mode = IFREG;
204     
205     IN_UNLOCK(newip);
206     vp = ITOV(newip);
207     VN_LOCK(vp);
208     vp->v_type = VREG;
209     VN_UNLOCK(vp);
210     
211     if ( !vp->v_object)
212         {
213             extern struct vfs_ubcops ufs_ubcops;
214             extern struct vm_ubc_object* ubc_object_allocate();
215             struct vm_ubc_object* vop;
216             vop = ubc_object_allocate(&vp, &ufs_ubcops,
217                                       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 = (((param2 >> 16) & 0x1f) << 27) +
234             (((param4 >> 16) & 0x1f) << 22) + 
235                 (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 }