struct zcomp *zcomp_create(constchar *compress, int max_strm) { structzcomp *comp; structzcomp_backend *backend; int error;
backend = find_backend(compress); if (!backend) return ERR_PTR(-EINVAL);
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL); if (!comp) return ERR_PTR(-ENOMEM);
comp->backend = backend; if (max_strm > 1) error = zcomp_strm_multi_create(comp, max_strm); else error = zcomp_strm_single_create(comp); if (error) {
找到backend(lzo/lz4)后用zcomp_strm_multi_create创建多个 or 用zcomp_strm_single_create创建单个压缩流。
先来看简单的单压缩流数据。
单数据流操作
structzcomp_strm { /* compression/decompression buffer */ void *buffer; /* * The private data of the compression stream, only compression * stream backend can touch this (e.g. compression algorithm * working memory) */ void *private; /* used in multi stream backend, protected by backend strm_lock */ structlist_headlist; }; /* * single zcomp_strm backend */ structzcomp_strm_single { structmutexstrm_lock; structzcomp_strm *zstrm; };
Compression backend may use up to max_comp_streams compression streams, thus allowing up to max_comp_streams concurrent compression operations. By default, compression backend uses single compression stream.
Note: In order to enable compression backend’s multi stream support max_comp_streams must be initially set to desired concurrency level before ZRAM device initialisation. Once the device initialised as a single stream compression backend (max_comp_streams equals to 1), you will see error if you try to change the value of max_comp_streams because single stream compression backend implemented as a special case by lock overhead issue and does not support dynamic max_comp_streams. Only multi stream backend supports dynamic max_comp_streams adjustment.
spin_lock(&zs->strm_lock); zs->max_strm = num_strm; /* * if user has lowered the limit and there are idle streams, * immediately free as much streams (and memory) as we can. */ while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) { zstrm = list_entry(zs->idle_strm.next, struct zcomp_strm, list); list_del(&zstrm->list); zcomp_strm_free(comp, zstrm); zs->avail_strm--; } spin_unlock(&zs->strm_lock); returntrue; }
/* * multi zcomp_strm backend */ structzcomp_strm_multi { /* protect strm list */ spinlock_t strm_lock; /* max possible number of zstrm streams */ int max_strm; /* number of available zstrm streams */ int avail_strm; /* list of available strms */ structlist_headidle_strm; wait_queue_head_t strm_wait; };
staticintzcomp_strm_multi_create(struct zcomp *comp, int max_strm) { structzcomp_strm *zstrm; structzcomp_strm_multi *zs;
/* add stream back to idle list and wake up waiter or free the stream */ staticvoidzcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm) { structzcomp_strm_multi *zs = comp->stream;