⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmap.c

📁 Solaris操作系统下的过滤驱动程序, C源码程序.
💻 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/* are these two #defines (copied from 2.5.1) correct in 2.6/2.7? */#ifndef se_assert# define se_assert(x)            (*(x) > 0 || *(x) == -1)#endif /* not se_assert */#ifndef se_shared_assert# define se_shared_assert(x)     (*(x) > 0)#endif /* not se_shared_assert */#define PAGE_UNLOCK(p) { \/*	ASSERT(se_assert(&((p)->p_selock))); \ */ \	page_unlock(p); \}#define PAGE_IO_UNLOCK(p) { \	ASSERT(page_iolock_assert(p)); \	page_io_unlock(p); \}/* *  Vnode mmap ops for fist_wrapfs */extern int wrapfs_getpage(vnode_t *, u_offset_t, u_int, u_int *, page_t **,		       u_int, struct seg *, caddr_t, enum seg_rw, cred_t *);extern int wrapfs_getapage(vnode_t *, u_offset_t, 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, u_int, int, cred_t *);extern int wrapfs_putapage(struct vnode *vp, page_t * pp, u_offset_t * offp, u_int * lenp, int flags, struct cred *cr);extern int wrapfs_map(vnode_t *, offset_t, struct as *, caddr_t *, u_int,			  u_char, u_char, u_int, cred_t *);extern int wrapfs_addmap(vnode_t *, offset_t, struct as *, caddr_t, u_int,			     u_char, u_char, u_int, cred_t *);extern int wrapfs_delmap(vnode_t *, offset_t, struct as *, caddr_t, u_int,			     u_int, u_int, u_int, cred_t *);/* * Called from pvn_getpages or wrapfs_getpage to get a particular page. * Return one pages from [off..off+len] in given file. * rw is S_{READ,WRITE,EXEC,CREAT} flags from <vm/seg_enum.h>. */intwrapfs_getapage(		     vnode_t * vp,	/* vnode */		     u_offset_t offset,	/* offset */		     u_int len,		/* length (can be 0) */		     u_int * protp,	/* out arg: modified protection? */		     page_t * plarr[],	/* out arg: pages array to fill in? */		     u_int plsz,	/* length of pl[] array */		     struct seg *seg,	/* segment in question? */		     caddr_t addr,	/* address? */		     enum seg_rw rw,	/* read/write flag (of WHAT?) */		     cred_t * cr	/* user credentials */){  int error = EPERM;  vnode_t *hidden_vp = NULL;  caddr_t va;  page_t *this_pp, *hidden_pp = NULL;  int ret;  fist_dprint(4,	      "wrapfs_getapage vp %x, v_pages 0x%x, offset=%d, len=%d, rw=0x%x, protp=0x%x, addr=0x%x, plsz=%d\n",	      vp,	      vp->v_pages,	      offset,	      len,	      rw,	      (protp ? *protp : -1),	      addr,	      plsz);  if (len > PAGESIZE) {    fist_dprint(6, "GETAPAGE: len %d is greater than PAGESIZE, truncating.\n",		len, PAGESIZE);    len = PAGESIZE;  }  /* try to find this page in memory, and return it if found */  this_pp = page_lookup(vp, offset, SE_EXCL);  if (this_pp) {    fist_dprint(6, "WRAPFS_GETAPAGE: found page lookup\n");    plarr[0] = this_pp;    plarr[1] = NULL;    error = 0;    goto out;  }  /* if this page was not found, create it because we would need it later */  this_pp = page_create(vp, offset, PAGESIZE, PG_WAIT|PG_EXCL);  /*   * if returns NULL, page may exist in hidden_vp by a thread which ran in   * between our page_lookup and page_create!  or memory exhaused.   * either way, it is a bad thing   */  if (!this_pp) {    printk("%s:%d: no more memory\n", __FUNCTION__, __LINE__);    error = ENOMEM;    goto out;  }  /* remove unnecessary lock only if needed */  if (page_iolock_assert(this_pp))    PAGE_IO_UNLOCK(this_pp);  /* find underlying vnode */  hidden_vp = vntofwn(vp)->fwn_vnodep;  /*   * if hidden page not found, call VOP_GETPAGE (which will zfod it if it   * does not exist!   */  /* XXX: take out this next "if" */  if (!hidden_pp) {    error = VOP_GETPAGE(hidden_vp,			(offset_t) offset,			len,			protp,			plarr,			PAGESIZE, /* pass PAGESIZE b/c we want only 1 page */			seg,			addr,			rw,	/* XXX: should this be S_READ always? */			cr);    if (error) {      /* if gets here, something really bad happend! */      printk("VOP_GETPAGE failed with error=%d\n", error);      PAGE_UNLOCK(this_pp);      hat_pagesync(this_pp, HAT_SYNC_ZERORM); /* must be done before PP_CLRREFMOD */      page_clr_all_props(this_pp); /* XXX: EZK: new in 2.6 */      //      PP_CLRREFMOD(this_pp);      goto out;    }    hidden_pp = plarr[0];    if (page_iolock_assert(hidden_pp))      PAGE_IO_UNLOCK(hidden_pp);  }  /* got hidden page from hidden vnode: copy and decode it */  ppcopy(hidden_pp, this_pp);  va = ppmapin(this_pp, PROT_READ | PROT_WRITE, (caddr_t) -1);  ret = wrapfs_decode_block(va, va, len, vp, vp->v_vfsp);  ppmapout(va);  /* cleanup locks on hidden_pp as needed! */  ASSERT(!page_iolock_assert(hidden_pp));  PAGE_UNLOCK(hidden_pp);  ASSERT(!page_iolock_assert(this_pp));  /* do not page_unlock(this_pp), b/c upper layer would */  /* final stage: set outgoing arguments */  plarr[0] = this_pp;  plarr[1] = NULL;  error = 0;out:  print_location();  return (error);}/* Return all the pages from [off..off+len] in given file */intwrapfs_getpage(		    vnode_t * vp,	/* vnode */		    u_offset_t offset,	/* offset */		    u_int len,		/* length */		    u_int * protp,	/* out arg: modified protection? */		    page_t * plarr[],	/* out arg: pages array to fill in? */		    u_int plsz,		/* actual size to return? */		    struct seg *seg,	/* segment in question? */		    caddr_t addr,	/* address? */		    enum seg_rw rw,	/* read/write flag (of WHAT?) */		    cred_t * cr		/* user credentials */){  int error = EPERM;  fist_dprint(4, "wrapfs_getpage vp %x, offset=%d, len=%d, rw=0x%x, plsz=%d\n",	      vp, (u_int) offset, len, rw, plsz);  if (plarr == NULL) {    error = 0;    goto out;  }  if (vp->v_flag & VNOMAP) {    error = ENOSYS;    goto out;  }  if (protp != NULL)    *protp = PROT_ALL;again:  if (len <= PAGESIZE) {    fist_dprint(6, "GETPAGE is calling getapage with len=%d, pagesize=%d\n",		len, PAGESIZE);    error = wrapfs_getapage(vp, offset, len, protp, plarr, plsz,				seg, addr, rw, cr);    fist_dprint(6, "GETPAGE is back from calling getapage\n");  } else {    fist_dprint(6,		"GETPAGE is calling pvn_getpages with len=%d, pagesize=%d\n",		len, PAGESIZE);    error = pvn_getpages(wrapfs_getapage, vp, offset, len,			 protp, plarr, plsz, seg, addr, rw, cr);    fist_dprint(6, "GETPAGE is back from calling pvn_getpages\n");  }  if (error == ENOSPC || error == EAGAIN) {    fist_dprint(6, "WRAPFS: getpage is trying again...\n");    goto again;  }out:  print_location();  return (error);}intwrapfs_putapage(		     struct vnode *vp,		     page_t * pp,		     u_offset_t * offp,		     u_int * lenp,	/* return values */		     int flags,		     struct cred *cr){  int error = EPERM;  vnode_t *hidden_vp = NULL;  caddr_t va;  u_int offset = pp->p_offset;  page_t *this_pp = pp;  page_t *hidden_pp = NULL;  int ret;  fist_dprint(4,	      "wrapfs_putapage vp %x, offp 0x%x, lenp 0x%x, flags 0x%x, pp->p_state=0x%x\n",	      vp, offp, lenp, flags, (int) pp->p_state);  /* verify that this page has at least a shared lock */  ASSERT(!se_shared_assert(&(this_pp->p_selock)));  /* find interposed vnode */  hidden_vp = vntofwn(vp)->fwn_vnodep;  /* lookup for hidden page with same offset and lock if exclusively */  hidden_pp = page_lookup(hidden_vp, offset, SE_EXCL);  /* if not found, create new page and lock it exclusively */  if (!hidden_pp) {    hidden_pp = page_create(hidden_vp, offset, PAGESIZE, PG_WAIT|PG_EXCL);    /*     * if returns NULL, page may exist in hidden_vp by a thread which ran in     * between our page_lookup and page_create! or memory exhaused.     * either way, it is a bad thing     */    if (!hidden_pp) {      printk("%s:%d: no more memory\n", __FUNCTION__, __LINE__);      error = ENOMEM;      goto out;    }    /* remove this unnecessary lock, leaving only the regular lock */    if (page_iolock_assert(hidden_pp))      PAGE_IO_UNLOCK(hidden_pp);  }  /* copy data from this page to the hidden page */  ppcopy(this_pp, hidden_pp);  /* map page into kernel virtual memory */  va = ppmapin(hidden_pp, PROT_READ | PROT_WRITE, (caddr_t) -1);  /* encode hidden page using key in vp */  wrapfs_encode_block(va, va, PAGESIZE, vp, vp->v_vfsp);  /* unmap page */  ppmapout(va);  /* mark hidden page as dirty and unlock it */  /* the next 3 lines are crucial, else we deadlock */  ASSERT(!page_iolock_assert(hidden_pp));  PAGE_UNLOCK(hidden_pp);  page_set_props(hidden_pp, P_MOD);  //  PP_SETMOD(hidden_pp);		/* set dirty bit */  /* pass operation to hidden filesystem, and return status */  error = VOP_PUTPAGE(hidden_vp,		      (offset_t) offset,		      PAGESIZE,	/* was 0 or PAGESIZE */		      flags,	/* was | B_DONTNEED | B_FREE */		      cr);	/* was cr */  if (error) {    printk("VOP_PUTPAGE failed with error %d.\n", error);    goto out;  }  hat_pagesync(this_pp, HAT_SYNC_ZERORM); /* must do before PP_CLRREFMOD */  page_clr_all_props(this_pp); /* XXX: EZK: new in 2.6 */  //  PP_CLRREFMOD(this_pp);  ret = pvn_getdirty(this_pp, flags);out:  print_location();  return (error);}/* * Flags are composed of {B_INVAL, B_FREE, B_DONTNEED, B_FORCE} * If len == 0, do from off to EOF. * * B_* are from <sys/buf.h> * * The normal cases should be len == 0 & off == 0 (entire vp list), * len == MAXBSIZE (from segmap_release actions), and len == PAGESIZE * (from pageout). * Note len can be greater than one page! */intwrapfs_putpage(		    vnode_t * vp,		    offset_t offset,		    u_int len,		    int flags,		    cred_t * cr){  int error = 0;  page_t *this_pp;  offset_t cur_offset = offset;  /* OK */  fist_dprint(4,	      "PUTPAGE vp 0x%x, v_pages=0x%x, fstype %d, offset=0x%x, len=%d, flags=0x%x\n",	      vp, vp->v_pages, vp->v_vfsp->vfs_fstype,	      (u_int) offset, len, flags);  if(cr==kcred){    printk("putpage called with kcred, ignoring\n");    error=0;    goto out;  }  /* if no pages are left in this vnode, then all is OK */  if (vp->v_pages == NULL) {    error = 0;    goto out;  }  /* deal with len==0 case by flushing all pages w/ offset>=offset */  if (len == 0) {    error = pvn_vplist_dirty(vp, (u_int) offset, wrapfs_putapage, flags, cr);    goto out;  }  /* now handle one or more pages */  for (cur_offset = offset; cur_offset < offset+len; cur_offset += PAGESIZE) {    /* get an exclusive lock on the page b/c we are going to modify it */    this_pp = page_lookup(vp, (u_int) cur_offset, SE_EXCL);    if (!this_pp) {      fist_dprint(6,		  "WRAPFS: putpage failed to find page at cur_offset 0x%x\n",		  (u_int) cur_offset);      continue;			/* NOT AN ERROR: go on looking for next page */    }    fist_dprint(6, "PUTPAGE page_lookup ok cur_offset 0x%x!\n",		(u_int) cur_offset);    error = wrapfs_putapage(vp, this_pp, NULL, NULL, flags, cr);    if (error) {      printk("PUTPAGE: putapage failed with error %d\n", error);      goto out;			/* XXX: continue loop or abort? */    }  } /* end of "for (cur_offset..." loop */out:  print_location();  return (error);}intwrapfs_map(		vnode_t * vp,		offset_t offset,		struct as *as,		caddr_t * addrp,		u_int len,		u_char prot,		u_char maxprot,		u_int flags,		cred_t * cr){  struct segvn_crargs vn_a;  int error;  fist_dprint(4, "wrapfs_map vp %x\n", vp);  fist_dprint(4,	      "wrapfs_map offset=%d, len=%d, prot=0x%x, maxprot=0x%x, flags=0x%x\n",	      (int) offset,	/* from mmap() */	      (int) len,	/* from mmap() */	      (int) prot,	/* from mmap() | PROT_USER */	      (int) maxprot,	/* PROT_ALL */	      (int) flags);	/* from mmap() */  /* addrp is returned to user from mmap(2) */  if (vp->v_flag & VNOMAP)    return (ENOSYS);  if ((int) offset < 0 || (int) (offset + len) < 0)    return (EINVAL);  as_rangelock(as);  if ((flags & MAP_FIXED) == 0) {    map_addr(addrp, len, (off_t) offset, 1);    if (*addrp == NULL) {      as_rangeunlock(as);      return (ENOMEM);    }  } else {    /*     * User specified address - blow away any previous mappings     */    (void) as_unmap(as, *addrp, len);  }  vn_a.vp = vp;  vn_a.offset = (u_int) offset;  vn_a.type = flags & MAP_TYPE;  vn_a.prot = prot;  vn_a.maxprot = maxprot;  vn_a.flags = flags & ~MAP_TYPE;  vn_a.cred = cr;  vn_a.amp = NULL;  error = as_map(as, *addrp, len, segvn_create, (caddr_t) & vn_a);  as_rangeunlock(as);  return (error);}intwrapfs_addmap(		   vnode_t * vp,		   offset_t offset,		   struct as *as,		   caddr_t addr,		   u_int len,		   u_char prot,		   u_char maxprot,		   u_int flags,		   cred_t * cr){  fist_wrapfs_node_t *fwnp = vntofwn(vp);  fist_dprint(4, "wrapfs_addmap vp 0x%x, v_pages 0x%x\n", vp, vp->v_pages);  if (vp->v_flag & VNOMAP)    return (ENOSYS);  /* increment mapped pages counter */  /*   * This whole thing is for a program which does open(), then mmap(),   * then close(), and THEN access the bytes of the page!   */  mutex_enter(&fwnp->fwn_lock);  if (fwnp->fwn_mapcnt == 0)    VN_HOLD(vp);  fwnp->fwn_mapcnt += btopr(len);  fist_dprint(6, "WRAPFS_ADDMAP: fwnp->fwn_mapcnt %d.\n", fwnp->fwn_mapcnt);  mutex_exit(&fwnp->fwn_lock);  return 0;}intwrapfs_delmap(		   vnode_t * vp,		   offset_t offset,		   struct as *as,		   caddr_t addr,		   u_int len,		   u_int prot,		   u_int maxprot,		   u_int flags,		   cred_t * cr){  vnode_t *hidden_vp;  fist_wrapfs_node_t *fwnp = vntofwn(vp);  hidden_vp = vntofwn(vp)->fwn_vnodep;  fist_dprint(4, "wrapfs_delmap vp 0x%x, v_pages=0x%x, hidden_pages=0x%x\n", vp, (int) vp->v_pages, (int) hidden_vp->v_pages);  if (vp->v_flag & VNOMAP)    return (ENOSYS);  /* decrement mapped pages counter */  mutex_enter(&fwnp->fwn_lock);  fwnp->fwn_mapcnt -= btopr(len);  if (fwnp->fwn_mapcnt == 0)    VN_RELE(vp);  fist_dprint(6, "WRAPFS_DELMAP: fwnp->fwn_mapcnt %d.\n", fwnp->fwn_mapcnt);  mutex_exit(&fwnp->fwn_lock);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -