From patchwork Wed Aug 15 18:48:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?0LDRgNC60LDQtNC40Lkg0LjQstCw0L3QvtCy?= X-Patchwork-Id: 10566845 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5F65213B4 for ; Wed, 15 Aug 2018 20:49:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D4542AE1B for ; Wed, 15 Aug 2018 20:49:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F3A22AE1E; Wed, 15 Aug 2018 20:49:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7A1922AE1B for ; Wed, 15 Aug 2018 20:49:04 +0000 (UTC) Received: from localhost ([::1]:52105 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fq2iz-0004Xk-O9 for patchwork-qemu-devel@patchwork.kernel.org; Wed, 15 Aug 2018 16:49:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43274) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fq0qU-0001vN-Td for qemu-devel@nongnu.org; Wed, 15 Aug 2018 14:48:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fq0qR-0006dL-4O for qemu-devel@nongnu.org; Wed, 15 Aug 2018 14:48:38 -0400 Received: from mail-lf1-x132.google.com ([2a00:1450:4864:20::132]:42145) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fq0qQ-0006WH-0S for qemu-devel@nongnu.org; Wed, 15 Aug 2018 14:48:34 -0400 Received: by mail-lf1-x132.google.com with SMTP id 95-v6so1578410lfy.9 for ; Wed, 15 Aug 2018 11:48:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=WvbLx7vPgguGuDi4URHO4fwj9vT9ZDczP1f6NitMNY8=; b=OmZJCdOGCURYxKNYuX80RiGykhEMaQvdFhn1c96vdtNGxnRyJcAS9ru5PMZhF6Ixfu iU28XtYXUt1pbRoZdngLjkhFZNUFkbScx20kpVH6+XtLs9ctycwlx3E33PaUUhMISNae nQPCqSqguivfxjcABJHzdyzQh2e/Vt/m0WK8RUw7UsE9mZruWeMZhjaSO6Sf6czWEKYa sXnwIWkkLivf+/2+sxwmhrztRiSzQpFIG9BGdp+BlcsFhJWxksyGTXkBSpMQob8fKav8 ghOD/Hyki9ankdfe71EjV4ZMxdNbRp3zu4ZNffws7cVb8b5qIE1lyy92DYXHytrEOP4S kOWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=WvbLx7vPgguGuDi4URHO4fwj9vT9ZDczP1f6NitMNY8=; b=nDYMlxVyAQrA+7XYr/KHgsP49p1vTY8KZZmp7P8f6bfvwbLDqF4EoBjbT1tzPoc+Kx RIw6pgzAjE8Ncn852I3K+Ey9ZLiiHpLBVbN6JjSK29eQevKxQ5vPWtbtjQGIU0ZGiOQ0 rm+gwmZPvhQkyCO5VXfMF99iap4KDzgj8ZnUNzd4xLKkFKingWNRW4wM7/vxx4lH1R6p sysVoHUSj54gxgOcrQBr8taQDyPdVKIsRhxL+o0QR0lsDzh6l+oXA6dHG/4QZ72jfZTn QAhz0F9Gz8DhTFbynxKemvEheywg5Dpd6eYaHewkimlx9lzy9t9f0tVWJN9wvjs4iGxK 73iw== X-Gm-Message-State: AOUpUlHZ1DmdUA7R4n0hgA5BOIN1aeMgzY4y5txVKrVWlfXd6wXmN7ZL CXBgO0coaiFszcJBBQbjhBfwRnJ5 X-Google-Smtp-Source: AA+uWPyAvAxSKhfC7Nq14oW1MX22ySGFYLlAfgqCKg+OCpUty0fFcbh7qh9mD9XStuGaLGy4UrTZgQ== X-Received: by 2002:a19:c646:: with SMTP id w67-v6mr1050667lff.108.1534358911498; Wed, 15 Aug 2018 11:48:31 -0700 (PDT) Received: from localhost.localdomain ([178.57.116.28]) by smtp.gmail.com with ESMTPSA id q72-v6sm4150837lja.6.2018.08.15.11.48.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Aug 2018 11:48:30 -0700 (PDT) From: Arkasha To: qemu-devel@nongnu.org Date: Wed, 15 Aug 2018 21:48:19 +0300 Message-Id: <1534358899-32647-1-git-send-email-ivanovrkasha@gmail.com> X-Mailer: git-send-email 2.7.4 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::132 X-Mailman-Approved-At: Wed, 15 Aug 2018 16:46:51 -0400 Subject: [Qemu-devel] [PATCH] block: increased maximum size of vvfat devices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, Arkasha , pavel.dovgaluk@ispras.ru, mreitz@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This fixes the problem of the impossibility to create FAT disks larger than 504 mb: The change CHS made it possible to obtain a larger disk. Also, auto-detection of disk parameters was added depending on the volume of the connected files: The size of all folders and files on the created disk is calculated and the size of the FAT table is added. This size allows to choose the future size of the FAT drive from the standard limitations. Signed-off-by: Ivanov Arkasha --- block/vvfat.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 11 deletions(-) { BDRVVVFATState *s = bs->opaque; int cyls, heads, secs; + long int size_disk; bool floppy; const char *dirname, *label; QemuOpts *opts; Error *local_err = NULL; int ret; #ifdef DEBUG vvv = s; #endif @@ -1181,6 +1217,30 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, s->fat_type = qemu_opt_get_number(opts, "fat-type", 0); floppy = qemu_opt_get_bool(opts, "floppy", false); + unsigned int cluster; + long int sum = 0; + if (floppy) { + if (!s->fat_type) { + s->sectors_per_cluster = 2; + } else { + s->sectors_per_cluster = 1; + } + } else if (s->fat_type == 12) { + s->offset_to_bootsector = 0x3f; + s->sectors_per_cluster = 0x10; + } else { + s->offset_to_bootsector = 0x3f; + /* LATER TODO: if FAT32, adjust */ + s->sectors_per_cluster = 0x80; + } + + cluster = s->sectors_per_cluster * 0x200; + sum += find_size(dirname, cluster); + /* TODO: if there are more entries, bootsector has to be adjusted! */ + s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster; + /*File size + boot sector size + root directory size*/ + sum += 512 + s->root_entries * 32; memset(s->volume_label, ' ', sizeof(s->volume_label)); label = qemu_opt_get(opts, "label"); @@ -1201,24 +1261,38 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, if (!s->fat_type) { s->fat_type = 12; secs = 36; - s->sectors_per_cluster = 2; } else { secs = s->fat_type == 12 ? 18 : 36; - s->sectors_per_cluster = 1; } cyls = 80; heads = 2; } else { - /* 32MB or 504MB disk*/ if (!s->fat_type) { s->fat_type = 16; } - s->offset_to_bootsector = 0x3f; + size_disk = 528482304; cyls = s->fat_type == 12 ? 64 : 1024; heads = 16; secs = 63; - } + if (!check_size(s->offset_to_bootsector, cyls, heads, + secs, s->sectors_per_cluster, + s->fat_type, sum, size_disk)) { + cyls = s->fat_type == 12 ? 64 : 1024; + heads = 256; + secs = 63; + size_disk = 8455716864; + if (!check_size(s->offset_to_bootsector, cyls, heads, + secs, s->sectors_per_cluster, + s->fat_type, sum, size_disk)) { + cyls = s->fat_type == 12 ? 64 : 65536; + heads = 16; + secs = 255; + } + } + } switch (s->fat_type) { case 32: warn_report("FAT32 has not been tested. You are welcome to do so!"); @@ -1236,7 +1310,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, s->bs = bs; - /* LATER TODO: if FAT32, adjust */ - s->sectors_per_cluster=0x10; s->current_cluster=0xffffffff; @@ -1440,7 +1513,7 @@ read_cluster_directory: static void print_direntry(const direntry_t* direntry) { int j = 0; - char buffer[1024]; + char buffer[65536]; fprintf(stderr, "direntry %p: ", direntry); if(!direntry) diff --git a/block/vvfat.c b/block/vvfat.c index fc41841..8343019 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -77,6 +77,43 @@ static void checkpoint(void); #define DIR_KANJI_FAKE 0x05 #define DIR_FREE 0x00 +static bool check_size(uint32_t offset_to_bootsector, int cyls, int heads, + int secs, uint8_t sectors_per_cluster, int fat_type, + long int sum, long int size_disk) +{ + uint32_t sector_count = cyls * heads * secs - offset_to_bootsector; + int i = 1 + sectors_per_cluster * 0x200 * 8 / fat_type; + uint16_t sectors_per_fat = (sector_count + i) / i; + /*size + FAT1 and FAT2 table size*/ + if ((sum + sectors_per_fat * 512 * 2) < size_disk) { + return true; + } + return false; +} +static long int find_size(const char* dirname, unsigned int cluster) +{ + long int sum=0; + DIR *dir = opendir(dirname); + struct dirent *entry; + while ((entry = readdir(dir))) { + unsigned int length = strlen(dirname) + 2 + strlen(entry->d_name); + char *buffer; + struct stat st; + buffer = g_malloc(length); + snprintf(buffer, length, "%s/%s", dirname, entry->d_name); + if (stat(buffer, &st) < 0) { + g_free(buffer); + continue; + } + if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..") + && S_ISDIR(st.st_mode)) { + sum += find_size(buffer, cluster); + } + g_free(buffer); + sum += (st.st_size + cluster - 1) / (cluster) * (cluster); + } + closedir(dir); + return sum; +} + /* dynamic array functions */ typedef struct array_t { char* pointer; @@ -949,7 +986,6 @@ static int init_directories(BDRVVVFATState* s, init_fat(s); - /* TODO: if there are more entries, bootsector has to be adjusted! */ - s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster; s->cluster_count=sector2cluster(s, s->sector_count); mapping = array_get_next(&(s->mapping)); @@ -1154,12 +1190,12 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,