2e77da016fd1d980297c3817c3c0a0bf23142c78
[openafs.git] / src / afs / NBSD / 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  * FreeBSD 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 "../afs/afsincludes.h" /* Afs-based standard headers */
23 #include "../afs/osi_inode.h"
24 #include "../afs/afs_stats.h" /* statistics stuff */
25 #include <sys/queue.h>
26 #include <sys/lock.h>
27 #include <ufs/ufsmount.h>
28 #include <ufs/ufs/dinode.h>
29
30 getinode(fs, dev, inode, ipp, perror)
31      struct mount *fs;
32      struct inode **ipp;
33      dev_t dev;
34      ino_t inode;
35      int *perror;
36 {
37     register struct vnode *vp;
38     char fake_vnode[FAKE_INODE_SIZE];
39     struct inode *ip;
40     int code;
41
42     *ipp = 0;
43     *perror = 0;
44     if (!fs) {
45         register struct ufsmount *ump;
46         register struct vnode *vp;
47         register struct mount *mp;
48         
49         MOUNTLIST_LOCK();
50         if (mp = TAILQ_FIRST(&mountlist)) do {
51             /*
52              * XXX Also do the test for MFS 
53              */
54 #undef m_data
55 #undef m_next
56             if (mp->mnt_stat.f_type == MOUNT_UFS) {     
57                 MOUNTLIST_UNLOCK();
58                 ump = VFSTOUFS(mp);
59                 if (ump->um_fs == NULL)
60                     break;
61                 if (ump->um_dev == dev) {
62                     fs = ump->um_mountp;
63                 }
64                 MOUNTLIST_LOCK();
65             }
66             mp = TAILQ_NEXT(mp, mnt_list);
67         } while (mp != TAILQ_FIRST(&mountlist));
68         MOUNTLIST_UNLOCK();
69         if (!fs)
70             return(ENXIO);
71     }
72     vp = (struct vnode *) fake_vnode;
73     fake_inode_init(vp, fs);
74     code = iget(VTOI(vp), inode, &ip, 0);
75     if (code != 0) {
76         *perror = BAD_IGET;
77         return code;
78     } else {
79         *ipp = ip;
80         return(0);
81     }
82 }
83
84 igetinode(vfsp, dev, inode, ipp, perror)
85      struct inode **ipp;
86      struct mount *vfsp;
87      dev_t dev;
88      ino_t inode;
89      int *perror;
90 {
91     struct inode *pip, *ip;
92     extern struct osi_dev cacheDev;
93     register int code = 0;
94
95     *perror = 0;
96
97     AFS_STATCNT(igetinode);
98
99     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
100         return(code);
101     }
102
103     if (ip->i_mode == 0) {
104         /* Not an allocated inode */
105         iforget(ip);        
106         return(ENOENT);
107     }
108
109     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
110         iput(ip);
111         return(ENOENT);
112     }
113
114     *ipp = ip;
115     return(0);
116 }
117
118 iforget(ip)
119 struct inode *ip;
120 {
121     struct vnode *vp = ITOV(ip);
122
123     AFS_STATCNT(iforget);
124
125     VN_LOCK(vp);
126     /* this whole thing is too wierd.  Why??? XXX */
127     if (vp->v_usecount == 1) {
128         VN_UNLOCK(vp);
129         idrop(ip);
130     } else {
131         VN_UNLOCK(vp);
132     }
133 }
134
135 /*
136  * icreate system call -- create an inode
137  */
138 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
139      long *retval;
140      long dev, near_inode, param1, param2, param3, param4;
141 {
142     int dummy, err=0;
143     struct inode *ip, *newip;
144     register int code;
145     struct vnode *vp;
146     
147     AFS_STATCNT(afs_syscall_icreate);
148     
149     if (!afs_suser())
150         return(EPERM);
151
152     code = getinode(0, (dev_t)dev, 2, &ip, &dummy);
153     if (code) {
154         return(ENOENT);
155     }
156     code = ialloc(ip, (ino_t)near_inode, 0, &newip);
157     iput(ip);
158     if (code) {
159         return(code);
160     }
161     IN_LOCK(newip);
162     newip->i_flag |= IACC|IUPD|ICHG;
163     
164     newip->i_nlink = 1;
165
166     newip->i_mode = IFREG;
167     
168     IN_UNLOCK(newip);
169     vp = ITOV(newip);
170     VN_LOCK(vp);
171     vp->v_type = VREG;
172     VN_UNLOCK(vp);
173     
174     /*
175     if ( !vp->v_object)
176         {
177             extern struct vfs_ubcops ufs_ubcops;
178             extern struct vm_ubc_object* ubc_object_allocate();
179             struct vm_ubc_object* vop;
180             vop = ubc_object_allocate(&vp, &ufs_ubcops,
181                                       vp->v_mount->m_funnel);
182             VN_LOCK(vp);
183             vp->v_object = vop;
184             VN_UNLOCK(vp);
185         }
186     */
187     
188     IN_LOCK(newip);
189     /*    newip->i_flags |= IC_XUID|IC_XGID; */
190     /*    newip->i_flags &= ~IC_PROPLIST; */
191     newip->i_vicep1 = param1;
192     if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
193         newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
194         newip->i_vicep3a = (u_short)(param3 >> 16);
195         newip->i_vicep3b = (u_short)param3;
196     } else {
197         newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
198             (((param4 >> 16) & 0x1f) << 22) + 
199                 (param3 & 0x3fffff);        
200         newip->i_vicep3a = (u_short)param4;
201         newip->i_vicep3b = (u_short)param2;
202     }
203     newip->i_vicemagic = VICEMAGIC;
204     
205     *retval = newip->i_number;
206     IN_UNLOCK(newip);
207     iput(newip);
208     return(code);
209 }
210
211
212 afs_syscall_iopen(dev, inode, usrmod, retval)
213      long *retval;
214      int dev, inode, usrmod;
215 {
216     struct file *fp;
217     struct inode *ip;
218     struct vnode *vp = NULL;
219     int dummy;
220     int fd;
221     extern struct fileops vnops;
222     register int code;
223     
224     AFS_STATCNT(afs_syscall_iopen);
225     
226     if (!afs_suser())
227         return(EPERM);
228
229     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
230     if (code) {
231         return(code);
232     }
233     if ((code = falloc(curproc, &fp, &fd)) != 0) {
234         iput(ip);
235         return(code);
236     }
237     IN_UNLOCK(ip);
238     
239     /* FreeBSD doesn't do much mp stuff yet :( */
240     /* FP_LOCK(fp); */
241     fp->f_flag = (usrmod) & FMASK;
242     fp->f_type = DTYPE_VNODE;
243     fp->f_ops = &vnops;
244     fp->f_data = (caddr_t)ITOV(ip);
245     
246     /* FP_UNLOCK(fp); */
247     return(0);
248 }
249
250
251 /*
252  * Support for iinc() and idec() system calls--increment or decrement
253  * count on inode.
254  * Restricted to super user.
255  * Only VICEMAGIC type inodes.
256  */
257 afs_syscall_iincdec(dev, inode, inode_p1, amount)
258      int dev, inode, inode_p1, amount;
259 {
260     int dummy;
261     struct inode *ip;
262     register int code;
263     
264     if (!afs_suser())
265         return(EPERM);
266
267     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
268     if (code) {
269         return(code);
270     }
271     if (!IS_VICEMAGIC(ip)) {
272         return(EPERM);
273     } else if (ip->i_vicep1 != inode_p1) {
274         return(ENXIO);
275     }
276     ip->i_nlink += amount;
277     if (ip->i_nlink == 0) {
278         CLEAR_VICEMAGIC(ip);
279     }
280     ip->i_flag |= ICHG;
281     iput(ip);
282     return(0);
283 }