Linux: Remove unnecessary crhold on incomplete kernel credentials
[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
20 #include "afs/sysincludes.h"    /* Standard vendor system headers */
21 #include "afsincludes.h"        /* Afs-based standard headers */
22 #include "afs/osi_inode.h"
23 #include "afs/afs_stats.h"      /* statistics stuff */
24 #include <sys/queue.h>
25 #include <sys/lock.h>
26 #include <ufs/ufsmount.h>
27 #include <ufs/ufs/dinode.h>
28
29 getinode(fs, dev, inode, ipp, perror)
30      struct mount *fs;
31      struct inode **ipp;
32      dev_t dev;
33      ino_t inode;
34      int *perror;
35 {
36     register struct vnode *vp;
37     char fake_vnode[FAKE_INODE_SIZE];
38     struct inode *ip;
39     int code;
40
41     *ipp = 0;
42     *perror = 0;
43     if (!fs) {
44         register struct ufsmount *ump;
45         register struct vnode *vp;
46         register struct mount *mp;
47
48         MOUNTLIST_LOCK();
49         if (mp = TAILQ_FIRST(&mountlist))
50             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(NULL))
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 =
198             (((param2 >> 16) & 0x1f) << 27) +
199             (((param4 >> 16) & 0x1f) << 22) + (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(NULL))
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(NULL))
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 }