--- /usr/src/sys/conf/files.orig 2004-08-30 11:24:33.000000000 +0200 +++ /usr/src/sys/conf/files 2005-05-25 01:06:24.000000000 +0200 @@ -1269,7 +1269,7 @@ file net/route.c file net/rtsock.c file net/slcompress.c sl | ppp | strip | (irip & irip_vj) -file net/zlib.c (ppp & ppp_deflate) | ipsec | opencrypto +file net/zlib.c (ppp & ppp_deflate) | ipsec | opencrypto | vnd file net80211/ieee80211.c wlan file net80211/ieee80211_compat.c wlan file net80211/ieee80211_crypto.c wlan --- /usr/src/sys/dev/vndvar.h.orig 2003-08-07 18:30:52.000000000 +0200 +++ /usr/src/sys/dev/vndvar.h 2005-05-25 00:00:34.000000000 +0200 @@ -162,6 +162,13 @@ struct vndgeom sc_geom; /* virtual geometry */ struct pool sc_vxpool; /* vndxfer pool */ struct pool sc_vbpool; /* vndbuf pool */ + u_int32_t sc_comp_blksz; /* precompressed block size */ + u_int32_t sc_comp_numoffs;/* count of compressed block offsets */ + u_int64_t *sc_comp_offsets;/* file idx's to compressed blocks */ + unsigned char *sc_comp_buff; /* compressed data buffer */ + unsigned char *sc_comp_decombuf;/* decompressed data buffer */ + int32_t sc_comp_buffblk;/* current decompressed block */ + z_stream sc_comp_stream;/* decompress descriptor */ }; #endif @@ -175,6 +182,15 @@ #define VNF_READONLY 0x040 /* unit is read-only */ #define VNF_KLABEL 0x080 /* keep label on close */ #define VNF_VLABEL 0x100 /* label is valid */ +#define VNF_COMP 0x200 /* file is compressed */ + +/* structure of header in a compressed file */ +struct comp_header +{ + char preamble[128]; + u_int32_t block_size; + u_int32_t num_blocks; +}; /* * A simple structure for describing which vnd units are in use. --- /usr/src/sys/dev/vnd.c.orig 2004-01-25 19:06:48.000000000 +0100 +++ /usr/src/sys/dev/vnd.c 2005-05-25 00:00:34.000000000 +0200 @@ -156,6 +156,7 @@ #include #include #include +#include #include @@ -207,6 +208,7 @@ void vndclear __P((struct vnd_softc *, int)); void vndstart __P((struct vnd_softc *)); +void compstrategy __P((struct buf *, off_t)); int vndsetcred __P((struct vnd_softc *, struct ucred *)); void vndthrottle __P((struct vnd_softc *, struct vnode *)); void vndiodone __P((struct buf *)); @@ -219,6 +221,8 @@ static int vndlock __P((struct vnd_softc *)); static void vndunlock __P((struct vnd_softc *)); +static void *vnd_alloc __P((void *, u_int, u_int)); +static void vnd_free __P((void *, void *)); dev_type_open(vndopen); dev_type_close(vndclose); @@ -263,6 +267,9 @@ for (i = 0; i < numvnd; i++) { vnd_softc[i].sc_unit = i; + vnd_softc[i].sc_comp_offsets = NULL; + vnd_softc[i].sc_comp_buff = NULL; + vnd_softc[i].sc_comp_decombuf = NULL; bufq_alloc(&vnd_softc[i].sc_tab, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK); } @@ -483,6 +490,12 @@ bp->b_flags |= B_ERROR; goto done; } + /* handle a compressed read */ + if((bp->b_flags & B_READ) && (vnd->sc_flags & VNF_COMP)) { + compstrategy(bp, bn); + goto done; + } + bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize; addr = bp->b_data; flags = (bp->b_flags & (B_READ|B_ASYNC)) | B_CALL; @@ -726,6 +739,98 @@ splx(s); } +/* compressed file read */ +void +compstrategy(bp, bn) + struct buf *bp; + off_t bn; +{ + int error; + int unit = vndunit(bp->b_dev); + struct vnd_softc *vnd = &vnd_softc[unit]; + u_int32_t comp_block; + struct uio auio; + caddr_t addr; + + /* set up constants for data move */ + auio.uio_rw = UIO_READ; + auio.uio_segflg = bp->b_flags & B_PHYS ? UIO_USERSPACE : UIO_SYSSPACE; + auio.uio_procp = bp->b_proc; + + /* read, and transfer the data */ + addr = bp->b_data; + while(bp->b_resid > 0) { + unsigned length; + size_t length_in_buffer; + u_int32_t offset_in_buffer; + struct iovec aiov; + + /* calculate the compressed block number */ + comp_block = bn / (off_t)vnd->sc_comp_blksz; + + /* check for good block number */ + if(comp_block >= vnd->sc_comp_numoffs) { + bp->b_error = EINVAL; + bp->b_flags |= B_ERROR; + return; + } + + /* read in the compressed block, if not in buffer */ + if (comp_block != vnd->sc_comp_buffblk) { + length = vnd->sc_comp_offsets[comp_block + 1] - + vnd->sc_comp_offsets[comp_block]; + error = vn_rdwr(UIO_READ, vnd->sc_vp, vnd->sc_comp_buff, + length, vnd->sc_comp_offsets[comp_block], + UIO_SYSSPACE, IO_UNIT, vnd->sc_cred, NULL, NULL); + if(error) { + bp->b_error = error; + bp->b_flags |= B_ERROR; + return; + } + /* uncompress the buffer */ + vnd->sc_comp_stream.next_in = vnd->sc_comp_buff; + vnd->sc_comp_stream.avail_in = length; + vnd->sc_comp_stream.next_out = vnd->sc_comp_decombuf; + vnd->sc_comp_stream.avail_out = vnd->sc_comp_blksz; + inflateReset(&vnd->sc_comp_stream); + error = inflate(&vnd->sc_comp_stream, Z_FINISH); + if(error != Z_STREAM_END) { + if(vnd->sc_comp_stream.msg) + printf("%s: compressed file, %s\n", + vnd->sc_xname, + vnd->sc_comp_stream.msg); + bp->b_error = EBADMSG; + bp->b_flags |= B_ERROR; + return; + } + vnd->sc_comp_buffblk = comp_block; + } + + /* transfer the usable uncompressed data */ + offset_in_buffer = bn % (off_t)vnd->sc_comp_blksz; + length_in_buffer = vnd->sc_comp_blksz - offset_in_buffer; + if(length_in_buffer > bp->b_resid) + length_in_buffer = bp->b_resid; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = addr; + aiov.iov_len = length_in_buffer; + auio.uio_resid = aiov.iov_len; + auio.uio_offset = 0; + error = uiomove(vnd->sc_comp_decombuf + offset_in_buffer, + length_in_buffer, &auio); + if(error) { + bp->b_error = error; + bp->b_flags |= B_ERROR; + return; + } + + bn += length_in_buffer; + addr += length_in_buffer; + bp->b_resid -= length_in_buffer; + } +} + /* ARGSUSED */ int vndread(dev, uio, flags) @@ -859,11 +964,115 @@ if ((error = vn_open(&nd, fflags, 0)) != 0) goto unlock_and_exit; error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); - VOP_UNLOCK(nd.ni_vp, 0); if (!error && nd.ni_vp->v_type != VREG) error = EOPNOTSUPP; - if (error) + if (error) { + VOP_UNLOCK(nd.ni_vp, 0); goto close_and_exit; + } + + /* If using a compressed file, initialize its info */ + if (vio->vnd_flags & VNF_COMP) { + struct comp_header *ch; + int error; + int i; + u_int32_t comp_size; + u_int32_t comp_maxsize; + + /* allocate space for compresed file header */ + ch = malloc(sizeof(struct comp_header), + M_TEMP, M_WAITOK); + + /* read compressed file header */ + error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)ch, + sizeof(struct comp_header), 0, UIO_SYSSPACE, + IO_UNIT|IO_NODELOCKED, p->p_ucred, NULL, NULL); + if(error) { + free(ch, M_TEMP); + VOP_UNLOCK(nd.ni_vp, 0); + goto close_and_exit; + } + + /* save some header info */ + vnd->sc_comp_blksz = ntohl(ch->block_size); + /* note last offset is the file byte size */ + vnd->sc_comp_numoffs = ntohl(ch->num_blocks)+1; + free(ch, M_TEMP); + if(vnd->sc_comp_blksz % DEV_BSIZE !=0) { + VOP_UNLOCK(nd.ni_vp, 0); + error = EINVAL; + goto close_and_exit; + } + if(sizeof(struct comp_header) + + sizeof(u_int64_t) * vnd->sc_comp_numoffs > + vattr.va_size) { + VOP_UNLOCK(nd.ni_vp, 0); + error = EINVAL; + goto close_and_exit; + } + + /* set decompressed file size */ + vattr.va_size = + (vnd->sc_comp_numoffs - 1) * vnd->sc_comp_blksz; + + /* allocate space for all the compressed offsets */ + vnd->sc_comp_offsets = + malloc(sizeof(u_int64_t) * vnd->sc_comp_numoffs, + M_DEVBUF, M_WAITOK); + + /* read in the offsets */ + error = vn_rdwr(UIO_READ, nd.ni_vp, + (caddr_t)vnd->sc_comp_offsets, + sizeof(u_int64_t) * vnd->sc_comp_numoffs, + sizeof(struct comp_header), UIO_SYSSPACE, + IO_UNIT|IO_NODELOCKED, p->p_ucred, NULL, NULL); + if(error) { + VOP_UNLOCK(nd.ni_vp, 0); + goto close_and_exit; + } + /* + * find largest block size (used for allocation limit). + * Also convert offset to native byte order. + */ + comp_maxsize = 0; + for (i = 0; i < vnd->sc_comp_numoffs - 1; i++) { + vnd->sc_comp_offsets[i] = + be64toh(vnd->sc_comp_offsets[i]); + comp_size = be64toh(vnd->sc_comp_offsets[i + 1]) + - vnd->sc_comp_offsets[i]; + if (comp_size > comp_maxsize) + comp_maxsize = comp_size; + } + vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1] = + be64toh(vnd->sc_comp_offsets[vnd->sc_comp_numoffs - 1]); + + /* create compressed data buffer */ + vnd->sc_comp_buff = malloc(comp_maxsize, + M_DEVBUF, M_WAITOK); + + /* create decompressed buffer */ + vnd->sc_comp_decombuf = malloc(vnd->sc_comp_blksz, + M_DEVBUF, M_WAITOK); + vnd->sc_comp_buffblk = -1; + + /* Initialize decompress stream */ + bzero(&vnd->sc_comp_stream, sizeof(z_stream)); + vnd->sc_comp_stream.zalloc = vnd_alloc; + vnd->sc_comp_stream.zfree = vnd_free; + error = inflateInit2(&vnd->sc_comp_stream, MAX_WBITS); + if(error) { + if(vnd->sc_comp_stream.msg) + printf("vnd%d: compressed file, %s\n", + unit, vnd->sc_comp_stream.msg); + VOP_UNLOCK(nd.ni_vp, 0); + error = EINVAL; + goto close_and_exit; + } + + vnd->sc_flags |= VNF_COMP | VNF_READONLY; + } + + VOP_UNLOCK(nd.ni_vp, 0); vnd->sc_vp = nd.ni_vp; vnd->sc_size = btodb(vattr.va_size); /* note truncation */ @@ -964,6 +1173,19 @@ close_and_exit: (void) vn_close(nd.ni_vp, fflags, p->p_ucred, p); unlock_and_exit: + /* free any allocated memory (for compressed file) */ + if(vnd->sc_comp_offsets) { + free(vnd->sc_comp_offsets, M_DEVBUF); + vnd->sc_comp_offsets = NULL; + } + if(vnd->sc_comp_buff) { + free(vnd->sc_comp_buff, M_DEVBUF); + vnd->sc_comp_buff = NULL; + } + if(vnd->sc_comp_decombuf) { + free(vnd->sc_comp_decombuf, M_DEVBUF); + vnd->sc_comp_decombuf = NULL; + } vndunlock(vnd); return (error); @@ -1243,7 +1465,22 @@ if ((vnd->sc_flags & VNF_READONLY) == 0) fflags |= FWRITE; - vnd->sc_flags &= ~(VNF_INITED | VNF_READONLY | VNF_VLABEL); + /* free the compressed file buffers */ + if(vnd->sc_flags & VNF_COMP) { + if(vnd->sc_comp_offsets) { + free(vnd->sc_comp_offsets, M_DEVBUF); + vnd->sc_comp_offsets = NULL; + } + if(vnd->sc_comp_buff) { + free(vnd->sc_comp_buff, M_DEVBUF); + vnd->sc_comp_buff = NULL; + } + if(vnd->sc_comp_decombuf) { + free(vnd->sc_comp_decombuf, M_DEVBUF); + vnd->sc_comp_decombuf = NULL; + } + } + vnd->sc_flags &= ~(VNF_INITED | VNF_READONLY | VNF_VLABEL | VNF_COMP); if (vp == (struct vnode *)0) panic("vndioctl: null vp"); (void) vn_close(vp, fflags, vnd->sc_cred, p); @@ -1428,3 +1665,23 @@ wakeup(sc); } } + +/* compression memory allocation routines */ +static void * +vnd_alloc(aux, items, siz) + void *aux; + u_int items; + u_int siz; +{ + void *ptr; + ptr = malloc(items * siz, M_TEMP, M_NOWAIT); + return ptr; +} + +static void +vnd_free(aux, ptr) + void *aux; + void *ptr; +{ + free(ptr, M_TEMP); +} --- /usr/src/usr.sbin/vnconfig/vnconfig.c.orig 2004-01-25 22:49:04.000000000 +0100 +++ /usr/src/usr.sbin/vnconfig/vnconfig.c 2005-05-25 00:00:34.000000000 +0200 @@ -139,6 +139,7 @@ int verbose = 0; int readonly = 0; int force = 0; +int compressed = 0; char *tabname; int config __P((char *, char *, char *, int)); @@ -154,7 +155,7 @@ { int ch, rv, action = VND_CONFIG; - while ((ch = getopt(argc, argv, "Fcf:lrt:uv")) != -1) { + while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) { switch (ch) { case 'F': force = 1; @@ -181,6 +182,10 @@ case 'v': verbose = 1; break; + case 'z': + compressed = 1; + readonly = 1; + break; default: case '?': usage(); @@ -314,6 +319,9 @@ if (readonly) vndio.vnd_flags |= VNDIOF_READONLY; + if (compressed) + vndio.vnd_flags |= 0x200; /* VNF_COMP, cliff */ + /* * Clear (un-configure) the device */