libntfs: Cache opened attributes.

edge.strict_endians
Yura Pakhuchiy 2007-09-20 15:35:02 +03:00
parent 038fea1b5b
commit 673c23d74a
4 changed files with 39 additions and 1 deletions

View File

@ -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;
};
/**

View File

@ -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);

View File

@ -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)

View File

@ -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)) {