libntfs: Cache opened attributes.
parent
038fea1b5b
commit
673c23d74a
|
@ -27,6 +27,7 @@
|
|||
typedef struct _ntfs_attr ntfs_attr;
|
||||
typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
|
||||
|
||||
#include "list.h"
|
||||
#include "types.h"
|
||||
#include "inode.h"
|
||||
#include "unistr.h"
|
||||
|
@ -195,6 +196,8 @@ struct _ntfs_attr {
|
|||
u8 compression_block_size_bits;
|
||||
u8 compression_block_clusters;
|
||||
ntfs_crypto_attr *crypto;
|
||||
struct list_head list_entry;
|
||||
int nr_references;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -161,6 +161,8 @@ struct _ntfs_inode {
|
|||
int nr_references; /* How many times this inode was
|
||||
opened. We really close inode only
|
||||
when this reaches zero. */
|
||||
|
||||
struct list_head attr_cache; /* List of opened attributes. */
|
||||
};
|
||||
|
||||
extern void __ntfs_inode_add_to_cache(ntfs_inode *ni);
|
||||
|
|
|
@ -354,6 +354,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_attr *na;
|
||||
ATTR_RECORD *a;
|
||||
struct list_head *pos;
|
||||
int err;
|
||||
BOOL cs;
|
||||
|
||||
|
@ -363,6 +364,21 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
/* Check cache, maybe this attribute already opened? */
|
||||
list_for_each(pos, &ni->attr_cache) {
|
||||
ntfs_attr *tmp_na;
|
||||
|
||||
tmp_na = list_entry(pos, ntfs_attr, list_entry);
|
||||
if (tmp_na->type == type && tmp_na->name_len == name_len &&
|
||||
!ntfs_ucsncmp(tmp_na->name, name, name_len)) {
|
||||
ntfs_log_trace("Found this attribute in cache, "
|
||||
"increment reference count and "
|
||||
"return it.\n");
|
||||
tmp_na->nr_references++;
|
||||
return tmp_na;
|
||||
}
|
||||
}
|
||||
/* Search failed. Properly open attrbute. */
|
||||
na = calloc(sizeof(ntfs_attr), 1);
|
||||
if (!na)
|
||||
return NULL;
|
||||
|
@ -429,6 +445,8 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
ntfs_attr_put_search_ctx(ctx);
|
||||
if (NAttrEncrypted(na))
|
||||
ntfs_crypto_attr_open(na);
|
||||
list_add_tail(&na->list_entry, &ni->attr_cache);
|
||||
na->nr_references = 1;
|
||||
return na;
|
||||
put_err_out:
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
|
@ -449,6 +467,14 @@ void ntfs_attr_close(ntfs_attr *na)
|
|||
{
|
||||
if (!na)
|
||||
return;
|
||||
na->nr_references--;
|
||||
if (na->nr_references) {
|
||||
ntfs_log_trace("There are %d more references left to "
|
||||
"this attribute.\n", na->nr_references);
|
||||
return;
|
||||
}
|
||||
ntfs_log_trace("There are no more references left to this attribute\n");
|
||||
list_del(&na->list_entry);
|
||||
if (NAttrEncrypted(na))
|
||||
ntfs_crypto_attr_close(na);
|
||||
if (NAttrNonResident(na) && na->rl)
|
||||
|
|
|
@ -62,8 +62,10 @@ static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol)
|
|||
ntfs_inode *ni;
|
||||
|
||||
ni = (ntfs_inode*)calloc(1, sizeof(ntfs_inode));
|
||||
if (ni)
|
||||
if (ni) {
|
||||
ni->vol = vol;
|
||||
INIT_LIST_HEAD(&ni->attr_cache);
|
||||
}
|
||||
return ni;
|
||||
}
|
||||
|
||||
|
@ -292,6 +294,11 @@ int ntfs_inode_close(ntfs_inode *ni)
|
|||
ntfs_log_trace("There are no more references left to "
|
||||
"this inode.\n");
|
||||
}
|
||||
/* Check whether all attributes of this inode are closed. */
|
||||
if (!list_empty(&ni->attr_cache))
|
||||
ntfs_log_error("%s(): Not all attributes are closed. "
|
||||
"We definitely have memory leak. "
|
||||
"Continue anyway.\n", __FUNCTION__);
|
||||
/* If we have dirty metadata, write it out. */
|
||||
if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
|
||||
if (ntfs_inode_sync(ni)) {
|
||||
|
|
Loading…
Reference in New Issue