mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Cached looked-up inodes for subsequent use
This commit is contained in:
parent
d75f69d80e
commit
6072a95591
@ -61,6 +61,9 @@ extern ntfschar NTFS_INDEX_R[3];
|
||||
|
||||
extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
|
||||
const ntfschar *uname, const int uname_len);
|
||||
extern u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name);
|
||||
extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name,
|
||||
u64 inum);
|
||||
|
||||
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
||||
const char *pathname);
|
||||
|
@ -24,10 +24,13 @@
|
||||
|
||||
#define CACHE_INODE_SIZE 32 /* inode cache, zero or >= 3 and not too big */
|
||||
#define CACHE_NIDATA_SIZE 64 /* idata cache, zero or >= 3 and not too big */
|
||||
#define CACHE_LOOKUP_SIZE 64 /* lookup cache, zero or >= 3 and not too big */
|
||||
#define CACHE_SECURID_SIZE 16 /* securid cache, zero or >= 3 and not too big */
|
||||
#define CACHE_LEGACY_SIZE 8 /* legacy cache size, zero or >= 3 and not too big */
|
||||
|
||||
#define FORCE_FORMAT_v1x 0 /* Insert security data as in NTFS v1.x */
|
||||
#define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */
|
||||
|
||||
#define FULLCOLLATE 1
|
||||
|
||||
#endif /* defined _NTFS_PARAM_H */
|
||||
|
@ -235,6 +235,9 @@ struct _ntfs_volume {
|
||||
#if CACHE_NIDATA_SIZE
|
||||
struct CACHE_HEADER *nidata_cache;
|
||||
#endif
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
struct CACHE_HEADER *lookup_cache;
|
||||
#endif
|
||||
#if CACHE_SECURID_SIZE
|
||||
struct CACHE_HEADER *securid_cache;
|
||||
#endif
|
||||
|
@ -571,6 +571,13 @@ void ntfs_create_lru_caches(ntfs_volume *vol)
|
||||
ntfs_inode_nidata_free, ntfs_inode_nidata_hash,
|
||||
sizeof(struct CACHED_NIDATA),
|
||||
CACHE_NIDATA_SIZE, 2*CACHE_NIDATA_SIZE);
|
||||
#endif
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
/* lookup cache */
|
||||
vol->lookup_cache = ntfs_create_cache("lookup",
|
||||
(cache_free)NULL, ntfs_dir_lookup_hash,
|
||||
sizeof(struct CACHED_LOOKUP),
|
||||
CACHE_LOOKUP_SIZE, 2*CACHE_LOOKUP_SIZE);
|
||||
#endif
|
||||
vol->securid_cache = ntfs_create_cache("securid",(cache_free)NULL,
|
||||
(cache_hash)NULL,sizeof(struct CACHED_SECURID), CACHE_SECURID_SIZE, 0);
|
||||
@ -591,6 +598,9 @@ void ntfs_free_lru_caches(ntfs_volume *vol)
|
||||
#endif
|
||||
#if CACHE_NIDATA_SIZE
|
||||
ntfs_free_cache(vol->nidata_cache);
|
||||
#endif
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
ntfs_free_cache(vol->lookup_cache);
|
||||
#endif
|
||||
ntfs_free_cache(vol->securid_cache);
|
||||
#if CACHE_LEGACY_SIZE
|
||||
|
163
libntfs-3g/dir.c
163
libntfs-3g/dir.c
@ -158,6 +158,65 @@ static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
|
||||
|
||||
#endif
|
||||
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
|
||||
/*
|
||||
* File name comparing for entering/fetching from lookup cache
|
||||
*/
|
||||
|
||||
static int lookup_cache_compare(const struct CACHED_GENERIC *cached,
|
||||
const struct CACHED_GENERIC *wanted)
|
||||
{
|
||||
const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
|
||||
const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
|
||||
return (!c->name
|
||||
|| (c->parent != w->parent)
|
||||
|| (c->namesize != w->namesize)
|
||||
|| memcmp(c->name, w->name, c->namesize));
|
||||
}
|
||||
|
||||
/*
|
||||
* Inode number comparing for invalidating lookup cache
|
||||
*
|
||||
* All entries with designated inode number are invalidated
|
||||
*
|
||||
* Only use associated with a CACHE_NOHASH flag
|
||||
*/
|
||||
|
||||
static int lookup_cache_inv_compare(const struct CACHED_GENERIC *cached,
|
||||
const struct CACHED_GENERIC *wanted)
|
||||
{
|
||||
const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
|
||||
const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
|
||||
return (!c->name
|
||||
|| (c->parent != w->parent)
|
||||
|| (MREF(c->inum) != MREF(w->inum)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup hashing
|
||||
*
|
||||
* Based on first, second and and last char
|
||||
*/
|
||||
|
||||
int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached)
|
||||
{
|
||||
const unsigned char *name;
|
||||
int count;
|
||||
unsigned int val;
|
||||
|
||||
name = (const unsigned char*)cached->variable;
|
||||
count = cached->varsize;
|
||||
if (!name || !count) {
|
||||
ntfs_log_error("Bad lookup cache entry\n");
|
||||
return (-1);
|
||||
}
|
||||
val = (name[0] << 2) + (name[1] << 1) + name[count - 1] + count;
|
||||
return (val % (2*CACHE_LOOKUP_SIZE));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ntfs_inode_lookup_by_name - find an inode in a directory given its name
|
||||
* @dir_ni: ntfs inode of the directory in which to search for the name
|
||||
@ -183,8 +242,8 @@ static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
|
||||
* If the volume is mounted with the case sensitive flag set, then we only
|
||||
* allow exact matches.
|
||||
*/
|
||||
u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
const int uname_len)
|
||||
u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
|
||||
const ntfschar *uname, const int uname_len)
|
||||
{
|
||||
VCN vcn;
|
||||
u64 mref = 0;
|
||||
@ -472,6 +531,94 @@ close_err_out:
|
||||
goto eo_put_err_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup a file in a directory from its UTF-8 name
|
||||
*
|
||||
* The name is first fetched from cache if one is defined
|
||||
*
|
||||
* Returns the inode number
|
||||
* or -1 if not possible (errno tells why)
|
||||
*/
|
||||
|
||||
u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name)
|
||||
{
|
||||
int uname_len;
|
||||
ntfschar *uname = (ntfschar*)NULL;
|
||||
u64 inum;
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
struct CACHED_LOOKUP item;
|
||||
struct CACHED_LOOKUP *cached;
|
||||
|
||||
/*
|
||||
* fetch inode from cache
|
||||
*/
|
||||
|
||||
if (dir_ni->vol->lookup_cache) {
|
||||
item.name = name;
|
||||
item.namesize = strlen(name) + 1;
|
||||
item.parent = dir_ni->mft_no;
|
||||
cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache(
|
||||
dir_ni->vol->lookup_cache, GENERIC(&item),
|
||||
lookup_cache_compare);
|
||||
if (cached) {
|
||||
inum = cached->inum;
|
||||
if (inum == (u64)-1)
|
||||
errno = ENOENT;
|
||||
} else {
|
||||
/* Generate unicode name. */
|
||||
uname_len = ntfs_mbstoucs(name, &uname);
|
||||
if (uname_len >= 0) {
|
||||
inum = ntfs_inode_lookup_by_name(dir_ni,
|
||||
uname, uname_len);
|
||||
item.inum = inum;
|
||||
/* enter into cache, even if not found */
|
||||
ntfs_enter_cache(dir_ni->vol->lookup_cache,
|
||||
GENERIC(&item),
|
||||
lookup_cache_compare);
|
||||
free(uname);
|
||||
} else
|
||||
inum = (s64)-1;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Generate unicode name. */
|
||||
uname_len = ntfs_mbstoucs(name, &uname);
|
||||
if (uname_len >= 0)
|
||||
inum = ntfs_inode_lookup_by_name(dir_ni,
|
||||
uname, uname_len);
|
||||
else
|
||||
inum = (s64)-1;
|
||||
}
|
||||
return (inum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update a cache lookup record when a name has been defined
|
||||
*
|
||||
* The UTF-8 name is required
|
||||
*/
|
||||
|
||||
void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, u64 inum)
|
||||
{
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
struct CACHED_LOOKUP item;
|
||||
struct CACHED_LOOKUP *cached;
|
||||
|
||||
if (dir_ni->vol->lookup_cache) {
|
||||
item.name = name;
|
||||
item.namesize = strlen(name) + 1;
|
||||
item.parent = dir_ni->mft_no;
|
||||
item.inum = inum;
|
||||
cached = (struct CACHED_LOOKUP*)ntfs_enter_cache(
|
||||
dir_ni->vol->lookup_cache,
|
||||
GENERIC(&item), lookup_cache_compare);
|
||||
if (cached)
|
||||
cached->inum = inum;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_pathname_to_inode - Find the inode which represents the given pathname
|
||||
* @vol: An ntfs volume obtained from ntfs_mount
|
||||
@ -1557,6 +1704,9 @@ int ntfs_delete(ntfs_volume *vol, const char *pathname,
|
||||
u64 inum = (u64)-1;
|
||||
int count;
|
||||
#endif
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
struct CACHED_LOOKUP lkitem;
|
||||
#endif
|
||||
|
||||
ntfs_log_trace("Entering.\n");
|
||||
|
||||
@ -1670,6 +1820,15 @@ search:
|
||||
* case there are no reference to this inode left, so we should free all
|
||||
* non-resident attributes and mark all MFT record as not in use.
|
||||
*/
|
||||
#if CACHE_LOOKUP_SIZE
|
||||
/* invalidate entry in lookup cache */
|
||||
lkitem.name = (const char*)NULL;
|
||||
lkitem.namesize = 0;
|
||||
lkitem.inum = ni->mft_no;
|
||||
lkitem.parent = dir_ni->mft_no;
|
||||
ntfs_invalidate_cache(vol->lookup_cache, GENERIC(&lkitem),
|
||||
lookup_cache_inv_compare, CACHE_NOHASH);
|
||||
#endif
|
||||
#if CACHE_INODE_SIZE
|
||||
inum = ni->mft_no;
|
||||
if (pathname) {
|
||||
|
Loading…
Reference in New Issue
Block a user