This improves sequential read and write speed.
}
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,
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))
{
}
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;
/* 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))
{
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--)
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;
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);
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);
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;
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");
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");
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 */
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;