From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1aauQv-0004TW-50 for mharc-grub-devel@gnu.org; Tue, 01 Mar 2016 19:14:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52580) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aauQr-0004Pc-PT for grub-devel@gnu.org; Tue, 01 Mar 2016 19:14:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aauQp-0001Le-0q for grub-devel@gnu.org; Tue, 01 Mar 2016 19:14:25 -0500 Received: from mail-wm0-x230.google.com ([2a00:1450:400c:c09::230]:35366) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aauQo-0001LJ-Mq for grub-devel@gnu.org; Tue, 01 Mar 2016 19:14:22 -0500 Received: by mail-wm0-x230.google.com with SMTP id l68so61763325wml.0 for ; Tue, 01 Mar 2016 16:14:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references; bh=0PvvbB4l5IMkz139UhSxn8bqAirkAx+04xhp/frIaw8=; b=XJCk/iP+XKR/su0QoLS5pHrqK9zB/UNXoSL1GyCJYmPp1+oXZ9RgvdMv8201WELPoU g2thldJYQ2iA4BQkCaNWdmsPtKlZk+3izEwDfg6cOHqZc/bjpU/RkxiIUM6w1whLMUPn qGwNB9Xu+nM+VLu5N7FPnYvw0HeIX7HVi2raU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=0PvvbB4l5IMkz139UhSxn8bqAirkAx+04xhp/frIaw8=; b=WFxH0OdkZmDsLKleCGK3ukHDsXxU6/Ffz3idAabMVW1iBSuULtcCAtzI2UgAq2A3nJ 9nZd8bh9hc9Qq6frBoO3YfqC5eerxhiXGgKpgnvcH9J+7qB5Q5ttYQNeP4n8thpDX6bd YyBEU2sZx77bYdMp5b4sF34bNz8g16rRTk6ejBC8pf1aFa3yc+zEbCOuEA7dZMEUApYD hEYNm0kQxO3XJ6FxL4vVPIBd3idYAyNnX5+pyZpPTjlxwb8N2zrEwBNLXgo0GT6MR/e8 GdcucoQxxM1mX2gzGj/WjFXyiRD+X/qGwt4e8gVMziMrCboDU3tf1lXBFIgrJl98RCQR n22g== X-Gm-Message-State: AD7BkJL8EWYx2DRPY5UO7FpTBvGswjeNFqsCew79ypRD+cJfnnQtOVpDaHZqBPEPFUoqPEqc X-Received: by 10.28.211.130 with SMTP id k124mr1566767wmg.7.1456877662112; Tue, 01 Mar 2016 16:14:22 -0800 (PST) Received: from mohikan.mushroom.smurfnet.nu (cpc92308-cmbg19-2-0-cust814.5-4.cable.virginm.net. [82.24.251.47]) by smtp.gmail.com with ESMTPSA id ls5sm33035554wjb.33.2016.03.01.16.14.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 01 Mar 2016 16:14:21 -0800 (PST) From: Leif Lindholm To: grub-devel@gnu.org Subject: [PATCH v2 3/3] disk: read into cache directly Date: Wed, 2 Mar 2016 00:14:12 +0000 Message-Id: <1456877652-19389-4-git-send-email-leif.lindholm@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1456877652-19389-1-git-send-email-leif.lindholm@linaro.org> References: <1456877652-19389-1-git-send-email-leif.lindholm@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::230 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Mar 2016 00:14:27 -0000 From: Andrei Borzenkov --- grub-core/kern/disk.c | 96 +++++++++++++++++++++++++++++++-------------------- grub-core/lib/disk.c | 6 ++-- include/grub/disk.h | 11 +++++- 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 60a920b..0acf660 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -56,6 +56,20 @@ grub_err_t (*grub_disk_write_weak) (grub_disk_t disk, #include "disk_common.c" void +grub_disk_cache_free (struct grub_cache_buffer *buf) +{ + if (!buf->count) + /* FIXME This means corruption; what can we do? */ + return; + + if (!--buf->count) + { + grub_free (buf->data); + grub_free (buf); + } +} + +void grub_disk_cache_invalidate_all (void) { unsigned i; @@ -64,10 +78,10 @@ grub_disk_cache_invalidate_all (void) { struct grub_disk_cache *cache = grub_disk_cache_table + i; - if (cache->data && ! cache->lock) + if (cache->buffer && ! cache->lock) { - grub_free (cache->data); - cache->data = 0; + grub_disk_cache_free (cache->buffer); + cache->buffer = 0; } } } @@ -82,14 +96,14 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); cache = grub_disk_cache_table + cache_index; - if (cache->dev_id == dev_id && cache->disk_id == disk_id + if (cache->buffer && cache->dev_id == dev_id && cache->disk_id == disk_id && cache->sector == sector) { cache->lock = 1; #if DISK_CACHE_STATS grub_disk_cache_hits++; #endif - return cache->data; + return cache->buffer->data + cache->offset; } #if DISK_CACHE_STATS @@ -116,28 +130,36 @@ grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, static grub_err_t grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id, - grub_disk_addr_t sector, const char *data) + grub_disk_addr_t sector, grub_disk_addr_t n, char *data) { - unsigned cache_index; - struct grub_disk_cache *cache; + struct grub_cache_buffer *buf; + grub_addr_t offset; - cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + cache_index; + buf = grub_malloc (sizeof (*buf)); + if (! buf) + return grub_errno; + buf->data = data; + buf->count = 0; - cache->lock = 1; - grub_free (cache->data); - cache->data = 0; - cache->lock = 0; + for (offset = 0 ; n > 0; sector += GRUB_DISK_CACHE_SIZE, offset += (GRUB_DISK_CACHE_SIZE * GRUB_DISK_SECTOR_SIZE), n--) + { + unsigned cache_index; + struct grub_disk_cache *cache; - cache->data = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); - if (! cache->data) - return grub_errno; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; - grub_memcpy (cache->data, data, - GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); - cache->dev_id = dev_id; - cache->disk_id = disk_id; - cache->sector = sector; + cache->lock = 1; + if (cache->buffer) + grub_disk_cache_free (cache->buffer); + cache->buffer = buf; + cache->offset = offset; + buf->count++; + cache->lock = 0; + cache->dev_id = dev_id; + cache->disk_id = disk_id; + cache->sector = sector; + } return GRUB_ERR_NONE; } @@ -357,13 +379,11 @@ grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector, /* Copy it and store it in the disk cache. */ grub_memcpy (buf, tmp_buf + offset, size); grub_disk_cache_store (disk->dev->id, disk->id, - sector, tmp_buf); - grub_free (tmp_buf); + sector, 1, tmp_buf); return GRUB_ERR_NONE; } } - grub_free (tmp_buf); grub_errno = GRUB_ERR_NONE; { @@ -380,10 +400,6 @@ grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector, num = ((size + offset + (1ULL << (disk->log_sector_size)) - 1) >> (disk->log_sector_size)); - tmp_buf = disk->malloc (disk, num << disk->log_sector_size); - if (!tmp_buf) - return grub_errno; - if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector), num, tmp_buf)) { @@ -488,22 +504,26 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (agglomerate) { - grub_disk_addr_t i; + void *cache = disk->malloc (disk, agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + + if (!cache) + return grub_errno; err = (disk->dev->read) (disk, transform_sector (disk, sector), agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - disk->log_sector_size), - buf); + cache); if (err) - return err; + { + grub_free (cache); + return err; + } - for (i = 0; i < agglomerate; i ++) - grub_disk_cache_store (disk->dev->id, disk->id, - sector + (i << GRUB_DISK_CACHE_BITS), - (char *) buf - + (i << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS))); + grub_memcpy (buf, cache, + agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + grub_disk_cache_store (disk->dev->id, disk->id, + sector, agglomerate, cache); if (disk->read_hook) diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c index 0f18688..07fb117 100644 --- a/grub-core/lib/disk.c +++ b/grub-core/lib/disk.c @@ -42,11 +42,11 @@ grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, cache = grub_disk_cache_table + cache_index; if (cache->dev_id == dev_id && cache->disk_id == disk_id - && cache->sector == sector && cache->data) + && cache->sector == sector && cache->buffer) { cache->lock = 1; - grub_free (cache->data); - cache->data = 0; + grub_disk_cache_free (cache->buffer); + cache->buffer = 0; cache->lock = 0; } } diff --git a/include/grub/disk.h b/include/grub/disk.h index 0fdd779..bbb7830 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -238,16 +238,25 @@ grub_stop_disk_firmware (void) } } +struct grub_cache_buffer + { + char *data; + unsigned count; + }; + /* Disk cache. */ struct grub_disk_cache { enum grub_disk_dev_id dev_id; unsigned long disk_id; grub_disk_addr_t sector; - char *data; + struct grub_cache_buffer *buffer; + grub_addr_t offset; int lock; }; +void EXPORT_FUNC(grub_disk_cache_free) (struct grub_cache_buffer *buf); + extern struct grub_disk_cache EXPORT_VAR(grub_disk_cache_table)[GRUB_DISK_CACHE_NUM]; #if defined (GRUB_UTIL) -- 2.1.4