OSDN Git Service

Remember recently used cluster of each node.
authorrelan <relan@users.noreply.github.com>
Mon, 9 Nov 2009 18:58:50 +0000 (18:58 +0000)
committerrelan <relan@users.noreply.github.com>
Mon, 24 Aug 2015 05:26:10 +0000 (08:26 +0300)
This improves sequential read and write speed.

libexfat/cluster.c
libexfat/exfat.h
libexfat/io.c
libexfat/mount.c
libexfat/node.c

index 668acea..1de33bd 100644 (file)
@@ -69,17 +69,24 @@ cluster_t exfat_next_cluster(const struct exfat* ef,
 }
 
 cluster_t exfat_advance_cluster(const struct exfat* ef,
-               const struct exfat_node* node, cluster_t cluster, uint32_t count)
+               struct exfat_node* node, uint32_t count)
 {
        uint32_t i;
 
-       for (i = 0; i < count; i++)
+       if (node->fptr_index > count)
        {
-               cluster = exfat_next_cluster(ef, node, cluster);
-               if (CLUSTER_INVALID(cluster))
+               node->fptr_index = 0;
+               node->fptr_cluster = node->start_cluster;
+       }
+
+       for (i = node->fptr_index; i < count; i++)
+       {
+               node->fptr_cluster = exfat_next_cluster(ef, node, node->fptr_cluster);
+               if (CLUSTER_INVALID(node->fptr_cluster))
                        break;
        }
-       return cluster;
+       node->fptr_index = count;
+       return node->fptr_cluster;
 }
 
 static cluster_t find_bit_and_set(uint8_t* bitmap, cluster_t start,
@@ -206,7 +213,7 @@ static int grow_file(struct exfat* ef, struct exfat_node* node,
        if (node->start_cluster != EXFAT_CLUSTER_FREE)
        {
                /* get the last cluster of the file */
-               previous = exfat_advance_cluster(ef, node, node->start_cluster,
+               previous = exfat_advance_cluster(ef, node,
                                bytes2clusters(ef, node->size) - 1);
                if (CLUSTER_INVALID(previous))
                {
@@ -216,12 +223,14 @@ static int grow_file(struct exfat* ef, struct exfat_node* node,
        }
        else
        {
+               if (node->fptr_index != 0)
+                       exfat_bug("non-zero pointer index (%u)", node->fptr_index);
                /* file does not have clusters (i.e. is empty), allocate
                   the first one for it */
                previous = allocate_cluster(ef, 0);
                if (CLUSTER_INVALID(previous))
                        return -ENOSPC;
-               node->start_cluster = previous;
+               node->fptr_cluster = node->start_cluster = previous;
                difference--;
                /* file consists of only one cluster, so it's contiguous */
                node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
@@ -264,7 +273,7 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node,
        /* crop the file */
        if (current > difference)
        {
-               cluster_t last = exfat_advance_cluster(ef, node, node->start_cluster,
+               cluster_t last = exfat_advance_cluster(ef, node,
                                current - difference - 1);
                if (CLUSTER_INVALID(last))
                {
@@ -279,6 +288,8 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node,
                previous = node->start_cluster;
                node->start_cluster = EXFAT_CLUSTER_FREE;
        }
+       node->fptr_index = 0;
+       node->fptr_cluster = node->start_cluster;
 
        /* free remaining clusters */
        while (difference--)
index af92c98..edcd585 100644 (file)
@@ -38,6 +38,8 @@ struct exfat_node
        struct exfat_node* prev;
 
        int references;
+       uint32_t fptr_index;
+       cluster_t fptr_cluster;
        off_t meta1_offset, meta2_offset;
        cluster_t start_cluster;
        int flags;
@@ -80,7 +82,7 @@ void exfat_debug(const char* format, ...);
 
 void exfat_read_raw(void* buffer, size_t size, off_t offset, int fd);
 void exfat_write_raw(const void* buffer, size_t size, off_t offset, int fd);
-ssize_t exfat_read(const struct exfat* ef, const struct exfat_node* node,
+ssize_t exfat_read(const struct exfat* ef, struct exfat_node* node,
                void* buffer, size_t size, off_t offset);
 ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
                const void* buffer, size_t size, off_t offset);
@@ -96,7 +98,7 @@ off_t exfat_c2o(const struct exfat* ef, cluster_t cluster);
 cluster_t exfat_next_cluster(const struct exfat* ef,
                const struct exfat_node* node, cluster_t cluster);
 cluster_t exfat_advance_cluster(const struct exfat* ef,
-               const struct exfat_node* node, cluster_t cluster, uint32_t count);
+               struct exfat_node* node, uint32_t count);
 cluster_t exfat_allocate_cluster(struct exfat* ef, cluster_t previous);
 void exfat_free_cluster(struct exfat* ef, cluster_t cluster,
                cluster_t previous);
index d826079..ed7a255 100644 (file)
@@ -29,7 +29,7 @@ void exfat_write_raw(const void* buffer, size_t size, off_t offset, int fd)
                exfat_bug("failed to write %zu bytes to file at %llu", size, offset);
 }
 
-ssize_t exfat_read(const struct exfat* ef, const struct exfat_node* node,
+ssize_t exfat_read(const struct exfat* ef, struct exfat_node* node,
                void* buffer, size_t size, off_t offset)
 {
        cluster_t cluster;
@@ -41,8 +41,7 @@ ssize_t exfat_read(const struct exfat* ef, const struct exfat_node* node,
        if (size == 0)
                return 0;
 
-       cluster = exfat_advance_cluster(ef, node, node->start_cluster,
-                       offset / CLUSTER_SIZE(*ef->sb));
+       cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
        if (CLUSTER_INVALID(cluster))
        {
                exfat_error("got invalid cluster");
@@ -80,8 +79,7 @@ ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
        if (size == 0)
                return 0;
 
-       cluster = exfat_advance_cluster(ef, node, node->start_cluster,
-                       offset / CLUSTER_SIZE(*ef->sb));
+       cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
        if (CLUSTER_INVALID(cluster))
        {
                exfat_error("got invalid cluster");
index f0131e1..3c1d00f 100644 (file)
@@ -82,6 +82,7 @@ int exfat_mount(struct exfat* ef, const char* spec)
        memset(ef->root, 0, sizeof(struct exfat_node));
        ef->root->flags = EXFAT_ATTRIB_DIR;
        ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
+       ef->root->fptr_cluster = ef->root->start_cluster;
        ef->root->name[0] = cpu_to_le16('\0');
        ef->root->size = rootdir_size(ef);
        /* exFAT does not have time attributes for the root directory */
index 440d4f7..3fd36ea 100644 (file)
@@ -160,6 +160,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
                                        CLUSTER_SIZE(*ef->sb);
                        (*node)->size = le64_to_cpu(file_info->size);
                        (*node)->start_cluster = le32_to_cpu(file_info->start_cluster);
+                       (*node)->fptr_cluster = (*node)->start_cluster;
                        if (file_info->flag == EXFAT_FLAG_CONTIGUOUS)
                                (*node)->flags |= EXFAT_ATTRIB_CONTIGUOUS;
                        --continuations;