X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=lib%2Fexfat_dir.c;h=7c145f4a54978893f03ea6f07e81d001fca14324;hb=HEAD;hp=98e820f9404e1011a5f78fe9ff2ac153fcd1e3d4;hpb=fa2bd7b968e130b5833bb0bebffda6c14c34de31;p=sven%2Fexfatprogs.git diff --git a/lib/exfat_dir.c b/lib/exfat_dir.c index 98e820f..7b99af1 100644 --- a/lib/exfat_dir.c +++ b/lib/exfat_dir.c @@ -27,6 +27,12 @@ static struct path_resolve_ctx path_resolve_ctx; ##__VA_ARGS__); \ }) +static inline struct buffer_desc *exfat_de_iter_get_buffer( + struct exfat_de_iter *iter, unsigned int block) +{ + return &iter->buffer_desc[block % iter->exfat->buffer_count]; +} + static ssize_t write_block(struct exfat_de_iter *iter, unsigned int block) { off_t device_offset; @@ -34,10 +40,10 @@ static ssize_t write_block(struct exfat_de_iter *iter, unsigned int block) struct buffer_desc *desc; unsigned int i; - desc = &iter->buffer_desc[block & 0x01]; + desc = exfat_de_iter_get_buffer(iter, block); for (i = 0; i < iter->read_size / iter->write_size; i++) { - if (desc->dirty[i]) { + if (BITMAP_GET(desc->dirty, i)) { device_offset = exfat_c2o(exfat, desc->p_clus) + desc->offset; if (exfat_write(exfat->blk_dev->dev_fd, @@ -46,7 +52,7 @@ static ssize_t write_block(struct exfat_de_iter *iter, unsigned int block) device_offset + i * iter->write_size) != (ssize_t)iter->write_size) return -EIO; - desc->dirty[i] = 0; + BITMAP_CLEAR(desc->dirty, i); } } return 0; @@ -169,7 +175,7 @@ static ssize_t read_block(struct exfat_de_iter *iter, unsigned int block) off_t device_offset; ssize_t ret; - desc = &iter->buffer_desc[block & 0x01]; + desc = exfat_de_iter_get_buffer(iter, block); if (block == 0) { desc->p_clus = iter->parent->first_clus; desc->offset = 0; @@ -183,7 +189,7 @@ static ssize_t read_block(struct exfat_de_iter *iter, unsigned int block) if (block > iter->parent->size / iter->read_size) return EOF; - prev_desc = &iter->buffer_desc[(block-1) & 0x01]; + prev_desc = exfat_de_iter_get_buffer(iter, block - 1); if (prev_desc->offset + 2 * iter->read_size <= exfat->clus_size) { desc->p_clus = prev_desc->p_clus; @@ -225,7 +231,7 @@ int exfat_de_iter_init(struct exfat_de_iter *iter, struct exfat *exfat, iter->exfat = exfat; iter->parent = dir; iter->write_size = exfat->sect_size; - iter->read_size = exfat->clus_size <= 4*KB ? exfat->clus_size : 4*KB; + iter->read_size = exfat_get_read_size(exfat); if (exfat->clus_size <= 32 * KB) iter->ra_partial_size = MAX(4 * KB, exfat->clus_size / 2); else @@ -257,6 +263,7 @@ int exfat_de_iter_get(struct exfat_de_iter *iter, off_t next_de_file_offset; ssize_t ret; unsigned int block; + struct buffer_desc *bd; next_de_file_offset = iter->de_file_offset + ith * sizeof(struct exfat_dentry); @@ -265,9 +272,6 @@ int exfat_de_iter_get(struct exfat_de_iter *iter, if (next_de_file_offset + sizeof(struct exfat_dentry) > iter->parent->size) return EOF; - /* the dentry must be in current, or next block which will be read */ - if (block > iter->de_file_offset / iter->read_size + 1) - return -ERANGE; /* read next cluster if needed */ if (next_de_file_offset >= iter->next_read_offset) { @@ -280,8 +284,8 @@ int exfat_de_iter_get(struct exfat_de_iter *iter, if (ith + 1 > iter->max_skip_dentries) iter->max_skip_dentries = ith + 1; - *dentry = (struct exfat_dentry *) - (iter->buffer_desc[block & 0x01].buffer + + bd = exfat_de_iter_get_buffer(iter, block); + *dentry = (struct exfat_dentry *)(bd->buffer + next_de_file_offset % iter->read_size); return 0; } @@ -292,6 +296,7 @@ int exfat_de_iter_get_dirty(struct exfat_de_iter *iter, off_t next_file_offset; unsigned int block; int ret, sect_idx; + struct buffer_desc *bd; ret = exfat_de_iter_get(iter, ith, dentry); if (!ret) { @@ -300,7 +305,8 @@ int exfat_de_iter_get_dirty(struct exfat_de_iter *iter, block = (unsigned int)(next_file_offset / iter->read_size); sect_idx = (int)((next_file_offset % iter->read_size) / iter->write_size); - iter->buffer_desc[block & 0x01].dirty[sect_idx] = 1; + bd = exfat_de_iter_get_buffer(iter, block); + BITMAP_SET(bd->dirty, sect_idx); } return ret; @@ -308,8 +314,11 @@ int exfat_de_iter_get_dirty(struct exfat_de_iter *iter, int exfat_de_iter_flush(struct exfat_de_iter *iter) { - if (write_block(iter, 0) || write_block(iter, 1)) - return -EIO; + unsigned int i; + + for (i = 0; i < iter->exfat->buffer_count; i++) + if (write_block(iter, i)) + return -EIO; return 0; } @@ -333,7 +342,7 @@ off_t exfat_de_iter_device_offset(struct exfat_de_iter *iter) return EOF; block = iter->de_file_offset / iter->read_size; - bd = &iter->buffer_desc[block & 0x01]; + bd = exfat_de_iter_get_buffer(iter, block); return exfat_c2o(iter->exfat, bd->p_clus) + bd->offset + iter->de_file_offset % iter->read_size; } @@ -359,9 +368,12 @@ int exfat_lookup_dentry_set(struct exfat *exfat, struct exfat_inode *parent, int dentry_count, empty_dentry_count = 0; int retval; - bd = exfat_alloc_buffer(2, exfat->clus_size, exfat->sect_size); - if (!bd) - return -ENOMEM; + if (!exfat->lookup_buffer) { + exfat->lookup_buffer = exfat_alloc_buffer(exfat); + if (!exfat->lookup_buffer) + return -ENOMEM; + } + bd = exfat->lookup_buffer; retval = exfat_de_iter_init(&de_iter, exfat, parent, bd); if (retval == EOF || retval) @@ -441,8 +453,6 @@ out: filter->out.file_offset = exfat_de_iter_file_offset(&de_iter); filter->out.dev_offset = EOF; } - if (bd) - exfat_free_buffer(bd, 2); return retval; } @@ -613,7 +623,7 @@ int exfat_build_file_dentry_set(struct exfat *exfat, const char *name, name_len = retval / 2; dcount = 2 + DIV_ROUND_UP(name_len, ENTRY_NAME_MAX); - dset = calloc(1, dcount * DENTRY_SIZE); + dset = calloc(dcount, DENTRY_SIZE); if (!dset) return -ENOMEM; @@ -841,9 +851,8 @@ static int exfat_alloc_cluster(struct exfat *exfat, struct exfat_inode *inode, return -EIO; /* zero out the new cluster */ - if (exfat_write(exfat->blk_dev->dev_fd, exfat->zero_cluster, - exfat->clus_size, exfat_c2o(exfat, *new_clu)) != - (ssize_t)exfat->clus_size) { + if (exfat_write_zero(exfat->blk_dev->dev_fd, exfat->clus_size, + exfat_c2o(exfat, *new_clu))) { exfat_err("failed to fill new cluster with zeroes\n"); return -EIO; }