4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
34 * libcfs/libcfs/darwin/darwin-fs.c
36 * Darwin porting library
37 * Make things easy to port
39 * Author: Phil Schwan <phil@clusterfs.com>
42 #include <mach/mach_types.h>
45 #include <sys/malloc.h>
47 #include <sys/mount.h>
49 #include <sys/filedesc.h>
50 #include <sys/namei.h>
52 #define DEBUG_SUBSYSTEM S_LNET
54 #include <libcfs/libcfs.h>
57 * Kernel APIs for file system in xnu
63 #include <sys/vnode.h>
65 extern int vn_rdwr(enum uio_rw, vnode_t, caddr_t, int, off_t, enum uio_seg, int, kauth_cred_t, int *, proc_t);
67 /* vnode_size() is not exported */
69 vnode_size(vnode_t vp, off_t *sizep, vfs_context_t ctx)
75 VATTR_WANTED(&va, va_data_size);
76 error = vnode_getattr(vp, &va, ctx);
78 *sizep = va.va_data_size;
85 * kern_file_*() are not safe for multi-threads now,
86 * however, we need them only for tracefiled, so it's
87 * not so important to implement for MT.
90 kern_file_size(struct cfs_kern_file *fp, off_t *psize)
95 error = vnode_size(fp->f_vp, &size, fp->f_ctxt);
104 struct cfs_kern_file *
105 kern_file_open(const char * filename, int uflags, int mode, int *err)
107 struct cfs_kern_file *fp;
111 fp = (struct cfs_kern_file *)_MALLOC(sizeof(struct cfs_kern_file), M_TEMP, M_WAITOK);
117 fp->f_flags = FFLAGS(uflags);
118 fp->f_ctxt = vfs_context_create(NULL);
120 if ((error = vnode_open(filename, fp->f_flags,
121 mode, 0, &vp, fp->f_ctxt))){
135 kern_file_close(struct cfs_kern_file *fp)
137 vnode_close(fp->f_vp, fp->f_flags, fp->f_ctxt);
138 vfs_context_rele(fp->f_ctxt);
145 kern_file_read(struct cfs_kern_file *fp, void *buf, size_t nbytes, loff_t *pos)
147 struct proc *p = current_proc();
152 assert(fp != NULL && fp->f_vp != NULL);
154 error = vn_rdwr(UIO_READ, fp->f_vp, buf, nbytes, *pos,
155 UIO_SYSSPACE32, 0, vfs_context_ucred(fp->f_ctxt), &resid, p);
156 if ((error) || (nbytes == resid)) {
161 *pos += nbytes - resid;
163 return (int)(nbytes - resid);
167 kern_file_write(struct cfs_kern_file *fp, void *buf, size_t nbytes, loff_t *pos)
169 struct proc *p = current_proc();
174 assert(fp != NULL && fp->f_vp != NULL);
176 error = vn_rdwr(UIO_WRITE, fp->f_vp, buf, nbytes, *pos,
177 UIO_SYSSPACE32, 0, vfs_context_ucred(fp->f_ctxt), &resid, p);
178 if ((error) || (nbytes == resid)) {
183 *pos += nbytes - resid;
185 return (int)(nbytes - resid);
190 kern_file_sync (struct cfs_kern_file *fp)
192 return VNOP_FSYNC(fp->f_vp, MNT_WAIT, fp->f_ctxt);
195 #else /* !__DARWIN8__ */
198 kern_file_size(struct file *fp, off_t *size)
200 struct vnode *vp = (struct vnode *)fp->f_data;
204 rc = vn_stat(vp, &sb, current_proc());
214 kern_file_open(const char * filename, int flags, int mode, int *err)
218 register struct vnode *vp;
220 extern struct fileops vnops;
226 MALLOC_ZONE(fp, cfs_file_t *, sizeof(cfs_file_t), M_FILE, M_WAITOK|M_ZERO);
227 bzero(fp, sizeof(cfs_file_t));
229 LIST_CIRCLE(fp, f_list);
230 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)filename, current_proc());
231 if ((rc = vn_open(&nd, flags, mode)) != 0){
232 printf("filp_open failed at (%d)\n", rc);
235 FREE_ZONE(fp, sizeof *fp, M_FILE);
240 fp->f_flag = flags & FMASK;
241 fp->f_type = DTYPE_VNODE;
243 fp->f_data = (caddr_t)vp;
244 fp->f_cred = current_proc()->p_ucred;
246 * Hold cred to increase reference
250 * vnode is locked inside vn_open for lookup,
251 * we should release the lock before return
253 VOP_UNLOCK(vp, 0, current_proc());
260 frele_internal(cfs_file_t *fp)
262 if (fp->f_count == (short)0xffff)
263 panic("frele of lustre: stale");
264 if (--fp->f_count < 0)
265 panic("frele of lustre: count < 0");
266 return ((int)fp->f_count);
270 kern_file_close (cfs_file_t *fp)
279 if (frele_internal(fp) > 0)
281 vp = (struct vnode *)fp->f_data;
282 (void )vn_close(vp, fp->f_flag, fp->f_cred, current_proc());
285 * Dont use ffree to release fp!!!!
286 * ffree will call LIST_REMOVE(fp),
287 * but fp is not in any list, this will
292 if (cred != NOCRED) {
298 memset(fp, 0xff, sizeof *fp);
299 fp->f_count = (short)0xffff;
300 FREE_ZONE(fp, sizeof *fp, M_FILE);
306 extern void bwillwrite(void);
309 * Write buffer to filp inside kernel
312 kern_file_write (cfs_file_t *fp, void *buf, size_t nbyte, loff_t *pos)
316 struct proc *p = current_proc();
321 aiov.iov_base = (void *)(uintptr_t)buf;
322 aiov.iov_len = nbyte;
323 auio.uio_iov = &aiov;
326 auio.uio_offset = *pos;
328 * Liang: If don't set FOF_OFFSET, vn_write()
329 * will use fp->f_offset as the the real offset.
334 auio.uio_offset = (off_t)-1;
337 auio.uio_resid = nbyte;
338 auio.uio_rw = UIO_WRITE;
339 auio.uio_segflg = UIO_SYSSPACE;
344 if (fp->f_type == DTYPE_VNODE)
345 bwillwrite(); /* empty stuff now */
346 if ((error = fo_write(fp, &auio, fp->f_cred, flags, p))) {
347 if (auio.uio_resid != cnt && (error == ERESTART ||\
348 error == EINTR || error == EWOULDBLOCK))
350 /* The socket layer handles SIGPIPE */
351 if (error == EPIPE && fp->f_type != DTYPE_SOCKET)
358 cnt -= auio.uio_resid;
365 * Read from filp inside kernel
368 kern_file_read (cfs_file_t *fp, void *buf, size_t nbyte, loff_t *pos)
372 struct proc *p = current_proc();
377 aiov.iov_base = (caddr_t)buf;
378 aiov.iov_len = nbyte;
379 auio.uio_iov = &aiov;
382 auio.uio_offset = *pos;
385 auio.uio_offset = (off_t)-1;
388 auio.uio_resid = nbyte;
389 auio.uio_rw = UIO_READ;
390 auio.uio_segflg = UIO_SYSSPACE;
395 if ((error = fo_read(fp, &auio, fp->f_cred, flags, p)) != 0) {
396 if (auio.uio_resid != cnt && (error == ERESTART ||
397 error == EINTR || error == EWOULDBLOCK))
404 cnt -= auio.uio_resid;
412 kern_file_sync (cfs_file_t *fp)
414 struct vnode *vp = (struct vnode *)fp->f_data;
415 struct proc *p = current_proc();
420 if (fref(fp) == -1) {
424 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
425 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
426 VOP_UNLOCK(vp, 0, p);
433 #endif /* !__DARWIN8__ */
435 struct posix_acl *posix_acl_alloc(int count, int flags)
437 static struct posix_acl acl;
442 * XXX Liang: I've not converted all of them,
445 int cfs_oflags2univ(int flags)
449 f = flags & O_NOACCESS;
450 f |= (flags & O_CREAT) ? CFS_O_CREAT: 0;
451 f |= (flags & O_TRUNC) ? CFS_O_TRUNC: 0;
452 f |= (flags & O_EXCL) ? CFS_O_EXCL: 0;
453 f |= (flags & O_NONBLOCK) ? CFS_O_NONBLOCK: 0;
454 f |= (flags & O_APPEND) ? CFS_O_APPEND: 0;
455 f |= (flags & O_NOFOLLOW) ? CFS_O_NOFOLLOW: 0;
456 f |= (flags & O_SYNC)? CFS_O_SYNC: 0;
461 * XXX Liang: we don't need it in OSX.
462 * But it should be implemented anyway.
464 int cfs_univ2oflags(int flags)