Whamcloud - gitweb
* Landed portals:b_port_step as follows...
[fs/lustre-release.git] / lnet / libcfs / darwin / darwin-fs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002 Cluster File Systems, Inc.
5  * Author: Phil Schwan <phil@clusterfs.com>
6  *
7  * This file is part of Lustre, http://www.lustre.org.
8  *
9  * Lustre is free software; you can redistribute it and/or
10  * modify it under the terms of version 2 of the GNU General Public
11  * License as published by the Free Software Foundation.
12  *
13  * Lustre is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Lustre; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * Darwin porting library
23  * Make things easy to port
24  */
25 #include <mach/mach_types.h>
26 #include <string.h>
27 #include <sys/file.h>
28 #include <sys/malloc.h>
29 #include <sys/conf.h>
30 #include <sys/vnode.h>
31 #include <sys/mount.h>
32 #include <sys/uio.h>
33 #include <sys/filedesc.h>
34 #include <sys/namei.h>
35
36 #define DEBUG_SUBSYSTEM S_PORTALS
37
38 #include <libcfs/libcfs.h>
39 #include <libcfs/kp30.h>
40
41 /*
42  * Kernel APIs for file system in xnu
43  *
44  * Public functions
45  */
46 int
47 filp_node_size(struct file *fp, off_t *size)
48 {
49         struct vnode *vp = (struct vnode *)fp->f_data;
50         struct stat sb;
51         int     rc;
52
53         rc = vn_stat(vp, &sb, current_proc());
54         if (rc) {
55                 *size = 0;
56                 return rc;
57         }
58         *size = sb.st_size;
59         return 0;
60 }
61
62 cfs_file_t *
63 filp_open(const char * filename, int flags, int mode, int *err)
64 {
65         struct nameidata nd;
66         register cfs_file_t     *fp;
67         register struct vnode   *vp;
68         cfs_file_t              *nfp;
69         int                     rc;
70         extern struct fileops   vnops;
71         extern int nfiles;
72         CFS_DECL_CONE_DATA;
73
74         CFS_CONE_IN;
75         nfiles++;
76         MALLOC_ZONE(nfp, cfs_file_t *, sizeof(cfs_file_t), M_FILE, M_WAITOK|M_ZERO);
77         bzero(nfp, sizeof(cfs_file_t));
78         nfp->f_count = 1;
79         fp = nfp;
80         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)filename, current_proc());
81         if ((rc = vn_open(&nd, flags, mode)) != 0){
82                 printf("filp_open failed at (%d)\n", rc);
83                 if (err != NULL)
84                         *err = rc;
85                 ffree(fp);
86                 CFS_CONE_EX;
87                 return NULL;
88         }
89         vp = nd.ni_vp;
90         fp->f_flag = flags & FMASK;
91         fp->f_type = DTYPE_VNODE;
92         fp->f_ops = &vnops;
93         fp->f_data = (caddr_t)vp;
94         fp->f_cred = current_proc()->p_ucred;
95         /*
96          * Hold cred to increase reference
97          */
98         crhold(fp->f_cred);
99         /*
100          * vnode is locked inside vn_open for lookup,
101          * we should release the lock before return
102          */
103         VOP_UNLOCK(vp, 0, current_proc());
104         CFS_CONE_EX;
105
106         return fp;
107 }
108
109 static int
110 frele_internal(cfs_file_t *fp)
111 {
112         if (fp->f_count == (short)0xffff)
113                 panic("frele of lustre: stale");
114         if (--fp->f_count < 0)
115                 panic("frele of lustre: count < 0");
116         return ((int)fp->f_count);
117 }
118
119 int
120 filp_close (cfs_file_t *fp)
121 {
122         struct vnode    *vp;
123         CFS_DECL_CONE_DATA;
124         
125         if (fp == NULL)
126                 return 0;
127
128         CFS_CONE_IN;
129         if (frele_internal(fp) > 0)
130                 goto out;
131         vp = (struct vnode *)fp->f_data;
132         (void )vn_close(vp, fp->f_flag, fp->f_cred, current_proc());
133         /*
134          * ffree(fp);
135          * Dont use ffree to release fp!!!!
136          * ffree will call LIST_REMOVE(fp),
137          * but fp is not in any list, this will
138          * cause kernel panic
139          */
140         struct ucred *cred;
141         cred = fp->f_cred;
142         if (cred != NOCRED) {
143                 fp->f_cred = NOCRED;
144                 crfree(cred);
145         }
146         extern int nfiles;
147         nfiles--;
148         memset(fp, 0xff, sizeof *fp);
149         fp->f_count = (short)0xffff;
150         FREE_ZONE(fp, sizeof *fp, M_FILE);
151 out:
152         CFS_CONE_EX;
153         return 0;
154 }
155
156 extern void bwillwrite(void);
157
158 /*
159  * Write buffer to filp inside kernel
160  */
161 int
162 filp_write (cfs_file_t *fp, void *buf, size_t nbyte, off_t *pos)
163 {
164         struct uio auio;
165         struct iovec aiov;
166         struct proc *p = current_proc();
167         long cnt, error = 0;
168         CFS_DECL_CONE_DATA;
169
170         aiov.iov_base = (void *)(uintptr_t)buf;
171         aiov.iov_len = nbyte;
172         auio.uio_iov = &aiov;
173         auio.uio_iovcnt = 1;
174         if (pos != NULL)
175                 auio.uio_offset = *pos;
176         else
177                 auio.uio_offset = (off_t)-1;
178         if (nbyte > INT_MAX)
179                 return (EINVAL);
180         auio.uio_resid = nbyte;
181         auio.uio_rw = UIO_WRITE;
182         auio.uio_segflg = UIO_SYSSPACE;
183         auio.uio_procp = p;
184
185         cnt = nbyte;
186         CFS_CONE_IN;
187         if (fp->f_type == DTYPE_VNODE)
188                 bwillwrite();   /* empty stuff now */
189         if ((error = fo_write(fp, &auio, fp->f_cred, 0, p))) {
190                 if (auio.uio_resid != cnt && (error == ERESTART ||\
191                     error == EINTR || error == EWOULDBLOCK))
192                         error = 0;
193                 /* The socket layer handles SIGPIPE */
194                 if (error == EPIPE && fp->f_type != DTYPE_SOCKET)
195                         psignal(p, SIGPIPE);
196         }
197         CFS_CONE_EX;
198         if (error != 0)
199                 cnt = -error;
200         else
201                 cnt -= auio.uio_resid;
202         if (pos != NULL)
203                 *pos = auio.uio_offset;
204         return cnt;
205 }
206
207 /*
208  * Read from filp inside kernel
209  */
210 int
211 filp_read (cfs_file_t *fp, void *buf, size_t nbyte, off_t *pos)
212 {
213         struct uio auio;
214         struct iovec aiov;
215         struct proc *p = current_proc();
216         long cnt, error = 0;
217         CFS_DECL_CONE_DATA;
218
219         aiov.iov_base = (caddr_t)buf;
220         aiov.iov_len = nbyte;
221         auio.uio_iov = &aiov;
222         auio.uio_iovcnt = 1;
223         if (pos != NULL)
224                 auio.uio_offset = *pos;
225         else
226                 auio.uio_offset = (off_t)-1;
227         if (nbyte > INT_MAX)
228                 return (EINVAL);
229         auio.uio_resid = nbyte;
230         auio.uio_rw = UIO_READ;
231         auio.uio_segflg = UIO_SYSSPACE;
232         auio.uio_procp = p;
233
234         cnt = nbyte;
235         CFS_CONE_IN;
236         if ((error = fo_read(fp, &auio, fp->f_cred, 0, p)) != 0) {
237                 if (auio.uio_resid != cnt && (error == ERESTART ||
238                     error == EINTR || error == EWOULDBLOCK))
239                         error = 0;
240         }
241         CFS_CONE_EX;
242         if (error != 0)
243                 cnt = -error;
244         else
245                 cnt -= auio.uio_resid;
246         if (pos != NULL)
247                 *pos = auio.uio_offset;
248
249         return cnt;
250 }
251
252 int
253 filp_fsync (cfs_file_t *fp)
254 {
255         struct vnode *vp = (struct vnode *)fp->f_data;
256         struct proc *p = current_proc();
257         int error = 0;
258         CFS_DECL_CONE_DATA;
259         
260         CFS_CONE_IN;
261         if (fref(fp) == -1) {
262                 CFS_CONE_EX;
263                 return (-EBADF);
264         }
265         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
266         error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
267         VOP_UNLOCK(vp, 0, p);
268         frele(fp);
269         CFS_CONE_EX;
270
271         return error;
272 }
273
274 int
275 ref_file(cfs_file_t *fp)
276 {
277         CFS_DECL_CONE_DATA;
278
279         CFS_CONE_IN;
280         fref(fp);
281         CFS_CONE_EX;
282         return 0;
283 }
284
285 int 
286 rele_file(cfs_file_t *fp)
287 {
288         CFS_DECL_CONE_DATA;
289
290         CFS_CONE_IN;
291         frele(fp);
292         CFS_CONE_EX;
293         return 0;
294 }
295
296 /*
297  * Private functions
298  */
299 void vrele_safe(struct vnode *nd)
300
301         CFS_DECL_CONE_DATA; 
302         
303         CFS_CONE_IN; 
304         vrele(nd); 
305         CFS_CONE_EX;
306 }
307
308 int
309 path_lookup(const char *path, unsigned int flags, struct nameidata *nd)
310 {
311         int ret = 0;
312         CFS_DECL_CONE_DATA;
313
314         CFS_CONE_IN;
315         NDINIT(nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)path, current_proc());
316         if ((ret = namei(nd)) != 0){
317                 CERROR("path_lookup fail!\n");
318         }
319         CFS_CONE_EX;
320
321         return ret;
322 }
323
324 int 
325 file_count(struct file *fp)
326 {
327         return fcount(fp);
328 }
329
330