Annotation of qemu/block/qed-cluster.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU Enhanced Disk Format Cluster functions
        !             3:  *
        !             4:  * Copyright IBM, Corp. 2010
        !             5:  *
        !             6:  * Authors:
        !             7:  *  Stefan Hajnoczi   <[email protected]>
        !             8:  *  Anthony Liguori   <[email protected]>
        !             9:  *
        !            10:  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
        !            11:  * See the COPYING.LIB file in the top-level directory.
        !            12:  *
        !            13:  */
        !            14: 
        !            15: #include "qed.h"
        !            16: 
        !            17: /**
        !            18:  * Count the number of contiguous data clusters
        !            19:  *
        !            20:  * @s:              QED state
        !            21:  * @table:          L2 table
        !            22:  * @index:          First cluster index
        !            23:  * @n:              Maximum number of clusters
        !            24:  * @offset:         Set to first cluster offset
        !            25:  *
        !            26:  * This function scans tables for contiguous allocated or free clusters.
        !            27:  */
        !            28: static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
        !            29:                                                   QEDTable *table,
        !            30:                                                   unsigned int index,
        !            31:                                                   unsigned int n,
        !            32:                                                   uint64_t *offset)
        !            33: {
        !            34:     unsigned int end = MIN(index + n, s->table_nelems);
        !            35:     uint64_t last = table->offsets[index];
        !            36:     unsigned int i;
        !            37: 
        !            38:     *offset = last;
        !            39: 
        !            40:     for (i = index + 1; i < end; i++) {
        !            41:         if (last == 0) {
        !            42:             /* Counting free clusters */
        !            43:             if (table->offsets[i] != 0) {
        !            44:                 break;
        !            45:             }
        !            46:         } else {
        !            47:             /* Counting allocated clusters */
        !            48:             if (table->offsets[i] != last + s->header.cluster_size) {
        !            49:                 break;
        !            50:             }
        !            51:             last = table->offsets[i];
        !            52:         }
        !            53:     }
        !            54:     return i - index;
        !            55: }
        !            56: 
        !            57: typedef struct {
        !            58:     BDRVQEDState *s;
        !            59:     uint64_t pos;
        !            60:     size_t len;
        !            61: 
        !            62:     QEDRequest *request;
        !            63: 
        !            64:     /* User callback */
        !            65:     QEDFindClusterFunc *cb;
        !            66:     void *opaque;
        !            67: } QEDFindClusterCB;
        !            68: 
        !            69: static void qed_find_cluster_cb(void *opaque, int ret)
        !            70: {
        !            71:     QEDFindClusterCB *find_cluster_cb = opaque;
        !            72:     BDRVQEDState *s = find_cluster_cb->s;
        !            73:     QEDRequest *request = find_cluster_cb->request;
        !            74:     uint64_t offset = 0;
        !            75:     size_t len = 0;
        !            76:     unsigned int index;
        !            77:     unsigned int n;
        !            78: 
        !            79:     if (ret) {
        !            80:         goto out;
        !            81:     }
        !            82: 
        !            83:     index = qed_l2_index(s, find_cluster_cb->pos);
        !            84:     n = qed_bytes_to_clusters(s,
        !            85:                               qed_offset_into_cluster(s, find_cluster_cb->pos) +
        !            86:                               find_cluster_cb->len);
        !            87:     n = qed_count_contiguous_clusters(s, request->l2_table->table,
        !            88:                                       index, n, &offset);
        !            89: 
        !            90:     ret = offset ? QED_CLUSTER_FOUND : QED_CLUSTER_L2;
        !            91:     len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
        !            92:               qed_offset_into_cluster(s, find_cluster_cb->pos));
        !            93: 
        !            94:     if (offset && !qed_check_cluster_offset(s, offset)) {
        !            95:         ret = -EINVAL;
        !            96:     }
        !            97: 
        !            98: out:
        !            99:     find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
        !           100:     qemu_free(find_cluster_cb);
        !           101: }
        !           102: 
        !           103: /**
        !           104:  * Find the offset of a data cluster
        !           105:  *
        !           106:  * @s:          QED state
        !           107:  * @request:    L2 cache entry
        !           108:  * @pos:        Byte position in device
        !           109:  * @len:        Number of bytes
        !           110:  * @cb:         Completion function
        !           111:  * @opaque:     User data for completion function
        !           112:  *
        !           113:  * This function translates a position in the block device to an offset in the
        !           114:  * image file.  It invokes the cb completion callback to report back the
        !           115:  * translated offset or unallocated range in the image file.
        !           116:  *
        !           117:  * If the L2 table exists, request->l2_table points to the L2 table cache entry
        !           118:  * and the caller must free the reference when they are finished.  The cache
        !           119:  * entry is exposed in this way to avoid callers having to read the L2 table
        !           120:  * again later during request processing.  If request->l2_table is non-NULL it
        !           121:  * will be unreferenced before taking on the new cache entry.
        !           122:  */
        !           123: void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
        !           124:                       size_t len, QEDFindClusterFunc *cb, void *opaque)
        !           125: {
        !           126:     QEDFindClusterCB *find_cluster_cb;
        !           127:     uint64_t l2_offset;
        !           128: 
        !           129:     /* Limit length to L2 boundary.  Requests are broken up at the L2 boundary
        !           130:      * so that a request acts on one L2 table at a time.
        !           131:      */
        !           132:     len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos);
        !           133: 
        !           134:     l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)];
        !           135:     if (!l2_offset) {
        !           136:         cb(opaque, QED_CLUSTER_L1, 0, len);
        !           137:         return;
        !           138:     }
        !           139:     if (!qed_check_table_offset(s, l2_offset)) {
        !           140:         cb(opaque, -EINVAL, 0, 0);
        !           141:         return;
        !           142:     }
        !           143: 
        !           144:     find_cluster_cb = qemu_malloc(sizeof(*find_cluster_cb));
        !           145:     find_cluster_cb->s = s;
        !           146:     find_cluster_cb->pos = pos;
        !           147:     find_cluster_cb->len = len;
        !           148:     find_cluster_cb->cb = cb;
        !           149:     find_cluster_cb->opaque = opaque;
        !           150:     find_cluster_cb->request = request;
        !           151: 
        !           152:     qed_read_l2_table(s, request, l2_offset,
        !           153:                       qed_find_cluster_cb, find_cluster_cb);
        !           154: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.