PageRenderTime 62ms CodeModel.GetById 17ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/core/10.4/fusefs/fuse_node.c

http://macfuse.googlecode.com/
C | 249 lines | 187 code | 44 blank | 18 comment | 48 complexity | 51f79e54e2438c6a8ab61bb729e4daad 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_internal.h"
  8#include "fuse_ipc.h"
  9#include "fuse_locking.h"
 10#include "fuse_node.h"
 11#include "fuse_sysctl.h"
 12
 13void
 14FSNodeScrub(struct fuse_vnode_data *fvdat)
 15{
 16    lck_mtx_free(fvdat->createlock, fuse_lock_group);
 17#if M_MACFUSE_ENABLE_TSLOCKING
 18    lck_rw_free(fvdat->nodelock, fuse_lock_group);
 19    lck_rw_free(fvdat->truncatelock, fuse_lock_group);
 20#endif
 21    fvdat->fMagic = kFSNodeBadMagic;
 22}       
 23
 24errno_t
 25FSNodeGetOrCreateFileVNodeByID(vnode_t               *vnPtr,
 26                               uint32_t               flags,
 27                               struct fuse_entry_out *feo,
 28                               mount_t                mp,
 29                               vnode_t                dvp,
 30                               vfs_context_t          context,
 31                               uint32_t              *oflags)
 32{
 33    int   err;
 34    int   junk;
 35
 36    vnode_t  vn    = NULLVP;
 37    HNodeRef hn    = NULL;
 38    vnode_t  dirVN = NULLVP;
 39
 40    struct fuse_vnode_data *fvdat   = NULL;
 41    struct fuse_data       *mntdata = NULL;
 42    fuse_device_t           dummy_device;
 43
 44    enum vtype vtyp = IFTOVT(feo->attr.mode);
 45
 46    if ((vtyp >= VBAD) || (vtyp < 0) || (vtyp == VNON)) {
 47        return EINVAL;
 48    }
 49
 50    int      markroot   = (flags & FN_IS_ROOT) ? TRUE : FALSE;
 51    uint64_t size       = (flags & FN_IS_ROOT) ? 0    : feo->attr.size;
 52    uint32_t rdev       = (flags & FN_IS_ROOT) ? 0    : feo->attr.rdev;
 53    uint64_t generation = feo->generation;
 54
 55    mntdata = fuse_get_mpdata(mp);
 56    dummy_device = mntdata->fdev;
 57
 58    err = HNodeLookupCreatingIfNecessary(dummy_device, feo->nodeid,
 59                                         0 /* fork index */, &hn, &vn);
 60    if ((err == 0) && (vn == NULL)) {
 61
 62        struct vnode_fsparam params;
 63
 64        fvdat = (struct fuse_vnode_data *)FSNodeGenericFromHNode(hn);
 65
 66        if (!fvdat->fInitialised) {
 67
 68            /* check */
 69            fvdat->fMagic       = kFSNodeMagic;
 70            fvdat->fInitialised = TRUE;
 71
 72            /* self */
 73            fvdat->vp           = NULLVP; /* hold on */
 74            fvdat->nodeid       = feo->nodeid;
 75            fvdat->generation   = generation;
 76
 77            /* parent */
 78            fvdat->parentvp     = dvp;
 79            if (dvp) {
 80                fvdat->parent_nodeid = VTOI(dvp);
 81            } else {
 82                fvdat->parent_nodeid = 0;
 83            }
 84
 85            /* I/O */
 86            {
 87                int k;
 88                for (k = 0; k < FUFH_MAXTYPE; k++) {
 89                    FUFH_USE_RESET(&(fvdat->fufh[k]));
 90                }
 91            }
 92
 93            /* flags */
 94            fvdat->flag         = flags;
 95            fvdat->c_flag       = 0;
 96
 97            /* meta */
 98
 99            /* XXX: truncation */
100            fvdat->entry_valid.tv_sec  = (time_t)feo->entry_valid;
101
102            fvdat->entry_valid.tv_nsec = feo->entry_valid_nsec;
103
104            /* XXX: truncation */
105            fvdat->attr_valid.tv_sec   = (time_t)feo->attr_valid;
106
107            fvdat->attr_valid.tv_nsec  = feo->attr_valid_nsec;
108
109            /* XXX: truncation */
110            fvdat->modify_time.tv_sec  = (time_t)feo->attr.mtime;
111
112            fvdat->modify_time.tv_nsec = feo->attr.mtimensec;
113
114            fvdat->filesize            = size;
115            fvdat->nlookup             = 0;
116            fvdat->vtype               = vtyp;
117
118            /* locking */
119            fvdat->createlock = lck_mtx_alloc_init(fuse_lock_group,
120                                                   fuse_lock_attr);
121            fvdat->creator = current_thread();
122#if M_MACFUSE_ENABLE_TSLOCKING
123            fvdat->nodelock = lck_rw_alloc_init(fuse_lock_group,
124                                                fuse_lock_attr);
125            fvdat->nodelockowner = NULL;
126            fvdat->truncatelock  = lck_rw_alloc_init(fuse_lock_group,
127                                                     fuse_lock_attr);
128#endif
129        }
130
131        if (err == 0) {
132            params.vnfs_mp     = mp;
133            params.vnfs_vtype  = vtyp;
134            params.vnfs_str    = NULL;
135            params.vnfs_dvp    = dvp; /* NULLVP for the root vnode */
136            params.vnfs_fsnode = hn;
137
138#if M_MACFUSE_ENABLE_SPECFS
139            if ((vtyp == VBLK) || (vtyp == VCHR)) {
140                params.vnfs_vops = fuse_spec_operations;
141                params.vnfs_rdev = (dev_t)rdev;
142#else
143            if (0) {
144#endif
145#if M_MACFUSE_ENABLE_FIFOFS
146            } else if (vtyp == VFIFO) {
147                params.vnfs_vops = fuse_fifo_operations;
148                params.vnfs_rdev = 0;
149                (void)rdev;
150#else
151            } else if (0) {
152#endif
153            } else {
154                params.vnfs_vops = fuse_vnode_operations;
155                params.vnfs_rdev = 0;
156                (void)rdev;
157            }
158
159            params.vnfs_marksystem = FALSE;
160            params.vnfs_cnp        = NULL;
161            params.vnfs_flags      = VNFS_NOCACHE | VNFS_CANTCACHE;
162            params.vnfs_filesize   = size;
163            params.vnfs_markroot   = markroot;
164
165            err = vnode_create(VNCREATE_FLAVOR, (uint32_t)sizeof(params),
166                               &params, &vn);
167        }
168
169        if (err == 0) {
170            if (markroot == TRUE) {
171                fvdat->parentvp = vn;
172            } else {
173                fvdat->parentvp = dvp;
174            }
175            if (oflags) {
176                *oflags |= MAKEENTRY;
177            }
178            HNodeAttachVNodeSucceeded(hn, 0 /* forkIndex */, vn);
179            FUSE_OSAddAtomic(1, (SInt32 *)&fuse_vnodes_current);
180        } else {
181            if (HNodeAttachVNodeFailed(hn, 0 /* forkIndex */)) {
182                FSNodeScrub(fvdat);
183                HNodeScrubDone(hn);
184            }
185        }
186    }
187
188    if (err == 0) {
189        if (vnode_vtype(vn) != vtyp) {
190            IOLog("MacFUSE: vnode changed type behind us (old=%d, new=%d)\n",
191                  vnode_vtype(vn), vtyp);
192            fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT);
193            vnode_put(vn);
194            err = EIO;
195        } else if (VTOFUD(vn)->generation != generation) {
196            IOLog("MacFUSE: vnode changed generation\n");
197            fuse_internal_vnode_disappear(vn, context, REVOKE_SOFT);
198            vnode_put(vn);
199            err = ESTALE;
200        }
201    }
202
203    if (err == 0) {
204        *vnPtr = vn;
205        /* Need VT_MACFUSE from xnu */
206        vnode_settag(vn, VT_OTHER);
207    }
208
209    if (dirVN != NULL) {
210        junk = vnode_put(dirVN);
211        /* assert(junk == 0); */
212    }
213
214    /* assert((err == 0) == (*vnPtr != NULL); */
215
216    return err;
217}
218
219int
220fuse_vget_i(vnode_t               *vpp,
221            uint32_t               flags, 
222            struct fuse_entry_out *feo,
223            struct componentname  *cnp,
224            vnode_t                dvp,
225            mount_t                mp,
226            vfs_context_t          context)
227{
228    int err = 0;
229
230    if (!feo) {
231        return EINVAL;
232    }
233
234    err = FSNodeGetOrCreateFileVNodeByID(vpp, flags, feo, mp, dvp,
235                                         context, NULL);
236    if (err) {
237        return err;
238    }
239
240    if (!fuse_isnovncache_mp(mp) && (cnp->cn_flags & MAKEENTRY)) {
241        fuse_vncache_enter(dvp, *vpp, cnp);
242    }
243
244/* found: */
245
246    VTOFUD(*vpp)->nlookup++;
247
248    return 0;
249}