3.3in
%{ #ifdef HAVE_AC_CONFIG_H /* include Autoconf-generated header */ # include "config.h" #endif %} %fstype incore %filter gzip $$ %vn_write {%name =~ "\.txt$"} %filter gunzip $$ %vn_read {%name =~ "\.txt$"} %% /* Empty FiST rules section */ %% /* No additional code needed */ |
Gzipfs is a compression file system based on my wrapper file system (Appendix sec-appendix-typical-in-core-wrapfs). Data gets compressed before written to stable media, and decompressed after having been read from such. For this example, I only wish to compress regular files that have a file extension .txt', since ASCII files yield better compression ratios. The example of Figure fig-fist-definition-gzipfs shows the FiST input for this file system.
The code automatically generated for Gzipfs will be similar to Wrapfs, with the two exceptions of the read and write functions. One possible code for these, for example the read() function, is shown in Figure fig-fist-definition-gzipfs-code.
5in
static int fist_gzipfs_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr) { int error; vnode_t *interposed_vp; uio_t *new_uiop; /* for the decompressed bytes */ /* find interposed vnode that is "hidden" inside this vnode */ interposed_vp = vntofwn(vp)->fwn_vnodep; /* pass operation to interposed file system, and return status */ if ((error = VOP_READ(interposed_vp, uiop, ioflag, cr)) != 0) return (error); /* Check for triggered events after reading */ if (regexp_match(fist_get_file_name(vp), "\.txt$")) if (fist_filter_gunzip_data(&uiop, sizeof(uio_t), &new_uiop) < 0) return EIO; /* I/O error occurred */ uiop = new_uiop; /* pass up decompressed data */ return (error); } |
In this example, the routine decodes the ``hidden'' vnode pointer, and then passes the read operation to it. After the read had succeeded, we call the FiST filter function fist_filter_gzip_data(). This filter is used to decompress data in the uio. The filter function would make use of kernel functions that manipulate uio structures such as uiomove() to move blocks of bytes between one uio and another. Bytes will be read off of one uio structure, passed through a generic stream decompression function I pulled out of the GNU Zip package, and written to a new uio structure. Then the old uio structure is deallocated and replaced with the new one.
Figure fig-fist-definition-gzipfs-code-4nfs shows the code that would be generated for the NFS version of the same read operation.
5.5in
int nfsproc2_gzipfs_read(struct nfsreadargs *in, struct nfsrdresult *out, struct exportinfo *ex, struct svc_req *sr, cred_t *cr) { int error NFS_OK; /* perform simple read */ error = fist_gzipfs_read(in, out); if (error) return (error); /* check for triggered events after reading */ if (regexp_match(fist_get_nfs_file_name(in->ra_fhandle), "\.txt$")) if (fist_filter_gunzip_nfs_data(in, out) < 0) return NFS_ERR; /* I/O error occurred */ return (error); } |