📄 vnode.c
字号:
struct proc *p; } */ *ap;{ struct vnode *vp = ap->a_vp; struct vnode *lowervp = VP_TO_WRAPFS(vp) ? WRAPFS_VP_TO_LOWERVP(vp) : NULL; int error = 0; fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); if (vp->v_type == VNON || lowervp == NULL) { error = EINVAL; /* xxx - is this right */ goto retn; } /* create object for higher level vnode */ error = vop_stdcreatevobject(ap); if (error) goto retn; /* now create the object for the lower layer */ error = VOP_CREATEVOBJECT(lowervp, ap->a_cred, ap->a_p); if (error) { struct vop_destroyvobject_args destroy; destroy.a_vp = vp; vop_stddestroyvobject(&destroy); }retn: print_location(); return (error);}#else /* not FIST_FILTER_DATA *//* let the underlying filesystem do the work */static intwrapfs_createvobject(ap) struct vop_createvobject_args /* { struct vnode *vp; struct ucred *cred; struct proc *p; } */ *ap;{ struct vnode *vp = ap->a_vp; struct vnode *lowervp = VP_TO_WRAPFS(vp) ? WRAPFS_VP_TO_LOWERVP(vp) : NULL; int error = 0; fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); if (vp->v_type == VNON || lowervp == NULL) { goto retn; /* returns 0! */ } error = VOP_CREATEVOBJECT(lowervp, ap->a_cred, ap->a_p); if (error) goto retn; vp->v_flag |= VOBJBUF;retn: print_location(); return (error);}#endif /* not FIST_FILTER_DATA */#ifdef FIST_FILTER_DATA /* * if FIST_FILTER_DATA, then if the object of the higher vnode * or lower level vnode exists, then delete them */static intwrapfs_destroyvobject(ap) struct vop_destroyvobject_args /* { struct vnode *vp; } */ *ap;{ int error = 0; struct vnode *vp = ap->a_vp; struct vnode *lvp = WRAPFS_VP_TO_LOWERVP(vp); vm_object_t obj = vp->v_object; vm_object_t lower_obj; struct vop_destroyvobject_args destroy; fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); /* if the lower vnode exists destroy its object */ if (lvp) { error = VOP_GETVOBJECT(lvp, &lower_obj); if (!error) error = VOP_DESTROYVOBJECT(lvp); if (error) { printk(" error destroying the lowervp \n"); } } destroy.a_vp = vp; vop_stddestroyvobject(&destroy); print_location(); return (error);}#else /* not FIST_FILTER_DATA *//* do nothing */static intwrapfs_destroyvobject(ap) struct vop_destroyvobject_args /* { struct vnode *vp; } */ *ap;{ int error = 0; struct vnode *vp = ap->a_vp; fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); vp->v_flag &= ~VOBJBUF; print_location(); return (error);}#endif /* not FIST_FILTER_DATA */#ifdef FIST_FILTER_DATAstatic intwrapfs_getvobject(ap) struct vop_getvobject_args /* { struct vnode *vp; struct vm_object **objpp; } */ *ap;{ struct vnode *vp = ap->a_vp; struct vnode *lowervp = WRAPFS_VP_TO_LOWERVP(ap->a_vp); struct vm_object **objpp = ap->a_objpp; fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); /* XXX hack */ if (lowervp == NULL) return EINVAL; if (objpp) *objpp = vp->v_object; print_location(); return (vp->v_object ? 0 : EINVAL);}#else /* not FIST_FILTER_DATA */static intwrapfs_getvobject(ap) struct vop_getvobject_args /* { struct vnode *vp; struct vm_object **objpp; } */ *ap;{ struct vnode *lvp = WRAPFS_VP_TO_LOWERVP(ap->a_vp); fist_dprint(4, "FXN=%s FILE=%s LINE=%d\n",__FUNCTION__,__FILE__,__LINE__); if (lvp == NULL) return EINVAL; print_location(); return (VOP_GETVOBJECT(lvp, ap->a_objpp));}#endif /* not FIST_FILTER_DATA *//****************************************************************************/#ifdef FIST_FILTER_DATA/* * Create a page in the vnode and insert data into it. * This is used to synchronize data between the VM and read/write interface. * That that was written using write() gets pages containing the same data, so * that subsequent mmap() ops get valid data. */voidwrapfs_fill_page(vnode_t *vp, char *buf, long long offset){ vm_page_t pp; vm_offset_t kva; caddr_t ca; fist_dprint(4, "FILL_PAGE: vp=0x%x, buf=0x%x, offset=0x%x\n", (int) vp, (int) buf, buf[0], buf[1], buf[2], (int) offset); fist_dprint(1, "FILL_PAGE: vp=0x%x, buf=0x%x [%d,%d,%d], offset=0x%x\n", (int) vp, (int) buf, buf[0], buf[1], buf[2], (int) offset); pp = vm_page_grab(vp->v_object, OFF_TO_IDX(offset), VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if (!pp) { printf("vm_page_grab returned NULL for offset 0x%x!\n", (int) offset); return; } kva = vm_pager_map_page(pp); ca = (caddr_t) kva; bcopy(buf, ca, PAGE_SIZE); vm_pager_unmap_page(kva); vm_page_set_validclean(pp, 0, PAGE_SIZE); if (pp->wire_count == 0 && pp->hold_count == 0 && pp->busy == 0 && pp->flags & PG_BUSY ) { vm_page_free(pp); } /* if (pp->flags & PG_WANTED) { vm_page_activate(pp); } else { vm_page_deactivate(pp); }*/ vm_page_wakeup(pp); print_location();}static intwrapfs_read(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ /* easy mappings */ vnode_t *vp = ap->a_vp; uio_t *uiop = ap->a_uio; int ioflag = ap->a_ioflag; cred_t *cr = ap->a_cred; int error = EPERM; vnode_t *hidden_vp; uio_t temp_uio; iovec_t *temp_iovec; caddr_t current_base; int i, bytes_read; int num_pages, resid; long long start_loffset, end_loffset; long long cleartext_start_loffset, cleartext_end_loffset, current_loffset; fist_dprint(4, "fist_wrapfs_read vp %x\n", (int) vp);#ifdef FIST_DEBUG fist_print_uios("fist_wrapfs_read", uiop);#endif /* FIST_DEBUG */ cleartext_start_loffset = uiop->uio_offset; cleartext_end_loffset = uiop->uio_offset + uiop->uio_resid; start_loffset = cleartext_start_loffset & ~(PAGE_SIZE - 1); end_loffset = cleartext_end_loffset & ~(PAGE_SIZE - 1); /* if not multiple of PAGE_SIZE, then the above formula loses one page. * adjust for it */ if (cleartext_end_loffset > end_loffset) end_loffset += PAGE_SIZE; resid = end_loffset - start_loffset; num_pages = resid >> PAGE_SHIFT; fist_dprint(6, "READ: so=%d eo=%d cs=%d es=%d res=%d np=%d ps=%d\n", (int) start_loffset, (int) end_loffset, (int) cleartext_start_loffset, (int) cleartext_end_loffset, resid, num_pages, PAGE_SIZE); temp_iovec = kmem_zalloc(num_pages * sizeof(iovec_t)); for (i = 0; i < num_pages; i++) { temp_iovec[i].iov_len = PAGE_SIZE; temp_iovec[i].iov_base = kmem_zalloc(PAGE_SIZE); fist_dprint(6, "READ allocated %d address 0x%x\n", i, temp_iovec[i].iov_base); } temp_uio.uio_iov = temp_iovec; temp_uio.uio_iovcnt = num_pages; temp_uio.uio_offset = start_loffset; temp_uio.uio_segflg = UIO_SYSSPACE; temp_uio.uio_rw = uiop->uio_rw; temp_uio.uio_procp = uiop->uio_procp; temp_uio.uio_resid = resid; hidden_vp = WRAPFS_VP_TO_LOWERVP(vp); /* * pass operation to hidden filesystem, and return status */ error = VOP_READ(hidden_vp, &temp_uio, ioflag, cr); if (error) { fist_dprint(4, "VOP_READ in read returned error - not good\n"); /* XXX to be checked */ goto out_free; } current_loffset = start_loffset; for (i = 0; i < num_pages; i++) { bytes_read = PAGE_SIZE - temp_iovec[i].iov_len; if (bytes_read == 0) break; temp_iovec[i].iov_base -= bytes_read; current_base = temp_iovec[i].iov_base; /* decode the page/block */ wrapfs_decode_block( current_base, current_base, bytes_read, vp, vp->v_mount, OFF_TO_IDX(current_loffset)); /* * save the original size, for kmem_free. * no need for it w/ wrapfs; size is always PAGE_SIZE, hence this line * is commented out: * temp_iovec[i].iov_len = uiop->uio_iov[i].iov_len; */ /* treat first and last iovec separately, not all data in them is needed */ if (current_loffset + bytes_read > cleartext_end_loffset) { bytes_read = cleartext_end_loffset - current_loffset; } if (i == 0) { bytes_read -= cleartext_start_loffset - start_loffset; current_loffset += cleartext_start_loffset - start_loffset; current_base += cleartext_start_loffset - start_loffset; } if ((error = fist_uiomove(current_base, bytes_read, UIO_READ, uiop))) /* * XXX: we have to see the exact semantics of returning with an * EFAULT from read */ break; current_loffset += bytes_read; }out_free: for (i = 0; i < num_pages; i++) { fist_dprint(6, "READ freeing %d address 0x%x\n", i, temp_iovec[i].iov_base); kmem_free(temp_iovec[i].iov_base); } kmem_free(temp_iovec);#ifdef FIST_DEBUG fist_print_uios("fist_wrapfs_read (END)", uiop);#endif /* FIST_DEBUG */ print_location(); return (error);}static intwrapfs_write(ap) struct vop_write_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ /* easy mappings */ vnode_t *vp = ap->a_vp; uio_t *uiop = ap->a_uio; int ioflag = ap->a_ioflag; cred_t *cr = ap->a_cred; struct proc *p = curproc; /* XXX */ int error = EPERM; vnode_t *hidden_vp; vattr_t va; uio_t temp_uio; iovec_t *temp_iovec; iovec_t *free_iovec; /* for freeing allocated memory */ int i; caddr_t current_base; int resid, bytes_read, num_pages, first_page_bytes, real_first_page; long long start_loffset, end_loffset, real_start_loffset; long long cleartext_start_loffset, cleartext_end_loffset, current_loffset; long long page_loffset; /* maintain offset to be passed to wrapfs_fill_page */ int hidden_ioflag = (ioflag & ~IO_APPEND); fist_dprint(4, "fist_wrapfs_write vp=0x%x ioflag=0x%x offset=0x%x resid=%d iovcnt=%x\n", (int) vp, ioflag, (int) uiop->uio_offset, uiop->uio_resid, uiop->uio_iovcnt);#ifdef FIST_DEBUG fist_print_uios("fist_wrapfs_write (START)", uiop);#endif /* FIST_DEBUG */ hidden_vp = WRAPFS_VP_TO_LOWERVP(vp); /* we don't want anybody to do updates while we write, so lock the vnode */#ifdef DO_WLOCK VREF(hidden_vp); /* XXX: is this needed? */ vn_lock(hidden_vp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE, p);#endif /* get the attributes, length is necessary for correct updates */ if ((error = VOP_GETATTR(hidden_vp, &va, cr, p))) { fist_dprint(4, "VOP_GETATTR returned error - not good\n"); /* XXX to be checked */ goto out; } /* just in case someone tries to pull a fast one */ if (uiop->uio_resid == 0) { error = 0; goto out; } cleartext_start_loffset = uiop->uio_offset; cleartext_end_loffset = uiop->uio_offset + uiop->uio_resid; if (ioflag & IO_APPEND) { fist_dprint(6, "WRITE: turning off append flag\n"); cleartext_start_loffset += va.va_size; cleartext_end_loffset += va.va_size; } start_loffset = MIN(cleartext_start_loffset, va.va_size) & ~(PAGE_SIZE - 1); real_start_loffset = cleartext_start_loffset & ~(PAGE_SIZE - 1); first_page_bytes = MIN(cleartext_start_loffset, va.va_size) - start_loffset; /* must use this to avoid shifting a quad w/ gcc */ real_first_page = (int)(real_start_loffset - start_loffset) >> PAGE_SHIFT; end_loffset = cleartext_end_loffset & ~(PAGE_SIZE - 1); ASSERT(first_page_bytes <= PAGE_SIZE); /* * if not multiple of PAGE_SIZE, then the above formula loses one page. * adjust for it */ if (cleartext_end_loffset > end_loffset) end_loffset += PAGE_SIZE; resid = end_loffset - start_loffset; num_pages = resid >> PAGE_SHIFT; if (num_pages == 1) first_page_bytes = PAGE_SIZE; temp_iovec = kmem_zalloc(num_pages * sizeof(iovec_t)); free_iovec = kmem_zalloc(num_pages * sizeof(iovec_t)); for (i = 0; i < num_pages; i++) { temp_iovec[i].iov_len = free_iovec[i].iov_len = PAGE_SIZE; /* we need the pages to be zeroed out */ temp_iovec[i].iov_base = free_iovec[i].iov_base = kmem_zalloc(PAGE_SIZE); } fist_dprint(6, "WRITE: so=%d eo=%d cso=%d ceo=%d rso=%d res=%d np=%d rfp=%d\n", (int) start_loffset, (int) end_loffset, (int) cleartext_start_loffset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -