1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
5 * Author: Phil Schwan <phil@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
22 * Darwin porting library
23 * Make things easy to port
25 #include <mach/mach_types.h>
28 #include <sys/malloc.h>
30 #include <sys/mount.h>
32 #include <sys/filedesc.h>
33 #include <sys/namei.h>
35 #define DEBUG_SUBSYSTEM S_LNET
37 #include <libcfs/libcfs.h>
38 #include <libcfs/kp30.h>
41 * Kernel APIs for file system in xnu
47 #include <sys/vnode.h>
49 extern int vn_rdwr(enum uio_rw, vnode_t, caddr_t, int, off_t, enum uio_seg, int, kauth_cred_t, int *, proc_t);
51 /* vnode_size() is not exported */
53 vnode_size(vnode_t vp, off_t *sizep, vfs_context_t ctx)
59 VATTR_WANTED(&va, va_data_size);
60 error = vnode_getattr(vp, &va, ctx);
62 *sizep = va.va_data_size;
69 * kern_file_*() are not safe for multi-threads now,
70 * however, we need them only for tracefiled, so it's
71 * not so important to implement for MT.
74 kern_file_size(struct cfs_kern_file *fp, off_t *psize)
79 error = vnode_size(fp->f_vp, &size, fp->f_ctxt);
88 struct cfs_kern_file *
89 kern_file_open(const char * filename, int uflags, int mode, int *err)
91 struct cfs_kern_file *fp;
95 fp = (struct cfs_kern_file *)_MALLOC(sizeof(struct cfs_kern_file), M_TEMP, M_WAITOK);
101 fp->f_flags = FFLAGS(uflags);
102 fp->f_ctxt = vfs_context_create(NULL);
104 if ((error = vnode_open(filename, fp->f_flags,
105 mode, 0, &vp, fp->f_ctxt))){
119 kern_file_close(struct cfs_kern_file *fp)
121 vnode_close(fp->f_vp, fp->f_flags, fp->f_ctxt);
122 vfs_context_rele(fp->f_ctxt);
129 kern_file_read(struct cfs_kern_file *fp, void *buf, size_t nbytes, loff_t *pos)
131 struct proc *p = current_proc();
136 assert(fp != NULL && fp->f_vp != NULL);
138 error = vn_rdwr(UIO_READ, fp->f_vp, buf, nbytes, *pos,
139 UIO_SYSSPACE32, 0, vfs_context_ucred(fp->f_ctxt), &resid, p);
140 if ((error) || (nbytes == resid)) {
145 *pos += nbytes - resid;
147 return (int)(nbytes - resid);
151 kern_file_write(struct cfs_kern_file *fp, void *buf, size_t nbytes, loff_t *pos)
153 struct proc *p = current_proc();
158 assert(fp != NULL && fp->f_vp != NULL);
160 error = vn_rdwr(UIO_WRITE, fp->f_vp, buf, nbytes, *pos,
161 UIO_SYSSPACE32, 0, vfs_context_ucred(fp->f_ctxt), &resid, p);
162 if ((error) || (nbytes == resid)) {
167 *pos += nbytes - resid;
169 return (int)(nbytes - resid);
174 kern_file_sync (struct cfs_kern_file *fp)
176 return VNOP_FSYNC(fp->f_vp, MNT_WAIT, fp->f_ctxt);
179 #else /* !__DARWIN8__ */
182 kern_file_size(struct file *fp, off_t *size)
184 struct vnode *vp = (struct vnode *)fp->f_data;
188 rc = vn_stat(vp, &sb, current_proc());
198 kern_file_open(const char * filename, int flags, int mode, int *err)
202 register struct vnode *vp;
204 extern struct fileops vnops;
210 MALLOC_ZONE(fp, cfs_file_t *, sizeof(cfs_file_t), M_FILE, M_WAITOK|M_ZERO);
211 bzero(fp, sizeof(cfs_file_t));
213 LIST_CIRCLE(fp, f_list);
214 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (char *)filename, current_proc());
215 if ((rc = vn_open(&nd, flags, mode)) != 0){
216 printf("filp_open failed at (%d)\n", rc);
219 FREE_ZONE(fp, sizeof *fp, M_FILE);
224 fp->f_flag = flags & FMASK;
225 fp->f_type = DTYPE_VNODE;
227 fp->f_data = (caddr_t)vp;
228 fp->f_cred = current_proc()->p_ucred;
230 * Hold cred to increase reference
234 * vnode is locked inside vn_open for lookup,
235 * we should release the lock before return
237 VOP_UNLOCK(vp, 0, current_proc());
244 frele_internal(cfs_file_t *fp)
246 if (fp->f_count == (short)0xffff)
247 panic("frele of lustre: stale");
248 if (--fp->f_count < 0)
249 panic("frele of lustre: count < 0");
250 return ((int)fp->f_count);
254 kern_file_close (cfs_file_t *fp)
263 if (frele_internal(fp) > 0)
265 vp = (struct vnode *)fp->f_data;
266 (void )vn_close(vp, fp->f_flag, fp->f_cred, current_proc());
269 * Dont use ffree to release fp!!!!
270 * ffree will call LIST_REMOVE(fp),
271 * but fp is not in any list, this will
276 if (cred != NOCRED) {
282 memset(fp, 0xff, sizeof *fp);
283 fp->f_count = (short)0xffff;
284 FREE_ZONE(fp, sizeof *fp, M_FILE);
290 extern void bwillwrite(void);
293 * Write buffer to filp inside kernel
296 kern_file_write (cfs_file_t *fp, void *buf, size_t nbyte, loff_t *pos)
300 struct proc *p = current_proc();
305 aiov.iov_base = (void *)(uintptr_t)buf;
306 aiov.iov_len = nbyte;
307 auio.uio_iov = &aiov;
310 auio.uio_offset = *pos;
312 * Liang: If don't set FOF_OFFSET, vn_write()
313 * will use fp->f_offset as the the real offset.
318 auio.uio_offset = (off_t)-1;
321 auio.uio_resid = nbyte;
322 auio.uio_rw = UIO_WRITE;
323 auio.uio_segflg = UIO_SYSSPACE;
328 if (fp->f_type == DTYPE_VNODE)
329 bwillwrite(); /* empty stuff now */
330 if ((error = fo_write(fp, &auio, fp->f_cred, flags, p))) {
331 if (auio.uio_resid != cnt && (error == ERESTART ||\
332 error == EINTR || error == EWOULDBLOCK))
334 /* The socket layer handles SIGPIPE */
335 if (error == EPIPE && fp->f_type != DTYPE_SOCKET)
342 cnt -= auio.uio_resid;
349 * Read from filp inside kernel
352 kern_file_read (cfs_file_t *fp, void *buf, size_t nbyte, loff_t *pos)
356 struct proc *p = current_proc();
361 aiov.iov_base = (caddr_t)buf;
362 aiov.iov_len = nbyte;
363 auio.uio_iov = &aiov;
366 auio.uio_offset = *pos;
369 auio.uio_offset = (off_t)-1;
372 auio.uio_resid = nbyte;
373 auio.uio_rw = UIO_READ;
374 auio.uio_segflg = UIO_SYSSPACE;
379 if ((error = fo_read(fp, &auio, fp->f_cred, flags, p)) != 0) {
380 if (auio.uio_resid != cnt && (error == ERESTART ||
381 error == EINTR || error == EWOULDBLOCK))
388 cnt -= auio.uio_resid;
396 kern_file_sync (cfs_file_t *fp)
398 struct vnode *vp = (struct vnode *)fp->f_data;
399 struct proc *p = current_proc();
404 if (fref(fp) == -1) {
408 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
409 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
410 VOP_UNLOCK(vp, 0, p);
417 #endif /* !__DARWIN8__ */
419 struct posix_acl *posix_acl_alloc(int count, int flags)
421 static struct posix_acl acl;
426 * XXX Liang: I've not converted all of them,
429 int cfs_oflags2univ(int flags)
433 f = flags & O_ACCMODE;
434 f |= (flags & O_CREAT) ? CFS_O_CREAT: 0;
435 f |= (flags & O_TRUNC) ? CFS_O_TRUNC: 0;
436 f |= (flags & O_EXCL) ? CFS_O_EXCL: 0;
437 f |= (flags & O_NONBLOCK) ? CFS_O_NONBLOCK: 0;
438 f |= (flags & O_APPEND) ? CFS_O_APPEND: 0;
439 f |= (flags & O_NOFOLLOW) ? CFS_O_NOFOLLOW: 0;
440 f |= (flags & O_SYNC)? CFS_O_SYNC: 0;
445 * XXX Liang: we don't need it in OSX.
446 * But it should be implemented anyway.
448 int cfs_univ2oflags(int flags)