]> xenbits.xensource.com Git - people/dstodden/blktap.git/commitdiff
CA-46079: Recover the image storage type.
authorDaniel Stodden <daniel.stodden@citrix.com>
Thu, 30 Sep 2010 21:01:40 +0000 (14:01 -0700)
committerDaniel Stodden <daniel.stodden@citrix.com>
Thu, 30 Sep 2010 21:01:40 +0000 (14:01 -0700)
Used to be a message parameter passed in at open time, then down
through the VBD and images up to the driver. Replaced by stat() and
statfs().

The vbd->storage isn't really applicable with cross-SR VHD chains
became more popular, so removed. We keep the driver->storage, but only
for verbosity. Drivers with type-dependent code call
tapdisk_storage_type() during td_open() are encouraged to store the
result here.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
18 files changed:
control/tap-ctl-open.c
drivers/Makefile
drivers/block-vhd.c
drivers/tapdisk-control.c
drivers/tapdisk-diff.c
drivers/tapdisk-driver.c
drivers/tapdisk-driver.h
drivers/tapdisk-image.c
drivers/tapdisk-image.h
drivers/tapdisk-interface.c
drivers/tapdisk-ipc.c
drivers/tapdisk-storage.c [new file with mode: 0644]
drivers/tapdisk-storage.h [new file with mode: 0644]
drivers/tapdisk-stream.c
drivers/tapdisk-vbd.c
drivers/tapdisk-vbd.h
include/blktaplib.h
include/tapdisk-message.h

index fb9e9ef037c33298123558ef79f3c750bcaf63b4..274ac0434e429bd10c942421c1c26a9d65f5b89b 100644 (file)
@@ -45,7 +45,6 @@ tap_ctl_open(const int id, const int minor, const char *params, int flags,
        memset(&message, 0, sizeof(message));
        message.type = TAPDISK_MESSAGE_OPEN;
        message.cookie = minor;
-       message.u.params.storage = TAPDISK_STORAGE_TYPE_DEFAULT;
        message.u.params.devnum = minor;
        message.u.params.prt_devnum = prt_minor;
        message.u.params.flags = flags;
index e01e8efee2e2e10268ba7f378ba10c8884dab9d7..1fec139ea33e56d7c515601908f9ef54b231e053 100644 (file)
@@ -53,6 +53,7 @@ TAP-OBJS  += tapdisk-utils.o
 TAP-OBJS  += tapdisk-disktype.o
 TAP-OBJS  += tapdisk-syslog.o
 TAP-OBJS  += tapdisk-stats.o
+TAP-OBJS  += tapdisk-storage.o
 TAP-OBJS  += io-optimize.o
 TAP-OBJS  += lock.o
 
index a498427f01aee32e961a7aaf7893a5b8efdd88e1..59fa5ea8e8775daf2798a6e66e6e7afeb8b578a4 100644 (file)
@@ -68,6 +68,7 @@
 #include "tapdisk-driver.h"
 #include "tapdisk-interface.h"
 #include "tapdisk-disktype.h"
+#include "tapdisk-storage.h"
 
 unsigned int SPB;
 
@@ -727,6 +728,8 @@ _vhd_open(td_driver_t *driver, const char *name, td_flag_t flags)
                              VHD_FLAG_OPEN_NO_CACHE);
 
        /* pre-allocate for all but NFS and LVM storage */
+       driver->storage = tapdisk_storage_type(name);
+
        if (driver->storage != TAPDISK_STORAGE_TYPE_NFS &&
            driver->storage != TAPDISK_STORAGE_TYPE_LVM)
                vhd_flags |= VHD_FLAG_OPEN_PREALLOCATE;
index bce72c6e9b4753f949edd71a3787c9c29a0bf3a2..2026ae76ff3f50d88634648aef3c33f5887619bb 100644 (file)
@@ -747,7 +747,6 @@ tapdisk_control_open_image(struct tapdisk_ctl_conn *conn,
 
        err = tapdisk_vbd_open_vdi(vbd,
                                   type, path,
-                                  request->u.params.storage,
                                   flags, request->u.params.prt_devnum,
                                   secondary_type, secondary_path);
        if (err)
index 56cbe2993291ed19eff396c6beee5a1b85910c61..e383d074c99ff8798b1b05d5af4e6e4138eda25e 100644 (file)
@@ -572,7 +572,6 @@ tapdisk_stream_open_image(struct tapdisk_stream *s, const char *path, int type)
        tapdisk_vbd_set_callback(s->vbd, tapdisk_stream_dequeue, s);
 
        err = tapdisk_vbd_open_vdi(s->vbd, type, path,
-                                  TAPDISK_STORAGE_TYPE_DEFAULT,
                                   TD_OPEN_RDONLY, -1, -1, NULL);
        if (err)
                goto out;
index 7a9cc604c7f7a36f35d01c6694d3e27be063ae88..af8bdc1a04296ef9d5933ca8122a5e1848dc65a0 100644 (file)
@@ -35,7 +35,7 @@
 #include "tapdisk-stats.h"
 
 td_driver_t *
-tapdisk_driver_allocate(int type, char *name, td_flag_t flags, int storage)
+tapdisk_driver_allocate(int type, char *name, td_flag_t flags)
 {
        int err;
        td_driver_t *driver;
@@ -55,7 +55,7 @@ tapdisk_driver_allocate(int type, char *name, td_flag_t flags, int storage)
 
        driver->ops     = ops;
        driver->type    = type;
-       driver->storage = storage;
+       driver->storage = -1;
        driver->data    = calloc(1, ops->private_data_size);
        if (!driver->data)
                goto fail;
index 62b5ae1efe2765ece46f4730a208b16d31dbfd40..14d466be3bf4565c8fd277c8a6ef80f5dd85f009 100644 (file)
@@ -52,7 +52,7 @@ struct td_driver_handle {
        struct list_head             next;
 };
 
-td_driver_t *tapdisk_driver_allocate(int, char *, td_flag_t, int);
+td_driver_t *tapdisk_driver_allocate(int, char *, td_flag_t);
 void tapdisk_driver_free(td_driver_t *);
 
 void tapdisk_driver_queue_tiocb(td_driver_t *, struct tiocb *);
index bdeda4540bea75c8f107f573d46c4266fec95f73..43c633b38949b160b07d6aef915fd07c8d6dffa1 100644 (file)
@@ -38,8 +38,7 @@
 #define ERR(_err, _f, _a...) tlog_error(_err, _f, ##_a)
 
 td_image_t *
-tapdisk_image_allocate(char *file, int type, int storage,
-                      td_flag_t flags, void *private)
+tapdisk_image_allocate(char *file, int type, td_flag_t flags, void *private)
 {
        int err;
        td_image_t *image;
@@ -56,7 +55,6 @@ tapdisk_image_allocate(char *file, int type, int storage,
 
        image->type    = type;
        image->flags   = flags;
-       image->storage = storage;
        image->private = private;
        INIT_LIST_HEAD(&image->next);
 
index 7134be5bf19fa8acea06bbbcc36815364b8e289c..60f529b9dc2479ee17127f3159f42aa6819aba8c 100644 (file)
@@ -36,7 +36,6 @@ struct td_image_handle {
        char                        *name;
 
        td_flag_t                    flags;
-       int                          storage;
 
        td_driver_t                 *driver;
        td_disk_info_t               info;
@@ -65,7 +64,7 @@ struct td_image_handle {
        } stats;
 };
 
-td_image_t *tapdisk_image_allocate(char *, int, int, td_flag_t, void *);
+td_image_t *tapdisk_image_allocate(char *, int, td_flag_t, void *);
 void tapdisk_image_free(td_image_t *);
 
 int tapdisk_image_check_td_request(td_image_t *, td_request_t);
index 2995e5fed7aeed2875b63e7228ae1fcbb09f64db..af3c3150265a86743d5b50449c2b1633c5d076c2 100644 (file)
@@ -72,8 +72,7 @@ __td_open(td_image_t *image, td_disk_info_t *info)
        if (!driver) {
                driver = tapdisk_driver_allocate(image->type,
                                                 image->name,
-                                                image->flags,
-                                                image->storage);
+                                                image->flags);
                if (!driver)
                        return -ENOMEM;
 
index 24cf1437acee1a03617dff930626a1533ce520ae..8998dc6c28a0f602071c8bf5a1fcb651853bbcc6 100644 (file)
@@ -309,7 +309,6 @@ tapdisk_ipc_read(td_ipc_t *ipc)
 
                err   = tapdisk_vbd_open(vbd,
                                         type, path,
-                                        message.u.params.storage,
                                         message.u.params.devnum,
                                         devname, flags);
                free(devname);
diff --git a/drivers/tapdisk-storage.c b/drivers/tapdisk-storage.c
new file mode 100644 (file)
index 0000000..5ddc369
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2010, Citrix Systems, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include "tapdisk-storage.h"
+
+#ifndef NFS_SUPER_MAGIC
+#define NFS_SUPER_MAGIC 0x6969
+#endif
+
+static int
+__tapdisk_fs_storage_type(const char *rpath)
+{
+       struct statfs fst;
+       int type, err;
+
+       err = statfs(rpath, &fst);
+       if (err)
+               return -errno;
+
+       switch (fst.f_type) {
+       case NFS_SUPER_MAGIC:
+               type = TAPDISK_STORAGE_TYPE_NFS;
+               break;
+       default:
+               type = TAPDISK_STORAGE_TYPE_EXT;
+               break;
+       }
+
+       return type;
+}
+
+static int
+__tapdisk_blk_storage_type(const char *rpath)
+{
+       return TAPDISK_STORAGE_TYPE_LVM;
+}
+
+int
+tapdisk_storage_type(const char *path)
+{
+       char rpath[PATH_MAX], *p;
+       struct stat st;
+       int err, rv;
+
+       p = realpath(path, rpath);
+       if (!p)
+               return -errno;
+
+       err = stat(rpath, &st);
+       if (err)
+               return -errno;
+
+       switch (st.st_mode & S_IFMT) {
+       case S_IFBLK:
+               rv = __tapdisk_blk_storage_type(rpath);
+               break;
+       case S_IFREG:
+               rv = __tapdisk_fs_storage_type(rpath);
+               break;
+       default:
+               rv = -EINVAL;
+               break;
+       }
+
+       return rv;
+}
+
+const char *
+tapdisk_storage_name(int type)
+{
+       const char *name;
+
+       switch (type) {
+       case TAPDISK_STORAGE_TYPE_NFS:
+               return "nfs";
+       case TAPDISK_STORAGE_TYPE_EXT:
+               return "ext";
+       case TAPDISK_STORAGE_TYPE_LVM:
+               return "lvm";
+       case -1:
+               return "n/a";
+       default:
+               return "<unknown-type>";
+       }
+}
diff --git a/drivers/tapdisk-storage.h b/drivers/tapdisk-storage.h
new file mode 100644 (file)
index 0000000..b034442
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _TAPDISK_STORAGE_H_
+#define _TAPDISK_STORAGE_H_
+
+#define TAPDISK_STORAGE_TYPE_NFS       1
+#define TAPDISK_STORAGE_TYPE_EXT       2
+#define TAPDISK_STORAGE_TYPE_LVM       3
+
+int tapdisk_storage_type(const char *path);
+const char *tapdisk_storage_name(int type);
+
+#endif
index 20c000998c625016101b5bca054edf6fff383240..2328a7d4ddd54595800aafba44f75a61e38d8cca 100644 (file)
@@ -351,7 +351,6 @@ tapdisk_stream_open_image(struct tapdisk_stream *s, const char *path, int type)
        tapdisk_vbd_set_callback(s->vbd, tapdisk_stream_dequeue, s);
 
        err = tapdisk_vbd_open_vdi(s->vbd, type, path,
-                                  TAPDISK_STORAGE_TYPE_DEFAULT,
                                   TD_OPEN_RDONLY, -1, -1, NULL);
        if (err)
                goto out;
index f467d6a20fb60d70f402c6f763a2e1b28c42a265..d20a07b48f2a763ad9a290c2a85aaaf65a754d8b 100644 (file)
@@ -46,6 +46,7 @@
 #include "tapdisk-disktype.h"
 #include "tapdisk-interface.h"
 #include "tapdisk-stats.h"
+#include "tapdisk-storage.h"
 
 #include "blktap2.h"
 
@@ -167,7 +168,12 @@ tapdisk_vbd_validate_chain(td_vbd_t *vbd)
        DPRINTF("VBD CHAIN:\n");
 
        tapdisk_vbd_for_each_image(vbd, image, tmp) {
-               DPRINTF("%s: %d\n", image->name, image->type);
+               DPRINTF("%s: type:%s(%d) storage:%s(%d)\n",
+                       image->name,
+                       tapdisk_disk_types[image->type]->name,
+                       image->type,
+                       tapdisk_storage_name(image->driver->storage),
+                       image->driver->storage);
 
                if (tapdisk_vbd_is_last_image(vbd, image))
                        break;
@@ -230,7 +236,6 @@ tapdisk_vbd_add_block_cache(td_vbd_t *vbd)
 
        cache = tapdisk_image_allocate(target->name,
                                       DISK_TYPE_BLOCK_CACHE,
-                                      target->storage,
                                       target->flags,
                                       target->private);
        if (!cache)
@@ -249,8 +254,7 @@ tapdisk_vbd_add_block_cache(td_vbd_t *vbd)
 
        cache->driver = tapdisk_driver_allocate(cache->type,
                                                cache->name,
-                                               cache->flags,
-                                               cache->storage);
+                                               cache->flags);
        if (!cache->driver) {
                err = -ENOMEM;
                goto fail;
@@ -289,7 +293,6 @@ tapdisk_vbd_add_local_cache(td_vbd_t *vbd)
 
        cache = tapdisk_image_allocate(parent->name,
                        DISK_TYPE_LOCAL_CACHE,
-                       parent->storage,
                        parent->flags,
                        parent->private);
 
@@ -302,9 +305,8 @@ tapdisk_vbd_add_local_cache(td_vbd_t *vbd)
                goto done;
 
        cache->driver = tapdisk_driver_allocate(cache->type,
-                       cache->name,
-                       cache->flags,
-                       cache->storage);
+                                               cache->name,
+                                               cache->flags);
 
        if (!cache->driver) {
                err = -ENOMEM;
@@ -341,18 +343,16 @@ tapdisk_vbd_add_secondary(td_vbd_t *vbd)
 
        leaf = tapdisk_vbd_first_image(vbd);
        second = tapdisk_image_allocate(vbd->secondary_name,
-                       vbd->secondary_type,
-                       leaf->storage,
-                       leaf->flags,
-                       leaf->private);
+                                       vbd->secondary_type,
+                                       leaf->flags,
+                                       leaf->private);
 
        if (!second)
                return -ENOMEM;
 
        second->driver = tapdisk_driver_allocate(second->type,
-                       second->name,
-                       second->flags,
-                       second->storage);
+                                                second->name,
+                                                second->flags);
 
        if (!second->driver) {
                err = -ENOMEM;
@@ -437,8 +437,7 @@ tapdisk_vbd_open_index(td_vbd_t *vbd)
        }
 
        flags = vbd->flags | TD_OPEN_RDONLY | TD_OPEN_SHAREABLE;
-       image = tapdisk_image_allocate(path, DISK_TYPE_VINDEX,
-                                      vbd->storage, flags, vbd);
+       image = tapdisk_image_allocate(path, DISK_TYPE_VINDEX, flags, vbd);
        if (!image) {
                err = -ENOMEM;
                goto fail;
@@ -472,7 +471,6 @@ tapdisk_vbd_add_dirty_log(td_vbd_t *vbd)
 
        log    = tapdisk_image_allocate(parent->name,
                                        DISK_TYPE_LOG,
-                                       parent->storage,
                                        parent->flags,
                                        vbd);
        if (!log)
@@ -480,8 +478,7 @@ tapdisk_vbd_add_dirty_log(td_vbd_t *vbd)
 
        driver = tapdisk_driver_allocate(log->type,
                                         log->name,
-                                        log->flags,
-                                        log->storage);
+                                        log->flags);
        if (!driver) {
                err = -ENOMEM;
                goto fail;
@@ -518,8 +515,7 @@ __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags)
 
        for (;;) {
                err   = -ENOMEM;
-               image = tapdisk_image_allocate(file, type,
-                                              vbd->storage, flags, vbd);
+               image = tapdisk_image_allocate(file, type, flags, vbd);
 
                if (file != vbd->name) {
                        free(file);
@@ -558,9 +554,6 @@ __tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags)
                        goto fail;
                }
 
-               if (!image->storage)
-                       image->storage = vbd->storage;
-
                tapdisk_vbd_add_image(vbd, image);
                image = NULL;
 
@@ -625,7 +618,7 @@ fail:
 
 int
 tapdisk_vbd_open_vdi(td_vbd_t *vbd, int type, const char *path,
-                    uint16_t storage, td_flag_t flags, int prt_devnum,
+                    td_flag_t flags, int prt_devnum,
                     int secondary_type, const char *secondary_name)
 {
        const disk_info_t *info;
@@ -653,7 +646,6 @@ tapdisk_vbd_open_vdi(td_vbd_t *vbd, int type, const char *path,
        }
 
        vbd->flags   = flags;
-       vbd->storage = storage;
        vbd->type    = type;
 
        err = __tapdisk_vbd_open_vdi(vbd, 0);
@@ -786,12 +778,11 @@ fail:
 
 int
 tapdisk_vbd_open(td_vbd_t *vbd, int type, const char *path,
-                uint16_t storage, int minor, const char *ring, td_flag_t flags)
+                int minor, const char *ring, td_flag_t flags)
 {
        int err;
 
-       err = tapdisk_vbd_open_vdi(vbd, type, path, storage, flags, -1, -1,
-                       NULL);
+       err = tapdisk_vbd_open_vdi(vbd, type, path, flags, -1, -1, NULL);
        if (err)
                goto out;
 
index ba1bcec631a97aaeccc1c015b8aacc92be49b87c..d69804aa5cc8cde38bb7398180f5fc44dcf41ff4 100644 (file)
@@ -90,8 +90,6 @@ struct td_vbd_handle {
        int                         minor;
        int                         type;
 
-       int                         storage;
-
        td_flag_t                   flags;
        td_flag_t                   state;
 
@@ -189,11 +187,11 @@ td_vbd_t *tapdisk_vbd_create(td_uuid_t);
 int tapdisk_vbd_initialize(int, int, td_uuid_t);
 void tapdisk_vbd_set_callback(td_vbd_t *, td_vbd_cb_t, void *);
 int tapdisk_vbd_open(td_vbd_t *, int, const char *,
-                    uint16_t, int, const char *, td_flag_t);
+                    int, const char *, td_flag_t);
 int tapdisk_vbd_close(td_vbd_t *);
 
-int tapdisk_vbd_open_vdi(td_vbd_t *, int, const char *, uint16_t, td_flag_t,
-               int, int, const char *);
+int tapdisk_vbd_open_vdi(td_vbd_t *, int, const char *, td_flag_t,
+                        int, int, const char *);
 void tapdisk_vbd_close_vdi(td_vbd_t *);
 
 int tapdisk_vbd_attach(td_vbd_t *, const char *, int);
index 221904dd83f6fc8dc5b3ced6358e34705ce3c467..9e0e3a4347d4c16c68ed262173a85e3b00e00989 100644 (file)
@@ -223,11 +223,6 @@ typedef struct msg_lock {
 #define CTLMSG_RESUME          17
 #define CTLMSG_RESUME_RSP      18
 
-#define TAPDISK_STORAGE_TYPE_NFS       1
-#define TAPDISK_STORAGE_TYPE_EXT       2
-#define TAPDISK_STORAGE_TYPE_LVM       3
-#define TAPDISK_STORAGE_TYPE_DEFAULT   TAPDISK_STORAGE_TYPE_EXT
-
 /* Abitrary values, must match the underlying driver... */
 #define MAX_TAP_DEV 1024
 
index bc17271d8984584599344a13ee01f4c74db57aee..970040c071c463ee1e93779b42d239ae793ce284 100644 (file)
@@ -59,7 +59,6 @@ typedef struct tapdisk_message_stat      tapdisk_message_stat_t;
 struct tapdisk_message_params {
        tapdisk_message_flag_t           flags;
 
-       uint8_t                          storage;
        uint32_t                         devnum;
        uint32_t                         domid;
        char                             path[TAPDISK_MESSAGE_MAX_PATH_LENGTH];