当前位置: 首页 > 工具软件 > prov > 使用案例 >

prov_analyzer_pawrite函数分析

梁韬
2023-12-01
	proc_to_write.dtype = PROV_DIST_PROCESS;
	proc_to_write.pd_phook = p;
	err = prov_analyzer_pawrite(&proc_to_write, args, pos, &pa, 1);

如上,这是do_paread中的语句。当前进程封装为prov_dist_obj结构体。args是buf以及长度,pos是偏移,这两个感觉是用不到的。pa是prov_addition结构体。

开始分析:

int prov_analyzer_pawrite (struct prov_dist_obj * dobj,
			   struct prov_arguments * args,
			   loff_t *pos,
			   struct prov_addition ** in_additions,
			   const unsigned num_in_additions) {

    struct prov_addition ** out_additions = NULL;
    unsigned num_additions = 0;
    int ret = 0;

    ret = do_analysis(in_additions, num_in_additions,            /*分析层进行分析,去循环,去重复*/
		      &out_additions, &num_additions);
    if (ret < 0) {
	printk(KERN_ERR "PASS:(%s) do analysis failed %d\n",
	       __FUNCTION__, ret);
	goto out;
    }

    ret = prov_dist_pawrite(dobj, args, pos, out_additions, num_additions);    /*交给Distributor层*/
    if (num_additions) {
	free_prov_addition_array(out_additions, num_additions);
    }

 out:
    return ret;
}
Distributor层代码好多。。。。参数的意思基本不变。
int prov_dist_pawrite(struct prov_dist_obj * dobj,
		      struct prov_arguments * args,
		      loff_t * pos,
		      struct prov_addition ** additions,
		      const unsigned num_additions) {
    
    struct prov_obj_ref src_obj;
    struct prov_dist_info * dinfo;
    struct prov_array out_array;
    struct inode * inode = NULL;
    struct file * f = NULL;
    version_t version;
    int i = 0;
    int ret = 0;

    prov_array_init(&out_array);          /*初始化一个prov_array结构,里面是2个数和一个void类型的指针的指针*/
    /* set the inode and file */
    if (dobj->dtype == PROV_DIST_INODE) {
	inode = dobj->pd_inode;
    } else if (dobj->dtype == PROV_DIST_FILE) {
	f = dobj->pd_file;
	inode = f->f_path.dentry->d_inode;
    }

   
    if (!current->t_hook) {             /*当前进程无hook的话,只写数据*/
	/* current process doesn't have a hook, so go out. XXX this
	 * should have been filtered out at the observer, but I can't
	 * understand this */

	if (f) {
	    /* but we have a file to write data to, so do that before we go */
	    if (args->arg_type == NON_UIO_BASED) {
		if ((args->buf == NULL) && (args->buflen == 0) && (pos == NULL)) {
		    /* 
		     * This is us, during an mmap write.  For an mmap
		     * write, we need to add a record to the
		     * distributor/analyzer indicating that it wrote the
		     * file.  To get that effect, we make this dummy read
		     * call with everything set to NULL or 0 (depending on
		     * its type) from the obvserver.
		     */
		} else {
		    ret = vfs_write(f, args->buf, args->buflen, pos);
		}
	    } else {
		ret = vfs_writev(f, args->vec, args->vlen, pos);
	    }
	}

	goto out;
    }
    
    /* set up for converting */
    src_obj.rtype = PROV_PROCESS;
    src_obj.pr_phook = current->t_hook;

    /* then get the version out */
    dinfo = get_dist_info(&src_obj);
    if (IS_ERR(dinfo)) {
	ret = PTR_ERR(dinfo);
	printk (KERN_ERR "PASS:(%s) error dist info %d\n",
		__FUNCTION__, ret);
	goto out;
    }
    version = dinfo->version;
    put_dist_info(&src_obj);

    /* now process the additions.  The src_obj is used to convert any
       records that have CONVERT_REFER_SRC in them */
    ret = process_prov_additions(additions, num_additions, &src_obj,          /*见下文吧*/
				 version, &out_array);
    if (ret < 0) {
	printk (KERN_ERR "PASS:(%s) processing additions %d\n",
		    __FUNCTION__, ret);
	goto out_free;
    }

    if (out_array.num > 1024) {
	printk("number of elements %u\n", out_array.num);
    }

    switch(dobj->dtype) {

    case PROV_DIST_PROCESS:             /*如果是进程,就跳出,返回*/
	/* do nothing */
	break;

    case PROV_DIST_INODE:
    case PROV_DIST_FILE:

	if (!is_pass_file(inode)) {

	    if (args->arg_type == NON_UIO_BASED) {
		if ((args->buf == NULL) && (args->buflen == 0) && (pos == NULL)) {
		    /* 
		     * This is us, during an mmap write.  For an mmap
		     * write, we need to add a record to the
		     * distributor/analyzer indicating that it wrote the
		     * file.  To get that effect, we make this dummy read
		     * call with everything set to NULL or 0 (depending on
		     * its type) from the obvserver.
		     */
		} else {
		    ret = vfs_write(f, args->buf, args->buflen, pos);
		}
	    } else {
		ret = vfs_writev(f, args->vec, args->vlen, pos);
	    }

	    if (ret < 0) {
		printk (KERN_ERR "PASS:(%s) error vfs_writing %d\n",
			__FUNCTION__, ret);
	    }
	} else {
	    /*
	     * Write the provenance to the file system.  Note that we
	     * actually need to sort all the records by their volume
	     * and then write the provenance volume by volume.
	     */
	    
	    struct prov_addition ** additions = (struct prov_addition **) out_array.data;
	    if (args->arg_type == NON_UIO_BASED) {
		ret = inode->i_prov_hook->pi_ops->pi_pawrite(inode, f, args->buf, 
							     args->buflen, pos, 
							     additions,
							     out_array.num);
	    } else {
		ret = inode->i_prov_hook->pi_ops->pi_pawritev(inode, f, args->vec, 
							      args->vlen, pos,
							      additions,
							      out_array.num);
	    }

	    if (ret < 0) {
		printk (KERN_ERR "PASS:(%s) pawrite failed %d\n",
			__FUNCTION__, ret);
	    }
	}

	break; 
    }

 out_free:
    /* free the records, if any */
    for (i = 0; i < out_array.num; ++i) {
	free_prov_addition(out_array.data[i]); out_array.data[i] = NULL;
    }
    prov_array_cleanup(&out_array);

 out:
    return ret;
}
参数:&prov_addition       个数为1        进程的obj      进程dinfo中的版本      prov_array
static int 
process_prov_additions(struct prov_addition ** in_additions,
		       const unsigned num_additions,
		       struct prov_obj_ref * src_obj,
		       version_t version,
		       struct prov_array * out_array) {
    

    struct prov_addition * pa = NULL;
    int ret = 0;
    int i = 0;

    for (i = 0; i < num_additions; ++i) {

	if (!is_obj_pass_file(&in_additions[i]->pa_target)) {          /*在这里,target是上文中的进程,所以不是pass file*/

	    ret = convert_and_add_prov_addition_to_object(in_additions[i], /*注意prov_dist_info结构中的list*/
							  src_obj, 
							  version); 
	    if (ret < 0) { 
		printk(KERN_ERR "PASS:%s failed to convert_add_prov_addition"
		       "[%d]: %d\n", __FUNCTION__, i, ret);
	    }
	    /* we're done with this non-pass record and we can move on
	     * to the next element in the in_additions array */
	    continue;
	}

	/* record i is a pass volume provenance record */
	switch (in_additions[i]->pa_precord.pp_value.pv_type) {

	case PROV_TYPE_NIL:
	    switch (in_additions[i]->pa_conversion) {

	    case PROV_CONVERT_NONE:
		pa = copy_prov_addition(in_additions[i]);
		break;

	    case PROV_CONVERT_REFER_SRC:
		pa = convert_and_flush_phony_obj(&in_additions[i]->pa_target,
					  PROV_TYPE_OBJECTVERSION,
					  in_additions[i]->pa_precord.pp_attribute,
					  src_obj, version, out_array);
		break;

	    case PROV_CONVERT_REFER_DST:
		BUG(); /* xxx; we don't know how to handle this yet */
		break;
	    }
	    break;

	case PROV_TYPE_OBJECT:
	case PROV_TYPE_OBJECTVERSION:
	    if (is_obj_pass_file(&in_additions[i]->pa_precord.pp_value.pv_obj)){
		/* if the prov record points to a pass file, then we
		 * can just make a copy of the object */
		pa = copy_prov_addition(in_additions[i]); 
	    } else {
		/* else we convert the non-pass object to its phony */
		pa = convert_and_flush_phony_obj(&in_additions[i]->pa_target,
				 in_additions[i]->pa_precord.pp_value.pv_type,
				 in_additions[i]->pa_precord.pp_attribute,
				 &in_additions[i]->pa_precord.pp_value.pv_obj,
				 in_additions[i]->pa_precord.pp_value.pv_version,
			         out_array);
	    }
	    break;

	
	    
	default:
	    pa = copy_prov_addition(in_additions[i]);
	    break;
	}

	if (IS_ERR(pa)) {
	    /* print and error message and continue with the other guys */
	    ret = PTR_ERR(pa);
	    printk(KERN_ERR "PASS (%s): failed process addition %d:%d\n",
		   __FUNCTION__, i, ret);
	} else {
	    ret = prov_array_add(out_array, pa, NULL);                /*将pa放入array中*/
	    if (ret < 0) {
		//printk("freeing %s:%p\n", __FUNCTION__, pa);
		free_prov_addition(pa);
		printk(KERN_ERR "PASS (%s): failed to add addition %d:%d\n",
		       __FUNCTION__, i, ret);
		goto err;
	    }
	}
    }
    goto out;

 err:
    for (i = 0; i < out_array->num; ++i) {
	//printk("freeing %s:%p\n", __FUNCTION__, out_array->additions[i]);
	free_prov_addition(out_array->data[i]);
	out_array->data[i] = NULL;
    }
    prov_array_cleanup(out_array);

 out:
    return ret;
}


 类似资料: