/core/10.5/fusefs/fuse_file.c
C | 167 lines | 122 code | 27 blank | 18 comment | 20 complexity | 4df3a862d9d68e617439918508aab337 MD5 | raw file
1/* 2 * Copyright (C) 2006-2008 Google. All Rights Reserved. 3 * Amit Singh <singh@> 4 */ 5 6#include "fuse.h" 7#include "fuse_file.h" 8#include "fuse_internal.h" 9#include "fuse_ipc.h" 10#include "fuse_node.h" 11#include "fuse_sysctl.h" 12 13/* 14 * Because of the vagaries of how a filehandle can be used, we try not to 15 * be too smart in here (we try to be smart elsewhere). It is required that 16 * you come in here only if you really do not have the said filehandle--else 17 * we panic. 18 */ 19int 20fuse_filehandle_get(vnode_t vp, 21 vfs_context_t context, 22 fufh_type_t fufh_type, 23 int mode) 24{ 25 struct fuse_dispatcher fdi; 26 struct fuse_open_in *foi; 27 struct fuse_open_out *foo; 28 struct fuse_filehandle *fufh; 29 struct fuse_vnode_data *fvdat = VTOFUD(vp); 30 31 int err = 0; 32 int isdir = 0; 33 int oflags = 0; 34 int op = FUSE_OPEN; 35 36 fuse_trace_printf("fuse_filehandle_get(vp=%p, fufh_type=%d, mode=%x)\n", 37 vp, fufh_type, mode); 38 39 fufh = &(fvdat->fufh[fufh_type]); 40 41 if (FUFH_IS_VALID(fufh)) { 42 panic("MacFUSE: filehandle_get called despite valid fufh (type=%d)", 43 fufh_type); 44 /* NOTREACHED */ 45 } 46 47 /* 48 * Note that this means we are effectively FILTERING OUT open() flags. 49 */ 50 (void)mode; 51 oflags = fuse_filehandle_xlate_to_oflags(fufh_type); 52 53 if (vnode_isdir(vp)) { 54 isdir = 1; 55 op = FUSE_OPENDIR; 56 if (fufh_type != FUFH_RDONLY) { 57 IOLog("MacFUSE: non-rdonly fufh requested for directory\n"); 58 fufh_type = FUFH_RDONLY; 59 } 60 } 61 62 fdisp_init(&fdi, sizeof(*foi)); 63 fdisp_make_vp(&fdi, op, vp, context); 64 65 if (vnode_islnk(vp) && (mode & O_SYMLINK)) { 66 oflags |= O_SYMLINK; 67 } 68 69 foi = fdi.indata; 70 foi->flags = oflags; 71 72 FUSE_OSAddAtomic(1, (SInt32 *)&fuse_fh_upcall_count); 73 if ((err = fdisp_wait_answ(&fdi))) { 74#if M_MACFUSE_ENABLE_UNSUPPORTED 75 const char *vname = vnode_getname(vp); 76#endif /* M_MACFUSE_ENABLE_UNSUPPORTED */ 77 if (err == ENOENT) { 78 /* 79 * See comment in fuse_vnop_reclaim(). 80 */ 81 cache_purge(vp); 82 } 83#if M_MACFUSE_ENABLE_UNSUPPORTED 84 IOLog("MacFUSE: filehandle_get: failed for %s " 85 "(type=%d, err=%d, caller=%p)\n", 86 (vname) ? vname : "?", fufh_type, err, 87 __builtin_return_address(0)); 88 if (vname) { 89 vnode_putname(vname); 90 } 91#endif /* M_MACFUSE_ENABLE_UNSUPPORTED */ 92 if (err == ENOENT) { 93 fuse_internal_vnode_disappear(vp, context, REVOKE_SOFT); 94 } 95 return err; 96 } 97 FUSE_OSAddAtomic(1, (SInt32 *)&fuse_fh_current); 98 99 foo = fdi.answ; 100 101 fufh->fh_id = foo->fh; 102 fufh->open_count = 1; 103 fufh->open_flags = oflags; 104 fufh->fuse_open_flags = foo->open_flags; 105 fufh->aux_count = 0; 106 107 fuse_ticket_drop(fdi.tick); 108 109 return 0; 110} 111 112int 113fuse_filehandle_put(vnode_t vp, vfs_context_t context, fufh_type_t fufh_type, 114 fuse_op_waitfor_t waitfor) 115{ 116 struct fuse_dispatcher fdi; 117 struct fuse_release_in *fri; 118 struct fuse_vnode_data *fvdat = VTOFUD(vp); 119 struct fuse_filehandle *fufh = NULL; 120 121 int err = 0; 122 int isdir = 0; 123 int op = FUSE_RELEASE; 124 125 fuse_trace_printf("fuse_filehandle_put(vp=%p, fufh_type=%d)\n", 126 vp, fufh_type); 127 128 fufh = &(fvdat->fufh[fufh_type]); 129 130 if (FUFH_IS_VALID(fufh)) { 131 panic("MacFUSE: filehandle_put called on a valid fufh (type=%d)", 132 fufh_type); 133 /* NOTREACHED */ 134 } 135 136 if (fuse_isdeadfs(vp)) { 137 goto out; 138 } 139 140 if (vnode_isdir(vp)) { 141 op = FUSE_RELEASEDIR; 142 isdir = 1; 143 } 144 145 fdisp_init(&fdi, sizeof(*fri)); 146 fdisp_make_vp(&fdi, op, vp, context); 147 fri = fdi.indata; 148 fri->fh = fufh->fh_id; 149 fri->flags = fufh->open_flags; 150 151 if (waitfor == FUSE_OP_FOREGROUNDED) { 152 if ((err = fdisp_wait_answ(&fdi))) { 153 goto out; 154 } else { 155 fuse_ticket_drop(fdi.tick); 156 } 157 } else { 158 fuse_insert_callback(fdi.tick, NULL); 159 fuse_insert_message(fdi.tick); 160 } 161 162out: 163 FUSE_OSAddAtomic(-1, (SInt32 *)&fuse_fh_current); 164 fuse_invalidate_attr(vp); 165 166 return err; 167}