The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/os/linux/zfs/qat_compress.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 #if defined(_KERNEL) && defined(HAVE_QAT)
   23 #include <linux/slab.h>
   24 #include <linux/vmalloc.h>
   25 #include <linux/pagemap.h>
   26 #include <linux/completion.h>
   27 #include <sys/zfs_context.h>
   28 #include <sys/byteorder.h>
   29 #include <sys/zio.h>
   30 #include <sys/qat.h>
   31 
   32 /*
   33  * Max instances in a QAT device, each instance is a channel to submit
   34  * jobs to QAT hardware, this is only for pre-allocating instance and
   35  * session arrays; the actual number of instances are defined in the
   36  * QAT driver's configuration file.
   37  */
   38 #define QAT_DC_MAX_INSTANCES    48
   39 
   40 /*
   41  * ZLIB head and foot size
   42  */
   43 #define ZLIB_HEAD_SZ            2
   44 #define ZLIB_FOOT_SZ            4
   45 
   46 static CpaInstanceHandle dc_inst_handles[QAT_DC_MAX_INSTANCES];
   47 static CpaDcSessionHandle session_handles[QAT_DC_MAX_INSTANCES];
   48 static CpaBufferList **buffer_array[QAT_DC_MAX_INSTANCES];
   49 static Cpa16U num_inst = 0;
   50 static Cpa32U inst_num = 0;
   51 static boolean_t qat_dc_init_done = B_FALSE;
   52 int zfs_qat_compress_disable = 0;
   53 
   54 boolean_t
   55 qat_dc_use_accel(size_t s_len)
   56 {
   57         return (!zfs_qat_compress_disable &&
   58             qat_dc_init_done &&
   59             s_len >= QAT_MIN_BUF_SIZE &&
   60             s_len <= QAT_MAX_BUF_SIZE);
   61 }
   62 
   63 static void
   64 qat_dc_callback(void *p_callback, CpaStatus status)
   65 {
   66         if (p_callback != NULL)
   67                 complete((struct completion *)p_callback);
   68 }
   69 
   70 static void
   71 qat_dc_clean(void)
   72 {
   73         Cpa16U buff_num = 0;
   74         Cpa16U num_inter_buff_lists = 0;
   75 
   76         for (Cpa16U i = 0; i < num_inst; i++) {
   77                 cpaDcStopInstance(dc_inst_handles[i]);
   78                 QAT_PHYS_CONTIG_FREE(session_handles[i]);
   79                 /* free intermediate buffers  */
   80                 if (buffer_array[i] != NULL) {
   81                         cpaDcGetNumIntermediateBuffers(
   82                             dc_inst_handles[i], &num_inter_buff_lists);
   83                         for (buff_num = 0; buff_num < num_inter_buff_lists;
   84                             buff_num++) {
   85                                 CpaBufferList *buffer_inter =
   86                                     buffer_array[i][buff_num];
   87                                 if (buffer_inter->pBuffers) {
   88                                         QAT_PHYS_CONTIG_FREE(
   89                                             buffer_inter->pBuffers->pData);
   90                                         QAT_PHYS_CONTIG_FREE(
   91                                             buffer_inter->pBuffers);
   92                                 }
   93                                 QAT_PHYS_CONTIG_FREE(
   94                                     buffer_inter->pPrivateMetaData);
   95                                 QAT_PHYS_CONTIG_FREE(buffer_inter);
   96                         }
   97                 }
   98         }
   99 
  100         num_inst = 0;
  101         qat_dc_init_done = B_FALSE;
  102 }
  103 
  104 int
  105 qat_dc_init(void)
  106 {
  107         CpaStatus status = CPA_STATUS_SUCCESS;
  108         Cpa32U sess_size = 0;
  109         Cpa32U ctx_size = 0;
  110         Cpa16U num_inter_buff_lists = 0;
  111         Cpa16U buff_num = 0;
  112         Cpa32U buff_meta_size = 0;
  113         CpaDcSessionSetupData sd = {0};
  114 
  115         if (qat_dc_init_done)
  116                 return (0);
  117 
  118         status = cpaDcGetNumInstances(&num_inst);
  119         if (status != CPA_STATUS_SUCCESS)
  120                 return (-1);
  121 
  122         /* if the user has configured no QAT compression units just return */
  123         if (num_inst == 0)
  124                 return (0);
  125 
  126         if (num_inst > QAT_DC_MAX_INSTANCES)
  127                 num_inst = QAT_DC_MAX_INSTANCES;
  128 
  129         status = cpaDcGetInstances(num_inst, &dc_inst_handles[0]);
  130         if (status != CPA_STATUS_SUCCESS)
  131                 return (-1);
  132 
  133         for (Cpa16U i = 0; i < num_inst; i++) {
  134                 cpaDcSetAddressTranslation(dc_inst_handles[i],
  135                     (void*)virt_to_phys);
  136 
  137                 status = cpaDcBufferListGetMetaSize(dc_inst_handles[i],
  138                     1, &buff_meta_size);
  139 
  140                 if (status == CPA_STATUS_SUCCESS)
  141                         status = cpaDcGetNumIntermediateBuffers(
  142                             dc_inst_handles[i], &num_inter_buff_lists);
  143 
  144                 if (status == CPA_STATUS_SUCCESS && num_inter_buff_lists != 0)
  145                         status = QAT_PHYS_CONTIG_ALLOC(&buffer_array[i],
  146                             num_inter_buff_lists *
  147                             sizeof (CpaBufferList *));
  148 
  149                 for (buff_num = 0; buff_num < num_inter_buff_lists;
  150                     buff_num++) {
  151                         if (status == CPA_STATUS_SUCCESS)
  152                                 status = QAT_PHYS_CONTIG_ALLOC(
  153                                     &buffer_array[i][buff_num],
  154                                     sizeof (CpaBufferList));
  155 
  156                         if (status == CPA_STATUS_SUCCESS)
  157                                 status = QAT_PHYS_CONTIG_ALLOC(
  158                                     &buffer_array[i][buff_num]->
  159                                     pPrivateMetaData,
  160                                     buff_meta_size);
  161 
  162                         if (status == CPA_STATUS_SUCCESS)
  163                                 status = QAT_PHYS_CONTIG_ALLOC(
  164                                     &buffer_array[i][buff_num]->pBuffers,
  165                                     sizeof (CpaFlatBuffer));
  166 
  167                         if (status == CPA_STATUS_SUCCESS) {
  168                                 /*
  169                                  *  implementation requires an intermediate
  170                                  *  buffer approximately twice the size of
  171                                  *  output buffer, which is 2x max buffer
  172                                  *  size here.
  173                                  */
  174                                 status = QAT_PHYS_CONTIG_ALLOC(
  175                                     &buffer_array[i][buff_num]->pBuffers->
  176                                     pData, 2 * QAT_MAX_BUF_SIZE);
  177                                 if (status != CPA_STATUS_SUCCESS)
  178                                         goto fail;
  179 
  180                                 buffer_array[i][buff_num]->numBuffers = 1;
  181                                 buffer_array[i][buff_num]->pBuffers->
  182                                     dataLenInBytes = 2 * QAT_MAX_BUF_SIZE;
  183                         }
  184                 }
  185 
  186                 status = cpaDcStartInstance(dc_inst_handles[i],
  187                     num_inter_buff_lists, buffer_array[i]);
  188                 if (status != CPA_STATUS_SUCCESS)
  189                         goto fail;
  190 
  191                 sd.compLevel = CPA_DC_L1;
  192                 sd.compType = CPA_DC_DEFLATE;
  193                 sd.huffType = CPA_DC_HT_FULL_DYNAMIC;
  194                 sd.sessDirection = CPA_DC_DIR_COMBINED;
  195                 sd.sessState = CPA_DC_STATELESS;
  196                 sd.deflateWindowSize = 7;
  197                 sd.checksum = CPA_DC_ADLER32;
  198                 status = cpaDcGetSessionSize(dc_inst_handles[i],
  199                     &sd, &sess_size, &ctx_size);
  200                 if (status != CPA_STATUS_SUCCESS)
  201                         goto fail;
  202 
  203                 QAT_PHYS_CONTIG_ALLOC(&session_handles[i], sess_size);
  204                 if (session_handles[i] == NULL)
  205                         goto fail;
  206 
  207                 status = cpaDcInitSession(dc_inst_handles[i],
  208                     session_handles[i],
  209                     &sd, NULL, qat_dc_callback);
  210                 if (status != CPA_STATUS_SUCCESS)
  211                         goto fail;
  212         }
  213 
  214         qat_dc_init_done = B_TRUE;
  215         return (0);
  216 fail:
  217         qat_dc_clean();
  218         return (-1);
  219 }
  220 
  221 void
  222 qat_dc_fini(void)
  223 {
  224         if (!qat_dc_init_done)
  225                 return;
  226 
  227         qat_dc_clean();
  228 }
  229 
  230 /*
  231  * The "add" parameter is an additional buffer which is passed
  232  * to QAT as a scratch buffer alongside the destination buffer
  233  * in case the "compressed" data ends up being larger than the
  234  * original source data. This is necessary to prevent QAT from
  235  * generating buffer overflow warnings for incompressible data.
  236  */
  237 static int
  238 qat_compress_impl(qat_compress_dir_t dir, char *src, int src_len,
  239     char *dst, int dst_len, char *add, int add_len, size_t *c_len)
  240 {
  241         CpaInstanceHandle dc_inst_handle;
  242         CpaDcSessionHandle session_handle;
  243         CpaBufferList *buf_list_src = NULL;
  244         CpaBufferList *buf_list_dst = NULL;
  245         CpaFlatBuffer *flat_buf_src = NULL;
  246         CpaFlatBuffer *flat_buf_dst = NULL;
  247         Cpa8U *buffer_meta_src = NULL;
  248         Cpa8U *buffer_meta_dst = NULL;
  249         Cpa32U buffer_meta_size = 0;
  250         CpaDcRqResults dc_results;
  251         CpaStatus status = CPA_STATUS_FAIL;
  252         Cpa32U hdr_sz = 0;
  253         Cpa32U compressed_sz;
  254         Cpa32U num_src_buf = (src_len >> PAGE_SHIFT) + 2;
  255         Cpa32U num_dst_buf = (dst_len >> PAGE_SHIFT) + 2;
  256         Cpa32U num_add_buf = (add_len >> PAGE_SHIFT) + 2;
  257         Cpa32U bytes_left;
  258         Cpa32U dst_pages = 0;
  259         Cpa32U adler32 = 0;
  260         char *data;
  261         struct page *page;
  262         struct page **in_pages = NULL;
  263         struct page **out_pages = NULL;
  264         struct page **add_pages = NULL;
  265         Cpa32U page_off = 0;
  266         struct completion complete;
  267         Cpa32U page_num = 0;
  268         Cpa16U i;
  269 
  270         /*
  271          * We increment num_src_buf and num_dst_buf by 2 to allow
  272          * us to handle non page-aligned buffer addresses and buffers
  273          * whose sizes are not divisible by PAGE_SIZE.
  274          */
  275         Cpa32U src_buffer_list_mem_size = sizeof (CpaBufferList) +
  276             (num_src_buf * sizeof (CpaFlatBuffer));
  277         Cpa32U dst_buffer_list_mem_size = sizeof (CpaBufferList) +
  278             ((num_dst_buf + num_add_buf) * sizeof (CpaFlatBuffer));
  279 
  280         status = QAT_PHYS_CONTIG_ALLOC(&in_pages,
  281             num_src_buf * sizeof (struct page *));
  282         if (status != CPA_STATUS_SUCCESS)
  283                 goto fail;
  284 
  285         status = QAT_PHYS_CONTIG_ALLOC(&out_pages,
  286             num_dst_buf * sizeof (struct page *));
  287         if (status != CPA_STATUS_SUCCESS)
  288                 goto fail;
  289 
  290         status = QAT_PHYS_CONTIG_ALLOC(&add_pages,
  291             num_add_buf * sizeof (struct page *));
  292         if (status != CPA_STATUS_SUCCESS)
  293                 goto fail;
  294 
  295         i = (Cpa32U)atomic_inc_32_nv(&inst_num) % num_inst;
  296         dc_inst_handle = dc_inst_handles[i];
  297         session_handle = session_handles[i];
  298 
  299         cpaDcBufferListGetMetaSize(dc_inst_handle, num_src_buf,
  300             &buffer_meta_size);
  301         status = QAT_PHYS_CONTIG_ALLOC(&buffer_meta_src, buffer_meta_size);
  302         if (status != CPA_STATUS_SUCCESS)
  303                 goto fail;
  304 
  305         cpaDcBufferListGetMetaSize(dc_inst_handle, num_dst_buf + num_add_buf,
  306             &buffer_meta_size);
  307         status = QAT_PHYS_CONTIG_ALLOC(&buffer_meta_dst, buffer_meta_size);
  308         if (status != CPA_STATUS_SUCCESS)
  309                 goto fail;
  310 
  311         /* build source buffer list */
  312         status = QAT_PHYS_CONTIG_ALLOC(&buf_list_src, src_buffer_list_mem_size);
  313         if (status != CPA_STATUS_SUCCESS)
  314                 goto fail;
  315 
  316         flat_buf_src = (CpaFlatBuffer *)(buf_list_src + 1);
  317 
  318         buf_list_src->pBuffers = flat_buf_src; /* always point to first one */
  319 
  320         /* build destination buffer list */
  321         status = QAT_PHYS_CONTIG_ALLOC(&buf_list_dst, dst_buffer_list_mem_size);
  322         if (status != CPA_STATUS_SUCCESS)
  323                 goto fail;
  324 
  325         flat_buf_dst = (CpaFlatBuffer *)(buf_list_dst + 1);
  326 
  327         buf_list_dst->pBuffers = flat_buf_dst; /* always point to first one */
  328 
  329         buf_list_src->numBuffers = 0;
  330         buf_list_src->pPrivateMetaData = buffer_meta_src;
  331         bytes_left = src_len;
  332         data = src;
  333         page_num = 0;
  334         while (bytes_left > 0) {
  335                 page_off = ((long)data & ~PAGE_MASK);
  336                 page = qat_mem_to_page(data);
  337                 in_pages[page_num] = page;
  338                 flat_buf_src->pData = kmap(page) + page_off;
  339                 flat_buf_src->dataLenInBytes =
  340                     min((long)PAGE_SIZE - page_off, (long)bytes_left);
  341 
  342                 bytes_left -= flat_buf_src->dataLenInBytes;
  343                 data += flat_buf_src->dataLenInBytes;
  344                 flat_buf_src++;
  345                 buf_list_src->numBuffers++;
  346                 page_num++;
  347         }
  348 
  349         buf_list_dst->numBuffers = 0;
  350         buf_list_dst->pPrivateMetaData = buffer_meta_dst;
  351         bytes_left = dst_len;
  352         data = dst;
  353         page_num = 0;
  354         while (bytes_left > 0) {
  355                 page_off = ((long)data & ~PAGE_MASK);
  356                 page = qat_mem_to_page(data);
  357                 flat_buf_dst->pData = kmap(page) + page_off;
  358                 out_pages[page_num] = page;
  359                 flat_buf_dst->dataLenInBytes =
  360                     min((long)PAGE_SIZE - page_off, (long)bytes_left);
  361 
  362                 bytes_left -= flat_buf_dst->dataLenInBytes;
  363                 data += flat_buf_dst->dataLenInBytes;
  364                 flat_buf_dst++;
  365                 buf_list_dst->numBuffers++;
  366                 page_num++;
  367                 dst_pages++;
  368         }
  369 
  370         /* map additional scratch pages into the destination buffer list */
  371         bytes_left = add_len;
  372         data = add;
  373         page_num = 0;
  374         while (bytes_left > 0) {
  375                 page_off = ((long)data & ~PAGE_MASK);
  376                 page = qat_mem_to_page(data);
  377                 flat_buf_dst->pData = kmap(page) + page_off;
  378                 add_pages[page_num] = page;
  379                 flat_buf_dst->dataLenInBytes =
  380                     min((long)PAGE_SIZE - page_off, (long)bytes_left);
  381 
  382                 bytes_left -= flat_buf_dst->dataLenInBytes;
  383                 data += flat_buf_dst->dataLenInBytes;
  384                 flat_buf_dst++;
  385                 buf_list_dst->numBuffers++;
  386                 page_num++;
  387         }
  388 
  389         init_completion(&complete);
  390 
  391         if (dir == QAT_COMPRESS) {
  392                 QAT_STAT_BUMP(comp_requests);
  393                 QAT_STAT_INCR(comp_total_in_bytes, src_len);
  394 
  395                 cpaDcGenerateHeader(session_handle,
  396                     buf_list_dst->pBuffers, &hdr_sz);
  397                 buf_list_dst->pBuffers->pData += hdr_sz;
  398                 buf_list_dst->pBuffers->dataLenInBytes -= hdr_sz;
  399                 status = cpaDcCompressData(
  400                     dc_inst_handle, session_handle,
  401                     buf_list_src, buf_list_dst,
  402                     &dc_results, CPA_DC_FLUSH_FINAL,
  403                     &complete);
  404                 if (status != CPA_STATUS_SUCCESS) {
  405                         goto fail;
  406                 }
  407 
  408                 /* we now wait until the completion of the operation. */
  409                 wait_for_completion(&complete);
  410 
  411                 if (dc_results.status != CPA_STATUS_SUCCESS) {
  412                         status = CPA_STATUS_FAIL;
  413                         goto fail;
  414                 }
  415 
  416                 compressed_sz = dc_results.produced;
  417                 if (compressed_sz + hdr_sz + ZLIB_FOOT_SZ > dst_len) {
  418                         status = CPA_STATUS_INCOMPRESSIBLE;
  419                         goto fail;
  420                 }
  421 
  422                 /* get adler32 checksum and append footer */
  423                 *(Cpa32U*)(dst + hdr_sz + compressed_sz) =
  424                     BSWAP_32(dc_results.checksum);
  425 
  426                 *c_len = hdr_sz + compressed_sz + ZLIB_FOOT_SZ;
  427                 QAT_STAT_INCR(comp_total_out_bytes, *c_len);
  428         } else {
  429                 ASSERT3U(dir, ==, QAT_DECOMPRESS);
  430                 QAT_STAT_BUMP(decomp_requests);
  431                 QAT_STAT_INCR(decomp_total_in_bytes, src_len);
  432 
  433                 buf_list_src->pBuffers->pData += ZLIB_HEAD_SZ;
  434                 buf_list_src->pBuffers->dataLenInBytes -= ZLIB_HEAD_SZ;
  435                 status = cpaDcDecompressData(dc_inst_handle, session_handle,
  436                     buf_list_src, buf_list_dst, &dc_results, CPA_DC_FLUSH_FINAL,
  437                     &complete);
  438 
  439                 if (CPA_STATUS_SUCCESS != status) {
  440                         status = CPA_STATUS_FAIL;
  441                         goto fail;
  442                 }
  443 
  444                 /* we now wait until the completion of the operation. */
  445                 wait_for_completion(&complete);
  446 
  447                 if (dc_results.status != CPA_STATUS_SUCCESS) {
  448                         status = CPA_STATUS_FAIL;
  449                         goto fail;
  450                 }
  451 
  452                 /* verify adler checksum */
  453                 adler32 = *(Cpa32U *)(src + dc_results.consumed + ZLIB_HEAD_SZ);
  454                 if (adler32 != BSWAP_32(dc_results.checksum)) {
  455                         status = CPA_STATUS_FAIL;
  456                         goto fail;
  457                 }
  458                 *c_len = dc_results.produced;
  459                 QAT_STAT_INCR(decomp_total_out_bytes, *c_len);
  460         }
  461 
  462 fail:
  463         if (status != CPA_STATUS_SUCCESS && status != CPA_STATUS_INCOMPRESSIBLE)
  464                 QAT_STAT_BUMP(dc_fails);
  465 
  466         if (in_pages) {
  467                 for (page_num = 0;
  468                     page_num < buf_list_src->numBuffers;
  469                     page_num++) {
  470                         kunmap(in_pages[page_num]);
  471                 }
  472                 QAT_PHYS_CONTIG_FREE(in_pages);
  473         }
  474 
  475         if (out_pages) {
  476                 for (page_num = 0; page_num < dst_pages; page_num++) {
  477                         kunmap(out_pages[page_num]);
  478                 }
  479                 QAT_PHYS_CONTIG_FREE(out_pages);
  480         }
  481 
  482         if (add_pages) {
  483                 for (page_num = 0;
  484                     page_num < buf_list_dst->numBuffers - dst_pages;
  485                     page_num++) {
  486                         kunmap(add_pages[page_num]);
  487                 }
  488                 QAT_PHYS_CONTIG_FREE(add_pages);
  489         }
  490 
  491         QAT_PHYS_CONTIG_FREE(buffer_meta_src);
  492         QAT_PHYS_CONTIG_FREE(buffer_meta_dst);
  493         QAT_PHYS_CONTIG_FREE(buf_list_src);
  494         QAT_PHYS_CONTIG_FREE(buf_list_dst);
  495 
  496         return (status);
  497 }
  498 
  499 /*
  500  * Entry point for QAT accelerated compression / decompression.
  501  */
  502 int
  503 qat_compress(qat_compress_dir_t dir, char *src, int src_len,
  504     char *dst, int dst_len, size_t *c_len)
  505 {
  506         int ret;
  507         size_t add_len = 0;
  508         void *add = NULL;
  509 
  510         if (dir == QAT_COMPRESS) {
  511                 add_len = dst_len;
  512                 add = zio_data_buf_alloc(add_len);
  513         }
  514 
  515         ret = qat_compress_impl(dir, src, src_len, dst,
  516             dst_len, add, add_len, c_len);
  517 
  518         if (dir == QAT_COMPRESS)
  519                 zio_data_buf_free(add, add_len);
  520 
  521         return (ret);
  522 }
  523 
  524 static int
  525 param_set_qat_compress(const char *val, zfs_kernel_param_t *kp)
  526 {
  527         int ret;
  528         int *pvalue = kp->arg;
  529         ret = param_set_int(val, kp);
  530         if (ret)
  531                 return (ret);
  532         /*
  533          * zfs_qat_compress_disable = 0: enable qat compress
  534          * try to initialize qat instance if it has not been done
  535          */
  536         if (*pvalue == 0 && !qat_dc_init_done) {
  537                 ret = qat_dc_init();
  538                 if (ret != 0) {
  539                         zfs_qat_compress_disable = 1;
  540                         return (ret);
  541                 }
  542         }
  543         return (ret);
  544 }
  545 
  546 module_param_call(zfs_qat_compress_disable, param_set_qat_compress,
  547     param_get_int, &zfs_qat_compress_disable, 0644);
  548 MODULE_PARM_DESC(zfs_qat_compress_disable, "Enable/Disable QAT compression");
  549 
  550 #endif

Cache object: ba91ccb9eeb16103bb00cf5a9bc06a6c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.