statfs() and free inode calculation is O(1) (David Fox, Szabolcs Szakacsits)
parent
8796b5ee89
commit
ffa355c0f8
|
@ -214,6 +214,7 @@ struct _ntfs_volume {
|
|||
|
||||
s64 free_clusters; /* Track the number of free clusters which
|
||||
greatly improves statfs() performance */
|
||||
s64 free_mft_records; /* Same for free mft records (see above) */
|
||||
|
||||
/* Temp: for directory handling */
|
||||
void *private_data; /* ntfs_dir for . */
|
||||
|
|
|
@ -797,6 +797,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
|
|||
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
|
||||
if (ll == 8) {
|
||||
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
|
||||
vol->free_mft_records += (8 * 8);
|
||||
return 0;
|
||||
}
|
||||
ntfs_log_error("Failed to write to mft bitmap.\n");
|
||||
|
@ -1440,6 +1441,7 @@ found_free_rec:
|
|||
/* Return the opened, allocated inode of the allocated mft record. */
|
||||
ntfs_log_debug("Returning opened, allocated %sinode 0x%llx.\n",
|
||||
base_ni ? "extent " : "", (long long)bit);
|
||||
vol->free_mft_records--;
|
||||
return ni;
|
||||
|
||||
undo_mftbmp_alloc:
|
||||
|
@ -1508,8 +1510,10 @@ int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni)
|
|||
}
|
||||
|
||||
/* Throw away the now freed inode. */
|
||||
if (!ntfs_inode_close(ni))
|
||||
if (!ntfs_inode_close(ni)) {
|
||||
vol->free_mft_records++;
|
||||
return 0;
|
||||
}
|
||||
err = errno;
|
||||
|
||||
/* Rollback what we did... */
|
||||
|
|
|
@ -105,8 +105,6 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
ntfs_volume *vol;
|
||||
int state;
|
||||
long free_mft;
|
||||
unsigned int uid;
|
||||
unsigned int gid;
|
||||
unsigned int fmask;
|
||||
|
@ -121,11 +119,6 @@ typedef struct {
|
|||
BOOL no_detach;
|
||||
} ntfs_fuse_context_t;
|
||||
|
||||
typedef enum {
|
||||
NF_FreeMFTOutdate = (1 << 1), /* Information about amount of
|
||||
free MFT records is outdated. */
|
||||
} ntfs_fuse_state_bits;
|
||||
|
||||
static struct options {
|
||||
char *mnt_point; /* Mount point */
|
||||
char *options; /* Mount options */
|
||||
|
@ -162,11 +155,6 @@ static const char *usage_msg =
|
|||
"\n"
|
||||
"%s";
|
||||
|
||||
static __inline__ void ntfs_fuse_mark_free_space_outdated(void)
|
||||
{
|
||||
/* Mark information about free MFT records outdated. */
|
||||
ctx->state |= NF_FreeMFTOutdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_fuse_is_named_data_stream - check path to be to named data stream
|
||||
|
@ -181,14 +169,12 @@ static __inline__ int ntfs_fuse_is_named_data_stream(const char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long ntfs_fuse_get_nr_free_mft_records(ntfs_volume *vol, s64 numof_inode)
|
||||
static long ntfs_get_nr_free_mft_records(ntfs_volume *vol)
|
||||
{
|
||||
u8 *buf;
|
||||
long nr_free = 0;
|
||||
s64 br, total = 0;
|
||||
|
||||
if (!(ctx->state & NF_FreeMFTOutdate))
|
||||
return ctx->free_mft;
|
||||
buf = ntfs_malloc(vol->cluster_size);
|
||||
if (!buf)
|
||||
return -errno;
|
||||
|
@ -201,20 +187,15 @@ static long ntfs_fuse_get_nr_free_mft_records(ntfs_volume *vol, s64 numof_inode)
|
|||
break;
|
||||
total += br;
|
||||
for (i = 0; i < br; i++)
|
||||
for (j = 0; j < 8; j++) {
|
||||
|
||||
if (--numof_inode < 0)
|
||||
break;
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
if (!((buf[i] >> j) & 1))
|
||||
nr_free++;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
if (!total || br < 0)
|
||||
return -errno;
|
||||
ctx->free_mft = nr_free;
|
||||
ctx->state &= ~(NF_FreeMFTOutdate);
|
||||
|
||||
nr_free += (vol->mftbmp_na->allocated_size - vol->mftbmp_na->data_size) << 3;
|
||||
return nr_free;
|
||||
}
|
||||
|
||||
|
@ -266,8 +247,8 @@ static long ntfs_get_nr_free_clusters(ntfs_volume *vol)
|
|||
static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
|
||||
struct statvfs *sfs)
|
||||
{
|
||||
long size, delta_bits;
|
||||
u64 allocated_inodes;
|
||||
s64 size;
|
||||
int delta_bits;
|
||||
ntfs_volume *vol;
|
||||
|
||||
vol = ctx->vol;
|
||||
|
@ -300,11 +281,10 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
|
|||
size >>= -delta_bits;
|
||||
|
||||
/* Number of inodes in file system (at this point in time). */
|
||||
allocated_inodes = vol->mft_na->data_size >> vol->mft_record_size_bits;
|
||||
sfs->f_files = allocated_inodes + size;
|
||||
sfs->f_files = (vol->mftbmp_na->allocated_size << 3) + size;
|
||||
|
||||
/* Free inodes in fs (based on current total count). */
|
||||
size = ntfs_fuse_get_nr_free_mft_records(vol, allocated_inodes) + size;
|
||||
size += vol->free_mft_records;
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
sfs->f_ffree = size;
|
||||
|
@ -747,7 +727,6 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,
|
|||
}
|
||||
res = total;
|
||||
exit:
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
if (ni && ntfs_inode_close(ni))
|
||||
|
@ -784,7 +763,6 @@ static int ntfs_fuse_truncate(const char *org_path, off_t size)
|
|||
if (ntfs_attr_truncate(na, size))
|
||||
goto exit;
|
||||
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
ntfs_attr_close(na);
|
||||
errno = 0;
|
||||
exit:
|
||||
|
@ -926,7 +904,6 @@ static int ntfs_fuse_create_file(const char *org_path, mode_t mode,
|
|||
else
|
||||
res = ntfs_fuse_create_stream(path, stream_name,
|
||||
stream_name_len);
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
free(path);
|
||||
if (stream_name_len)
|
||||
free(stream_name);
|
||||
|
@ -952,7 +929,6 @@ static int ntfs_fuse_mknod(const char *org_path, mode_t mode, dev_t dev)
|
|||
else
|
||||
res = ntfs_fuse_create_stream(path, stream_name,
|
||||
stream_name_len);
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
exit:
|
||||
free(path);
|
||||
if (stream_name_len)
|
||||
|
@ -964,7 +940,6 @@ static int ntfs_fuse_symlink(const char *to, const char *from)
|
|||
{
|
||||
if (ntfs_fuse_is_named_data_stream(from))
|
||||
return -EINVAL; /* n/a for named data streams. */
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
return ntfs_fuse_create(from, S_IFLNK, 0, to);
|
||||
}
|
||||
|
||||
|
@ -1014,7 +989,6 @@ static int ntfs_fuse_ln(const char *old_path, const char *new_path, int mtime)
|
|||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
/* Create hard link. */
|
||||
if (ntfs_link(ni, dir_ni, uname, uname_len))
|
||||
res = -errno;
|
||||
|
@ -1115,7 +1089,6 @@ static int ntfs_fuse_unlink(const char *org_path)
|
|||
res = ntfs_fuse_rm(path);
|
||||
else
|
||||
res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len);
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
free(path);
|
||||
if (stream_name_len)
|
||||
free(stream_name);
|
||||
|
@ -1239,7 +1212,6 @@ static int ntfs_fuse_mkdir(const char *path,
|
|||
{
|
||||
if (ntfs_fuse_is_named_data_stream(path))
|
||||
return -EINVAL; /* n/a for named data streams. */
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
return ntfs_fuse_create(path, S_IFDIR, 0, NULL);
|
||||
}
|
||||
|
||||
|
@ -1247,7 +1219,6 @@ static int ntfs_fuse_rmdir(const char *path)
|
|||
{
|
||||
if (ntfs_fuse_is_named_data_stream(path))
|
||||
return -EINVAL; /* n/a for named data streams. */
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
return ntfs_fuse_rm(path);
|
||||
}
|
||||
|
||||
|
@ -1543,7 +1514,6 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
|||
res = -EEXIST;
|
||||
goto exit;
|
||||
}
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
if (!na) {
|
||||
if (flags == XATTR_REPLACE) {
|
||||
res = -ENODATA;
|
||||
|
@ -1603,7 +1573,6 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
|
|||
res = -errno;
|
||||
}
|
||||
|
||||
ntfs_fuse_mark_free_space_outdated();
|
||||
exit:
|
||||
free(lename);
|
||||
if (ntfs_inode_close(ni))
|
||||
|
@ -1672,7 +1641,6 @@ static int ntfs_fuse_init(void)
|
|||
return -1;
|
||||
|
||||
*ctx = (ntfs_fuse_context_t) {
|
||||
.state = NF_FreeMFTOutdate,
|
||||
.uid = getuid(),
|
||||
.gid = getgid(),
|
||||
.fmask = 0,
|
||||
|
@ -2253,6 +2221,12 @@ int main(int argc, char *argv[])
|
|||
ntfs_log_perror("Failed to read NTFS $Bitmap");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ctx->vol->free_mft_records = ntfs_get_nr_free_mft_records(ctx->vol);
|
||||
if (ctx->vol->free_mft_records < 0) {
|
||||
ntfs_log_perror("Failed to calculate free MFT records");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (use_blkdev) {
|
||||
set_fuseblk_options(parsed_options);
|
||||
|
|
Loading…
Reference in New Issue