📄 vnode.c
字号:
/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * Copyright (c) 1997-2000 Columbia University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. *//* * Copyright (c) 1992 by Sun Microsystems, Inc. */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* HAVE_CONFIG_H */#ifdef FISTGEN# include "fist_wrapfs.h"#endif /* FISTGEN */#include <fist.h>#include <wrapfs.h>#if 0#include <sys/param.h>#include <sys/systm.h>#include <sys/errno.h>#include <sys/vnode.h>#include <sys/vfs.h>#include <sys/uio.h>#include <sys/cred.h>#include <sys/pathname.h>#include <sys/dirent.h>#include <sys/debug.h>#include <sys/sysmacros.h>#include <sys/tiuser.h>#include <sys/cmn_err.h>#include <sys/stat.h>#include <sys/mode.h>#include <rpc/types.h>#include <rpc/auth.h>#include <rpc/clnt.h>#include <sys/fs_subr.h>#include <sys/mman.h>#include <sys/vm.h>#include <vm/as.h>#include <vm/pvn.h>#include <vm/seg_vn.h>#include <vm/seg_kp.h>#include <vm/seg_map.h>#include <vm/page.h>#include <fist.h>#include <wrapfs.h>#endif/* * Vnode ops for fist_wrapfs */static int wrapfs_open(vnode_t **, int, cred_t *);static int wrapfs_close(vnode_t *, int, int, offset_t, cred_t *);static int wrapfs_getattr(vnode_t *, vattr_t *, int, cred_t *);static int wrapfs_access(vnode_t *, int, int, cred_t *);static int wrapfs_lookup(vnode_t *, char *, vnode_t **, pathname_t *, int, vnode_t *, cred_t *);static int wrapfs_remove(vnode_t *, char *, cred_t *);static int wrapfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *);static int wrapfs_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *);static int wrapfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *);static int wrapfs_readdir(vnode_t *, uio_t *, cred_t *, int *);static int wrapfs_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *);static int wrapfs_fsync(vnode_t *, int, cred_t *);static void wrapfs_inactive(vnode_t *, cred_t *);static void wrapfs_rwlock(vnode_t *, int);static void wrapfs_rwunlock(vnode_t * vp, int);static int wrapfs_seek(vnode_t * vp, offset_t, offset_t *);static int wrapfs_cmp(vnode_t *, vnode_t *);static int wrapfs_read(vnode_t *, uio_t *, int, cred_t *);static int wrapfs_write(vnode_t *, uio_t *, int, cred_t *);static int wrapfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *);static int wrapfs_setfl(vnode_t *, int, int, cred_t *);static int wrapfs_setattr(vnode_t *, vattr_t *, int, cred_t *);static int wrapfs_create(vnode_t *, char *, vattr_t *, vcexcl_t, int, vnode_t **, cred_t *, int);static int wrapfs_link(vnode_t *, vnode_t *, char *, cred_t *);static int wrapfs_readlink(vnode_t *, uio_t *, cred_t *);static int wrapfs_fid(vnode_t *, fid_t *);static int wrapfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t, cred_t *);static int wrapfs_space(vnode_t *, int, struct flock64 *, int, offset_t, cred_t *);static int wrapfs_realvp(vnode_t *, vnode_t **);extern int wrapfs_getpage(vnode_t *, offset_t, size_t, uint_t *, page_t **, size_t, struct seg *, caddr_t, enum seg_rw, cred_t *);extern int wrapfs_getapage(vnode_t *, u_int, u_int, u_int *, page_t **, u_int, struct seg *, caddr_t, enum seg_rw, cred_t *);extern int wrapfs_putpage(vnode_t *, offset_t, size_t, int, cred_t *);extern int wrapfs_putapage(struct vnode *vp, page_t * pp, u_offset_t * offp, size_t * lenp, int flags, struct cred *cr);extern int wrapfs_map(vnode_t *, offset_t, struct as *, caddr_t *, size_t, uchar_t, uchar_t, uint_t, cred_t *);extern int wrapfs_addmap(vnode_t *, offset_t, struct as *, caddr_t, size_t, uchar_t, uchar_t, uint_t, cred_t *);extern int wrapfs_delmap(vnode_t *, offset_t, struct as *, caddr_t, size_t, uint_t, uint_t, uint_t, cred_t *);static int wrapfs_poll(vnode_t *, short, int, short *, pollhead_t **);static int wrapfs_dump(vnode_t *, caddr_t, int, int);static int wrapfs_pathconf(vnode_t *, int, u_long *, cred_t *);static int wrapfs_pageio(vnode_t *, page_t *, u_offset_t, size_t, int, cred_t *);static int wrapfs_dumpctl(vnode_t *, int);static void wrapfs_dispose(vnode_t *, page_t *, int, int, cred_t *);static int wrapfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *);static int wrapfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *);vnodeops_t wrapfs_vnodeops ={ wrapfs_open, /* open */ wrapfs_close, /* close */ wrapfs_read, /* read */ wrapfs_write, /* write */ wrapfs_ioctl, /* ioctl */ wrapfs_setfl, /* setfl */ wrapfs_getattr, /* getattr */ wrapfs_setattr, /* setattr */ wrapfs_access, /* access */ wrapfs_lookup, /* lookup */ wrapfs_create, /* create */ wrapfs_remove, /* remove */ wrapfs_link, /* link */ wrapfs_rename, /* rename */ wrapfs_mkdir, /* mkdir */ wrapfs_rmdir, /* rmdir */ wrapfs_readdir, /* readdir */ wrapfs_symlink, /* symlink */ wrapfs_readlink, /* readlink */ wrapfs_fsync, /* fsync */ wrapfs_inactive, /* inactive */ wrapfs_fid, /* fid */ wrapfs_rwlock, /* rwlock */ wrapfs_rwunlock, /* rwunlock */ wrapfs_seek, /* seek */ wrapfs_cmp, /* cmp */ wrapfs_frlock, /* frlock */ wrapfs_space, /* space */ wrapfs_realvp, /* realvp */ wrapfs_getpage, /* getpage */ wrapfs_putpage, /* putpage */ wrapfs_map, /* map */ wrapfs_addmap, /* addmap */ wrapfs_delmap, /* delmap */ wrapfs_poll, /* poll */ wrapfs_dump, /* dump */ wrapfs_pathconf, /* pathconf */ wrapfs_pageio, /* pageio */ wrapfs_dumpctl, /* dumpctl */ wrapfs_dispose, /* dispose */ wrapfs_setsecattr, /* setsecattr */ wrapfs_getsecattr /* getsecattr */};/* interpose on an old vnode and return new one */vnode_t *wrapfs_interpose(vnode_t * hidden_vp, vfs_t * this_vfsp){ vnode_t *fw_vp; fist_wrapfs_node_t *fwnp; struct fist_wrapfs_info *fwip = NULL; mutex_enter(&vfstofwi(this_vfsp)->fwi_ht_lock); /* look if entry exists in HT */ fw_vp = fist_ht_find_vp(hidden_vp, this_vfsp); if (fw_vp) { fist_dprint(6, "WRAPFS_INTERPOSE found vp in HT!\n"); VN_HOLD(fw_vp); /* maybe VN_RELE(hidden_vp) */ VN_RELE(hidden_vp); goto out; } /* allocate new vnode */ fw_vp = kmem_zalloc(sizeof(vnode_t), KM_SLEEP); /* XXX: need VN_INIT2 that will reuse lock var of interposed vnode */ VN_INIT(fw_vp, this_vfsp, hidden_vp->v_type, (dev_t) NULL); /* allocate and fill in fist_wrapfs_node_t */ fwnp = (fist_wrapfs_node_t *) kmem_zalloc(sizeof(fist_wrapfs_node_t), KM_SLEEP); if (!fwnp) { kmem_free(fw_vp, sizeof(vnode_t)); fw_vp = NULL; goto out; } /* init fwnp */ fwnp->fwn_mapcnt = 0; /* no mapped pages */ mutex_init(&fwnp->fwn_lock, "fist_wrapfs private data lock", MUTEX_DEFAULT, NULL); /* store new vnode */ fwnp->fwn_vnodep = hidden_vp; fw_vp->v_data = (caddr_t) fwnp; /* operations are fist_wrapfs vnode ops */ fw_vp->v_op = &wrapfs_vnodeops; /* set rest of fields to NULL */ fw_vp->v_vfsmountedhere = NULL; fw_vp->v_filocks = NULL; /* don't do this one for now */ /* fw_vp->v_cv = NULL; */ /* increment interposed vnodes counter */ fwip = vfstofwi(this_vfsp); fwip->fwi_num_vnodes++; /* insert into HT */ fist_ht_insert_vp(hidden_vp, fw_vp); /* VN_RELE(hidden_vp); */#if 0 /* hold our vnode */ VN_HOLD(fw_vp);#endifout: mutex_exit(&vfstofwi(this_vfsp)->fwi_ht_lock); print_location(); /* finally return vnode to this newly created one */ return (fw_vp);}static intwrapfs_open( vnode_t ** vpp, int flag, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp, *new_vp; fist_dprint(4, "wrapfs_open vpp %x, flag 0x%x\n", vpp, flag); if (flag & FAPPEND) { fist_dprint(6, "***WARNING*** file is opened in append-only mode!!!\n"); flag &= ~FAPPEND; /* turn off FAPPEND flag */ } new_vp = hidden_vp = vntofwn(*vpp)->fwn_vnodep; /* we NEED read access */ flag |= FREAD; /* pass operation to hidden filesystem, and return status */ error = VOP_OPEN(&hidden_vp, flag, cr); /* check if a new vnode was returned (cloned) */ if (!error && new_vp != hidden_vp) { fist_dprint(6, "WRAPFS_OPEN1: hidden_vp->v_count %d\n", hidden_vp->v_count); /* * yes: need to allocate a new fist_wrapfs vnode, * initialize it, store interposed vnode in it, and * finally return the fist_wrapfs vnode back. */ *vpp = wrapfs_interpose(hidden_vp, (*vpp)->v_vfsp); fist_dprint(6, "WRAPFS_OPEN2: vpp->v_count %d, hidden_vp->v_count %d\n", (*vpp)->v_count, hidden_vp->v_count); } print_location(); return (error);}static intwrapfs_close( vnode_t * vp, int flag, int count, offset_t offset, cred_t * cr){ int error = EPERM; vnode_t *hidden_vp; fist_dprint(4, "wrapfs_close vp %x\n", vp); hidden_vp = vntofwn(vp)->fwn_vnodep; fist_dprint(6, "WRAPFS_CLOSE1: vp->v_count %d, hidden_vp->v_count %d\n", vp->v_count, hidden_vp->v_count); /* pass operation to hidden filesystem, and return status */ error = VOP_CLOSE(hidden_vp, flag, count, offset, cr); fist_dprint(6, "WRAPFS_CLOSE2: vp->v_count %d, hidden_vp->v_count %d\n", vp->v_count, hidden_vp->v_count); print_location(); return (error);}static intwrapfs_read( vnode_t * vp, uio_t * uiop, int ioflag, cred_t * cr){ 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, "wrapfs_read vp %x\n", vp);#ifdef FIST_DEBUG fist_print_uios("wrapfs_read", uiop);#endif /* FIST_DEBUG */ cleartext_start_loffset = uiop->uio_loffset; cleartext_end_loffset = uiop->uio_loffset + uiop->uio_resid; start_loffset = cleartext_start_loffset & ~(PAGESIZE - 1); end_loffset = cleartext_end_loffset & ~(PAGESIZE - 1); /* * 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; 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, PAGESIZE); temp_iovec = kmem_zalloc(num_pages * sizeof(iovec_t), KM_SLEEP); for (i = 0; i < num_pages; i++) { temp_iovec[i].iov_len = PAGESIZE; temp_iovec[i].iov_base = kmem_zalloc(PAGESIZE, KM_SLEEP); 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_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; hidden_vp = vntofwn(vp)->fwn_vnodep; /* * 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 = PAGESIZE - temp_iovec[i].iov_len; if (bytes_read == 0) break; temp_iovec[i].iov_base -= bytes_read; current_base = temp_iovec[i].iov_base; /* decodes the page/block */ wrapfs_decode_block(current_base, current_base, bytes_read, vp, vp->v_vfsp); /* * save the original size, for kmem_free. * no need for it w/ wrapfs; size is always PAGESIZE, 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 = 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, PAGESIZE); } kmem_free(temp_iovec, num_pages * sizeof(iovec_t));#ifdef FIST_DEBUG fist_print_uios("wrapfs_read (END)", uiop);#endif /* FIST_DEBUG */ print_location(); return (error);}static intwrapfs_write( vnode_t * vp, uio_t * uiop, int ioflag, cred_t * cr){ 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; int hidden_ioflag = (ioflag & ~FAPPEND); fist_dprint(4, "wrapfs_write vp %x, ioflag 0x5x\n", vp, ioflag);#ifdef FIST_DEBUG fist_print_uios("wrapfs_write (START)", uiop);#endif /* FIST_DEBUG */ hidden_vp = vntofwn(vp)->fwn_vnodep; /* we don't want anybody to do updates while we write, so lock the vnode */ mutex_enter(&vp->v_lock); /* get the attributes, length is necessary for correct updates */ va.va_mask = AT_SIZE; if ((error = VOP_GETATTR(hidden_vp, &va, 0, cr))) { fist_dprint(4, "VOP_GETATTR returned error - not good\n"); /* XXX to be checked */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -