0679b2a1859675f2991178d39f1a113a70fd7f2d
[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 "../afs/param.h"       /* Should be always first */
17 #include "../afs/sysincludes.h" /* Standard vendor system headers */
18 #include "../afs/afsincludes.h" /* Afs-based standard headers */
19 #include "../afs/osi_inode.h"
20 #include "../afs/afs_stats.h" /* statistics stuff */
21 #include <ufs/ufsmount.h>
22
23 getinode(fs, dev, inode, ipp, perror)
24      struct mount *fs;
25      struct inode **ipp;
26      dev_t dev;
27      ino_t inode;
28      int *perror;
29 {
30     register struct vnode *vp;
31     char fake_vnode[FAKE_INODE_SIZE];
32     struct inode *ip;
33     int code;
34
35     *ipp = 0;
36     *perror = 0;
37     if (!fs) {
38         register struct ufsmount *ump;
39         register struct vnode *vp;
40         register struct mount *mp;
41         
42         MOUNTLIST_LOCK();
43         if (mp = rootfs) do {
44             /*
45              * XXX Also do the test for MFS 
46              */
47 #undef m_data
48 #undef m_next
49             if (mp->m_stat.f_type == MOUNT_UFS) {       
50                 MOUNTLIST_UNLOCK();
51                 ump = VFSTOUFS(mp);
52                 if (ump->um_fs == NULL)
53                     break;
54                 if (ump->um_dev == dev) {
55                     fs = ump->um_mountp;
56                 }
57                 MOUNTLIST_LOCK();
58             }
59 #ifdef AFS_DUX50_ENV
60 #define m_next m_nxt
61 #endif
62             mp = mp->m_next;
63         } while (mp != rootfs);
64         MOUNTLIST_UNLOCK();
65         if (!fs)
66             return(ENXIO);
67     }
68     vp = (struct vnode *) fake_vnode;
69     fake_inode_init(vp, fs);
70     code = iget(VTOI(vp), inode, &ip, 0);
71     if (code != 0) {
72         *perror = BAD_IGET;
73         return code;
74     } else {
75         *ipp = ip;
76         return(0);
77     }
78 }
79
80 igetinode(vfsp, dev, inode, ipp, perror)
81      struct inode **ipp;
82      struct mount *vfsp;
83      dev_t dev;
84      ino_t inode;
85      int *perror;
86 {
87     struct inode *pip, *ip;
88     extern struct osi_dev cacheDev;
89     register int code = 0;
90
91     *perror = 0;
92
93     AFS_STATCNT(igetinode);
94
95     if ((code = getinode(vfsp, dev, inode, &ip, perror)) != 0) {
96         return(code);
97     }
98
99     if (ip->i_mode == 0) {
100         /* Not an allocated inode */
101         iforget(ip);        
102         return(ENOENT);
103     }
104
105     if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
106         iput(ip);
107         return(ENOENT);
108     }
109
110     *ipp = ip;
111     return(0);
112 }
113
114 iforget(ip)
115 struct inode *ip;
116 {
117     struct vnode *vp = ITOV(ip);
118
119     AFS_STATCNT(iforget);
120
121     VN_LOCK(vp);
122     /* this whole thing is too wierd.  Why??? XXX */
123     if (vp->v_usecount == 1) {
124         VN_UNLOCK(vp);
125         idrop(ip);
126     } else {
127         VN_UNLOCK(vp);
128     }
129 }
130
131 /*
132  * icreate system call -- create an inode
133  */
134 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, retval)
135      long *retval;
136      long dev, near_inode, param1, param2, param3, param4;
137 {
138     int dummy, err=0;
139     struct inode *ip, *newip;
140     register int code;
141     struct vnode *vp;
142     
143     AFS_STATCNT(afs_syscall_icreate);
144     
145     if (!afs_suser())
146         return(EPERM);
147
148     code = getinode(0, (dev_t)dev, 2, &ip, &dummy);
149     if (code) {
150         return(ENOENT);
151     }
152     code = ialloc(ip, (ino_t)near_inode, 0, &newip);
153     iput(ip);
154     if (code) {
155         return(code);
156     }
157     IN_LOCK(newip);
158     newip->i_flag |= IACC|IUPD|ICHG;
159     
160     newip->i_nlink = 1;
161
162     newip->i_mode = IFREG;
163     
164     IN_UNLOCK(newip);
165     vp = ITOV(newip);
166     VN_LOCK(vp);
167     vp->v_type = VREG;
168     VN_UNLOCK(vp);
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 = (((param2 >> 16) & 0x1f) << 27) +
193             (((param4 >> 16) & 0x1f) << 22) + 
194                 (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 afs_syscall_iopen(dev, inode, usrmod, retval)
208      long *retval;
209      int dev, inode, usrmod;
210 {
211     struct file *fp;
212     struct inode *ip;
213     struct vnode *vp = (struct vnode *)0;
214     int dummy;
215     int fd;
216     extern struct fileops vnops;
217     register int code;
218 #ifdef AFS_DUX50_ENV
219     struct ufile_entry *fe;
220 #endif
221     
222     AFS_STATCNT(afs_syscall_iopen);
223     
224     if (!afs_suser())
225         return(EPERM);
226
227     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
228     if (code) {
229         return(code);
230     }
231 #ifdef AFS_DUX50_ENV
232     if ((code = falloc(&fp, &fd, &fe)) != 0) {
233         iput(ip);
234         return(code);
235     }
236 #else
237     if ((code = falloc(&fp, &fd)) != 0) {
238         iput(ip);
239         return(code);
240     }
241 #endif
242     IN_UNLOCK(ip);
243     
244     FP_LOCK(fp);
245     fp->f_flag = (usrmod-FOPEN) & FMASK;
246     fp->f_type = DTYPE_VNODE;
247     fp->f_ops = &vnops;
248     fp->f_data = (caddr_t)ITOV(ip);
249     
250     FP_UNLOCK(fp);
251 #ifdef AFS_DUX50_ENV
252     u_set_fe(fd, fe, fp, &u.u_file_state);
253 #else
254     U_FD_SET(fd, fp, &u.u_file_state);
255 #endif
256     *retval = fd;
257     return(0);
258 }
259
260
261 /*
262  * Support for iinc() and idec() system calls--increment or decrement
263  * count on inode.
264  * Restricted to super user.
265  * Only VICEMAGIC type inodes.
266  */
267 afs_syscall_iincdec(dev, inode, inode_p1, amount)
268      int dev, inode, inode_p1, amount;
269 {
270     int dummy;
271     struct inode *ip;
272     register int code;
273     
274     if (!afs_suser())
275         return(EPERM);
276
277     code = igetinode(0, (dev_t)dev, (ino_t)inode, &ip, &dummy);
278     if (code) {
279         return(code);
280     }
281     if (!IS_VICEMAGIC(ip)) {
282         return(EPERM);
283     } else if (ip->i_vicep1 != inode_p1) {
284         return(ENXIO);
285     }
286     ip->i_nlink += amount;
287     if (ip->i_nlink == 0) {
288         CLEAR_VICEMAGIC(ip);
289     }
290     ip->i_flag |= ICHG;
291     iput(ip);
292     return(0);
293 }