📄 vnode.c
字号:
/* 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_loffset; cleartext_end_loffset = uiop->uio_loffset + uiop->uio_resid; if (ioflag & FAPPEND) { 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) & ~(PAGESIZE - 1); real_start_loffset = cleartext_start_loffset & ~(PAGESIZE - 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) >> PAGESHIFT; end_loffset = cleartext_end_loffset & ~(PAGESIZE - 1); ASSERT(first_page_bytes <= PAGESIZE); /* * if not multiple of PAGESIZE, then the above formula loses one page. * adjust for it */ if (cleartext_end_loffset > end_loffset) end_loffset += PAGESIZE; resid = end_loffset - start_loffset; num_pages = resid >> PAGESHIFT; if (num_pages == 1) first_page_bytes = PAGESIZE; temp_iovec = kmem_zalloc(num_pages * sizeof(iovec_t), KM_SLEEP); free_iovec = kmem_zalloc(num_pages * sizeof(iovec_t), KM_SLEEP); for (i = 0; i < num_pages; i++) { temp_iovec[i].iov_len = free_iovec[i].iov_len = PAGESIZE; /* we need the pages to be zeroed out */ temp_iovec[i].iov_base = free_iovec[i].iov_base = kmem_zalloc(PAGESIZE, KM_SLEEP); } 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, (int) cleartext_end_loffset, (int) real_start_loffset, resid, num_pages, real_first_page ); current_loffset = start_loffset; /* read first block XXX check length of file */ temp_uio.uio_iov = temp_iovec; temp_uio.uio_iovcnt = 1; temp_uio.uio_loffset = start_loffset; temp_uio.uio_segflg = UIO_SYSSPACE; temp_uio.uio_fmode = FREAD; temp_uio.uio_llimit = uiop->uio_llimit; temp_uio.uio_resid = first_page_bytes; fist_print_uios("WRITE (before VOP_READ 1)", &temp_uio); error = VOP_READ(hidden_vp, &temp_uio, hidden_ioflag, cr); if (error) { fist_dprint(5, "VOP_READ returned error - not good\n"); /* XXX to be checked */ goto out_free; } fist_print_uios("WRITE (after VOP_READ 1)", &temp_uio); bytes_read = PAGESIZE - temp_iovec[0].iov_len; temp_iovec[0].iov_base -= bytes_read; temp_iovec[0].iov_len = PAGESIZE; /* decode block read */ wrapfs_decode_block(temp_iovec[0].iov_base, temp_iovec[0].iov_base, bytes_read, vp, vp->v_vfsp); /* * if num_pages == 1, we already read the page... don't clobber it * if num_pages > 1, then we must read the last page, and decodes it * completely, before clobbering it. * XXX: if end offset is on page boundary, we don't have to do this. */ if (num_pages > 1) { /* read last block XXX check length of file */ temp_uio.uio_iov = temp_iovec + (num_pages - 1); temp_uio.uio_iovcnt = 1; temp_uio.uio_loffset = end_loffset - PAGESIZE; temp_uio.uio_segflg = UIO_SYSSPACE; temp_uio.uio_fmode = FREAD; temp_uio.uio_llimit = uiop->uio_llimit; temp_uio.uio_resid = PAGESIZE; fist_print_uios("WRITE (before VOP_READ 2)", &temp_uio); error = VOP_READ(hidden_vp, &temp_uio, hidden_ioflag, cr); fist_print_uios("WRITE (after VOP_READ 3)", &temp_uio); if (error) { fist_dprint(4, "VOP_READ returned error - not good\n"); /* XXX to be checked */ goto out_free; } bytes_read = PAGESIZE - temp_iovec[num_pages - 1].iov_len; temp_iovec[num_pages - 1].iov_base -= bytes_read; temp_iovec[num_pages - 1].iov_len = PAGESIZE; /* decodes block read */ wrapfs_decode_block(temp_iovec[num_pages-1].iov_base, temp_iovec[num_pages-1].iov_base, bytes_read, vp, vp->v_vfsp); } /* * Now we are ready to write the bytes within the start/end * cleartext offsets in the buffers we allocated. */ for (i = 0; i < num_pages; i++) { if (i >= real_first_page) { bytes_read = PAGESIZE; current_base = temp_iovec[i].iov_base; if (i == real_first_page) {#define real_first_page_offset (cleartext_start_loffset - real_start_loffset) bytes_read -= real_first_page_offset; current_loffset += real_first_page_offset; current_base += real_first_page_offset;#undef real_first_page_offset } if (current_loffset + bytes_read > cleartext_end_loffset) { bytes_read = cleartext_end_loffset - current_loffset; } if ((error = uiomove(current_base, bytes_read, UIO_WRITE, uiop))) break; } /* encode block before writing */ wrapfs_encode_block(temp_iovec[i].iov_base, temp_iovec[i].iov_base, PAGESIZE, vp, vp->v_vfsp); current_loffset += bytes_read; } fist_print_uios("WRITE (after for loop 4)", &temp_uio); if (va.va_size < end_loffset) { if (va.va_size < cleartext_end_loffset) resid -= end_loffset - cleartext_end_loffset; else resid -= end_loffset - va.va_size; } /* XXX: no need for full initialization here */ temp_uio.uio_iov = temp_iovec; temp_uio.uio_iovcnt = num_pages; temp_uio.uio_loffset = start_loffset; temp_uio.uio_segflg = UIO_SYSSPACE; temp_uio.uio_fmode = uiop->uio_fmode; temp_uio.uio_llimit = uiop->uio_llimit; temp_uio.uio_resid = resid; /* * pass operation to hidden filesystem, and return status */ fist_print_uios("WRITE (before write)", &temp_uio); error = VOP_WRITE(hidden_vp, &temp_uio, hidden_ioflag, cr); fist_print_uios("WRITE (after write)", &temp_uio); if (temp_uio.uio_loffset < cleartext_end_loffset) { /* incomplete write: this case is an error and should not happen */ uiop->uio_loffset = temp_uio.uio_loffset; uiop->uio_resid = cleartext_end_loffset - temp_uio.uio_loffset; } else { /* * we may have written more than what was asked of us to preserve the * encoding/decoding over a whole page */ uiop->uio_loffset = cleartext_end_loffset; uiop->uio_resid = 0; } /* if FAPPEND was used, return offset of 0 to upper level */ if (ioflag & FAPPEND) { uiop->uio_loffset = 0; }out_free: for (i = 0; i < num_pages; i++) { fist_dprint(6, "PRINT_BASE1 %d: 0x%x (len=%d)\n", i, temp_iovec[i].iov_base, temp_iovec[i].iov_len); fist_dprint(6, "PRINT_BASE2 %d: 0x%x (len=%d)\n", i, free_iovec[i].iov_base, free_iovec[i].iov_len); kmem_free(free_iovec[i].iov_base, PAGESIZE); } kmem_free(free_iovec, num_pages * sizeof(iovec_t)); kmem_free(temp_iovec, num_pages * sizeof(iovec_t));out: mutex_exit(&vp->v_lock);#ifdef FIST_DEBUG fist_print_uios("wrapfs_write (END)", uiop);#endif /* FIST_DEBUG */ print_location(); return (error);}static intwrapfs_ioctl( vnode_t * vp, int cmd, int arg, int flag, cred_t * cr, int *rvalp){ int error = 0; vnode_t *hidden_vp; vfs_t *this_vfs = vp->v_vfsp; vnode_t *this_vnode = vp;#ifdef FIST_DEBUG int val = 0;#endif /* FIST_DEBUG */ fist_dprint(4, "wrapfs_ioctl this_vfs %x vp %x cmd %d\n", this_vfs, vp, cmd); /* check if asked for local commands */ switch (cmd) {#ifdef FIST_DEBUG case FIST_IOCTL_GET_DEBUG_VALUE: if (copyin((caddr_t) arg, (caddr_t) & val, sizeof(int))) { error = EFAULT; goto out; } val = fist_get_debug_value(); if (copyout((caddr_t) & val, (caddr_t) arg, sizeof(int))) { error = EFAULT; goto out; } error = 0; goto out; break; case FIST_IOCTL_SET_DEBUG_VALUE: if (copyin((caddr_t) arg, (caddr_t) & val, sizeof(int))) { error = EFAULT; goto out; } if (val < 0 || val > 20) { error = EINVAL; goto out; } fist_dprint(6, "IOCTL: got arg %d\n", val); fist_set_debug_value(val); error = 0; goto out; break;#endif /* FIST_DEBUG */ /* add non-debugging fist ioctl's here */FIST_IOCTL_ECLS default: hidden_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to hidden filesystem, and return status */ error = VOP_IOCTL(hidden_vp, cmd, arg, flag, cr, rvalp); } /* end of switch statement */#ifdef FIST_DEBUGout:#endif /* FIST_DEBUG */ print_location(); return (error);}static intwrapfs_setfl( vnode_t * vp, int oflags, int nflags, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp; fist_dprint(4, "wrapfs_setfl vp %x\n", vp); hidden_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to hidden filesystem, and return status */ error = VOP_SETFL(hidden_vp, oflags, nflags, cr); print_location(); return (error);}static intwrapfs_getattr( vnode_t * vp, vattr_t * vap, int flags, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp; fist_dprint(4, "wrapfs_getattr vp %x\n", vp); hidden_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to hidden filesystem, and return status */ error = VOP_GETATTR(hidden_vp, vap, flags, cr); if (error) { fist_dprint(4, "ERROR: wrapfs_getattr %d\n", error); } print_location(); return (error);}static intwrapfs_setattr( vnode_t * vp, vattr_t * vap, int flags, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp; fist_dprint(4, "wrapfs_setattr vp %x\n", vp); hidden_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to hidden filesystem, and return status */ error = VOP_SETATTR(hidden_vp, vap, flags, cr); print_location(); return (error);}static intwrapfs_access( vnode_t * vp, int mode, int flags, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp; fist_dprint(4, "wrapfs_access vp %x\n", vp); hidden_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to hidden filesystem, and return status */ error = VOP_ACCESS(hidden_vp, mode, flags, cr); print_location(); return (error);}static intwrapfs_lookup( vnode_t * dvp, char *name, vnode_t ** vpp, pathname_t * pnp, int flags, vnode_t * rdir, cred_t * cr){ int err = EPERM; vnode_t *this_vnode = dvp; vnode_t *hidden_dvp; vnode_t *this_dir = dvp; char *encoded_name = name;#ifdef FIST_FILTER_NAME int encoded_length;#endif /* FIST_FILTER_NAME */ fist_dprint(4, "wrapfs_lookup dvp %x, rdir %x, name \"%s\"\n", dvp, rdir, (name ? name : "Null")); hidden_dvp = vntofwn(this_vnode)->fwn_vnodep; FIST_OP_LOOKUP_PRECALL;#ifdef FIST_FILTER_NAME encoded_length = wrapfs_encode_filename(name, strlen(name), &encoded_name, SKIP_DOTS, dvp, dvp->v_vfsp);#endif /* FIST_FILTER_NAME */ /* pass operation to hidden filesystem, and return status */ err = VOP_LOOKUP(hidden_dvp, encoded_name, vpp, pnp, flags, rdir, cr); FIST_OP_LOOKUP_POSTCALL; /* if no error, interpose vnode */ if (!err) { fist_dprint(6, "WRAPFS_LOOKUP1: hidden_vp->v_count=%d, vpp->v_type=%d\n", (*vpp)->v_count, (*vpp)->v_type); *vpp = wrapfs_interpose(*vpp, dvp->v_vfsp); fist_dprint(6, "WRAPFS_LOOKUP2: vpp->v_count=%d, hidden_vp->v_count=%d, vpp->v_type=%d\n", (*vpp)->v_count, vntofwn(*vpp)->fwn_vnodep->v_count, (*vpp)->v_type); }#ifdef FIST_FILTER_NAME kmem_free(encoded_name, encoded_length);#endif /* FIST_FILTER_NAME */ if (err) { fist_dprint(4, "ERROR: wrapfs_lookup %d\n", err); } FIST_OP_LOOKUP_POSTCALL; print_location(); return (err);}static intwrapfs_create( vnode_t * dvp, char *name, vattr_t * vap, vcexcl_t excl, int mode, vnode_t ** vpp, cred_t * cr, int flag /* XXX: EZK: new in 2.6, why? 64-bit support? */){ int error = EPERM; vnode_t *hidden_vp; char *encoded_name = name;#ifdef FIST_FILTER_NAME int encoded_length;#endif /* FIST_FILTER_NAME */ fist_dprint(4, "wrapfs_create vp=%x name=\"%s\" mode=%x\n", dvp, name, mode); hidden_vp = vntofwn(dvp)->fwn_vnodep;#ifdef FIST_FILTER_NAME encoded_length = wrapfs_encode_filename(name, strlen(name), &encoded_name, SKIP_DOTS, dvp, dvp->v_vfsp);#endif /* FIST_FILTER_NAME */ /* pass operation to hidden filesystem, and return status */ error = VOP_CREATE(hidden_vp, encoded_name, vap, excl, mode, vpp, cr, flag); /* if no error, interpose vnode */ if (!error) { fist_dprint(6, "WRAPFS_CREATE1: hidden_vp->v_count %d\n", (*vpp)->v_count); *vpp = wrapfs_interpose(*vpp, dvp->v_vfsp); fist_dprint(6, "WRAPFS_CREATE2: vpp->v_count %d, hidden_vp->v_count %d\n", (*vpp)->v_count, vntofwn(*vpp)->fwn_vnodep->v_count); }#ifdef FIST_FILTER_NAME kmem_free(encoded_name, encoded_length);#endif /* FIST_FILTER_NAME */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -