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