1 /* This file contains directory entry management and the name lookup hashtable.
3 * The entry points into this file are:
4 * init_dentry initialize the directory entry name lookup hashtable
5 * lookup_dentry find an inode based on parent directory and name
6 * add_dentry add an inode as directory entry to a parent directory
7 * del_dentry delete an inode from its parent directory
10 * April 2009 (D.C. van Moolenbroek)
15 PRIVATE
LIST_HEAD(hash_head
, inode
) hash_table
[NUM_HASH_SLOTS
];
17 FORWARD
_PROTOTYPE( void del_one_dentry
, (struct inode
*ino
) );
18 FORWARD
_PROTOTYPE( unsigned int hash_dentry
, (struct inode
*parent
,
21 /*===========================================================================*
23 *===========================================================================*/
24 PUBLIC
void init_dentry()
26 /* Initialize the names hashtable.
30 for (i
= 0; i
< NUM_HASH_SLOTS
; i
++)
31 LIST_INIT(&hash_table
[i
]);
34 /*===========================================================================*
36 *===========================================================================*/
37 PUBLIC
struct inode
*lookup_dentry(parent
, name
)
41 /* Given a directory inode and a component name, look up the inode associated
42 * with that directory entry. Return the inode (with increased reference
43 * count) if found, or NULL otherwise.
48 assert(IS_DIR(parent
));
50 slot
= hash_dentry(parent
, name
);
52 LIST_FOREACH(ino
, &hash_table
[slot
], i_hash
) {
53 if (compare_name(ino
->i_name
, name
) == TRUE
)
65 /*===========================================================================*
67 *===========================================================================*/
68 PUBLIC
void add_dentry(parent
, name
, ino
)
73 /* Add an entry to a parent inode, in the form of a new inode, with the given
74 * name. An entry with this name must not already exist.
78 assert(IS_DIR(parent
));
79 assert(parent
->i_ref
> 0);
80 assert(ino
->i_ref
> 0);
82 assert(strlen(name
) <= NAME_MAX
);
84 link_inode(parent
, ino
);
86 strcpy(ino
->i_name
, name
);
89 slot
= hash_dentry(parent
, ino
->i_name
);
90 LIST_INSERT_HEAD(&hash_table
[slot
], ino
, i_hash
);
93 /*===========================================================================*
95 *===========================================================================*/
96 PRIVATE
void del_one_dentry(ino
)
99 /* This inode has become inaccessible by name. Disassociate it from its parent
100 * and remove it from the names hash table.
103 /* There can and must be exactly one root inode, so don't delete it! */
107 /* INUSE -> DELETED, CACHED -> FREE */
109 /* Remove the entry from the hashtable.
110 * Decrease parent's refcount, possibly adding it to the free list.
111 * Do not touch open handles. Do not add to the free list.
114 assert(ino
->i_parent
!= NULL
);
117 LIST_REMOVE(ino
, i_hash
);
124 /*===========================================================================*
126 *===========================================================================*/
127 PUBLIC
void del_dentry(ino
)
130 /* Disassociate an inode from its parent, effectively deleting it. Recursively
131 * delete all its children as well, fragmenting the deleted branch into single
134 LIST_HEAD(work_list
, inode
) work_list
;
139 /* Quick way out: one directory entry that itself has no children. */
140 if (!HAS_CHILDREN(ino
))
143 /* Recursively delete all children of the inode as well.
144 * Iterative version: this is potentially 128 levels deep.
147 LIST_INIT(&work_list
);
148 LIST_INSERT_HEAD(&work_list
, ino
, i_next
);
151 ino
= LIST_FIRST(&work_list
);
152 LIST_REMOVE(ino
, i_next
);
156 while (!LIST_EMPTY(&ino
->i_child
)) {
157 child
= LIST_FIRST(&ino
->i_child
);
158 LIST_REMOVE(child
, i_next
);
160 del_one_dentry(child
);
162 if (HAS_CHILDREN(child
))
163 LIST_INSERT_HEAD(&work_list
, child
, i_next
);
165 } while (!LIST_EMPTY(&work_list
));
168 /*===========================================================================*
170 *===========================================================================*/
171 PRIVATE
unsigned int hash_dentry(parent
, name
)
172 struct inode
*parent
;
175 /* Generate a hash value for a given name. Normalize the name first, so that
176 * different variations of the name will result in the same hash value.
179 char buf
[NAME_MAX
+1], *p
;
181 dprintf(("HGFS: hash_dentry for '%s'\n", name
));
183 normalize_name(buf
, name
);
185 /* djb2 string hash algorithm, XOR variant */
187 for (p
= buf
; *p
; p
++)
188 val
= ((val
<< 5) + val
) ^ *p
;
190 /* Mix with inode number: typically, many file names occur in several
191 * different directories.
193 return (val
^ parent
->i_num
) % NUM_HASH_SLOTS
;