Esempio n. 1
0
static int
shadow_write(struct vn_softc * vn, struct buf * bp, char * base, 
	     vfs_context_t ctx)
{
	u_int32_t		blocksize = vn->sc_secsize;
	int 		error = 0;
	u_int32_t		offset;
	boolean_t	shadow_grew;
	u_int32_t		resid;
	u_int32_t		start = 0;

	offset = buf_blkno(bp);
	resid =  buf_resid(bp) / blocksize;
	while (resid > 0) {
		user_ssize_t	temp_resid;
		u_int32_t		this_offset;
		u_int32_t		this_resid;

		shadow_grew = shadow_map_write(vn->sc_shadow_map, 
					       offset, resid, 
					       &this_offset, &this_resid);
		if (shadow_grew) {
#if 0
			off_t	size;
			/* truncate the file to its new length before write */
			size = (off_t)shadow_map_shadow_size(vn->sc_shadow_map) 
				* blocksize;
			vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, ctx);
#endif
		}
		error = file_io(vn->sc_shadow_vp, ctx, UIO_WRITE, 
				base + start,
				(off_t)this_offset * blocksize,
				(user_ssize_t)this_resid * blocksize, 
				&temp_resid);
		if (error) {
			break;
		}
		this_resid -= (temp_resid / blocksize);
		if (this_resid == 0) {
			printf("vn device: shadow_write zero length write\n");
			break;
		}
		resid -= this_resid;
		offset += this_resid;
		start += this_resid * blocksize;
	}
	buf_setresid(bp, resid * blocksize);
	return (error);
}
Esempio n. 2
0
static int
vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, 
	       vfs_context_t ctx)
{
	u_int32_t		blocksize = vn->sc_secsize;
	int 		error = 0;
	user_ssize_t	resid;
	off_t		offset;

	resid = uio_resid(uio);
	offset = uio_offset(uio);

	while (resid > 0) {
		int		flags = 0;
		u_int32_t		offset_block_number;
		u_int32_t		remainder;
		u_int32_t		resid_block_count;
		u_int32_t		shadow_block_count;
		u_int32_t		shadow_block_number;
		user_ssize_t	this_resid;

		/* figure out which blocks to write */
		offset_block_number = block_truncate(offset, blocksize);
		remainder = block_remainder(offset, blocksize);
		resid_block_count = block_round(resid + remainder, blocksize);
		/* figure out if the first or last blocks are partial writes */
		if (remainder > 0
		    && !shadow_map_is_written(vn->sc_shadow_map,
					      offset_block_number)) {
			/* the first block is a partial write */
			flags |= FLAGS_FIRST_BLOCK_PARTIAL;
		}
		if (resid_block_count > 1
		    && !shadow_map_is_written(vn->sc_shadow_map,
					      offset_block_number
					      + resid_block_count - 1)
		    && block_remainder(offset + resid, blocksize) > 0) {
			/* the last block is a partial write */
			flags |= FLAGS_LAST_BLOCK_PARTIAL;
		}
		if (shadow_map_write(vn->sc_shadow_map,
				     offset_block_number, resid_block_count,
				     &shadow_block_number, 
				     &shadow_block_count)) {
			/* shadow file is growing */
#if 0
			/* truncate the file to its new length before write */
			off_t	size;
			size = (off_t)shadow_map_shadow_size(vn->sc_shadow_map) 
				* vn->sc_secsize;
			vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, ctx);
#endif
		}
		/* write the blocks (or parts thereof) */
		uio_setoffset(uio, (off_t)
			      shadow_block_number * blocksize + remainder);
		this_resid = (off_t)shadow_block_count * blocksize - remainder;
		if (this_resid >= resid) {
			this_resid = resid;
			if ((flags & FLAGS_LAST_BLOCK_PARTIAL) != 0) {
				/* copy the last block to the shadow */
				u_int32_t 	d;
				u_int32_t	s;

				s = offset_block_number 
					+ resid_block_count - 1;
				d = shadow_block_number 
					+ shadow_block_count - 1;
				error = vncopy_block_to_shadow(vn, ctx, s, d);
				if (error) {
					printf("vnwrite_shadow: failed to copy"
					       " block %u to shadow block %u\n",
					       s, d);
					break;
				}
			}
		}
		uio_setresid(uio, this_resid);
		if ((flags & FLAGS_FIRST_BLOCK_PARTIAL) != 0) {
			/* copy the first block to the shadow */
			error = vncopy_block_to_shadow(vn, ctx,
						       offset_block_number,
						       shadow_block_number);
			if (error) {
				printf("vnwrite_shadow: failed to"
				       " copy block %u to shadow block %u\n", 
				       offset_block_number, 
				       shadow_block_number);
				break;
			}
		}
		error = VNOP_WRITE(vn->sc_shadow_vp, uio, ioflag, ctx);
		if (error) {
			break;
		}
		/* figure out how much we actually wrote */
		this_resid -= uio_resid(uio);
		if (this_resid == 0) {
			printf("vn device: vnwrite_shadow zero length write\n");
			break;
		}
		resid -= this_resid;
		offset += this_resid;
	}
	uio_setresid(uio, resid);
	uio_setoffset(uio, offset);
	return (error);
}
Esempio n. 3
0
int
main()
{
    shadow_map_t *	map;
    int 		i;
    block_request_t 	requests[] = {
	{ WriteRequest, BAND_SIZE_BLOCKS * 2, 1 },
	{ ReadRequest, BAND_SIZE_BLOCKS / 2, BAND_SIZE_BLOCKS * 2 - 2 },
	{ WriteRequest, BAND_SIZE_BLOCKS * 1, 5 * BAND_SIZE_BLOCKS + 3},
	{ ReadRequest, 0, BAND_SIZE_BLOCKS * 10 },
	{ WriteRequest, BAND_SIZE_BLOCKS * (BAND_MAX - 1),
	  BAND_SIZE_BLOCKS * 2},
	{ 0, 0 },
    };
    
    map = shadow_map_create(1024 * 1024 * 1024 * 8ULL, 0, 0, 512);
    if (map == NULL) {
	printf("shadow_map_create failed\n");
	exit(1);
    }
    for (i = 0; TRUE; i++) {
	u_long		offset;
	u_long		resid;
	boolean_t	shadow_grew;
	boolean_t	read_shadow;

    	if (requests[i].count == 0) {
	    break;
	}
	offset = requests[i].offset;
	resid = requests[i].count;
	printf("\n%s REQUEST (%ld, %ld)\n", 
	       requests[i].type == WriteRequest ? "WRITE" : "READ",
	       offset, resid);
	switch (requests[i].type) {
	case WriteRequest:
	    while (resid > 0) {
		u_long this_offset;
		u_long this_count;
		
		shadow_grew = shadow_map_write(map, offset,
					       resid,
					       &this_offset,
					       &this_count);
		printf("\t(%ld, %ld) => (%ld, %ld)",
		       offset, resid, this_offset, this_count);
		resid -= this_count;
		offset += this_count;
		if (shadow_grew) {
		    printf(" shadow grew to %ld", shadow_map_shadow_size(map));
		}
		printf("\n");
	    }
	    break;
	case ReadRequest:
	    while (resid > 0) {
		u_long this_offset;
		u_long this_count;
		
		read_shadow = shadow_map_read(map, offset,
					      resid,
					      &this_offset,
					      &this_count);
		printf("\t(%ld, %ld) => (%ld, %ld)%s\n",
		       offset, resid, this_offset, this_count,
		       read_shadow ? " from shadow" : "");
		if (this_count == 0) {
		    printf("this_count is 0, aborting\n");
		    break;
		}
		resid -= this_count;
		offset += this_count;
	    }
	    break;
	default:
	    break;
	}
    }
    if (map) {
	shadow_map_free(map);
    }
    exit(0);
    return (0);
}