summaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c101
1 files changed, 49 insertions, 52 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 3caf950eb..1b3ff98b2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -337,25 +337,27 @@ repeat:
}
}
+/*
+ * Search for at least 1 mount point in the dentry's subdirs.
+ * We descend to the next level whenever the d_subdirs
+ * list is non-empty and continue searching.
+ */
+
/**
- * is_root_busy - check if a root dentry could be freed
- * @root: Dentry to work down from
- *
- * Check whether a root dentry would be in use if all of its
- * child dentries were freed. This allows a non-destructive
- * test for unmounting a device.
+ * have_submounts - check for mounts over a dentry
+ * @parent: dentry to check.
*
- * Return non zero if the root is still busy.
+ * Return true if the parent or its subdirectories contain
+ * a mount point
*/
-int is_root_busy(struct dentry *root)
+int have_submounts(struct dentry *parent)
{
- struct dentry *this_parent = root;
+ struct dentry *this_parent = parent;
struct list_head *next;
- int count = root->d_count;
-
- check_lock();
+ if (d_mountpoint(parent))
+ return 1;
repeat:
next = this_parent->d_subdirs.next;
resume:
@@ -363,48 +365,31 @@ resume:
struct list_head *tmp = next;
struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
next = tmp->next;
- /* Decrement count for unused children */
- count += (dentry->d_count - 1);
+ /* Have we found a mount point ? */
+ if (d_mountpoint(dentry))
+ return 1;
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
goto repeat;
}
- /* root is busy if any leaf is busy */
- if (dentry->d_count)
- return 1;
}
/*
* All done at this level ... ascend and resume the search.
*/
- if (this_parent != root) {
+ if (this_parent != parent) {
next = this_parent->d_child.next;
this_parent = this_parent->d_parent;
goto resume;
}
- return (count > 1); /* remaining users? */
+ return 0; /* No mount points found in tree */
}
-/*
- * Search for at least 1 mount point in the dentry's subdirs.
- * We descend to the next level whenever the d_subdirs
- * list is non-empty and continue searching.
- */
-
-/**
- * have_submounts - check for mounts over a dentry
- * @parent: dentry to check.
- *
- * Return true if the parent or its subdirectories contain
- * a mount point
- */
-
-int have_submounts(struct dentry *parent)
+int d_active_refs(struct dentry *root)
{
- struct dentry *this_parent = parent;
+ struct dentry *this_parent = root;
struct list_head *next;
+ int count = root->d_count;
- if (d_mountpoint(parent))
- return 1;
repeat:
next = this_parent->d_subdirs.next;
resume:
@@ -412,9 +397,8 @@ resume:
struct list_head *tmp = next;
struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
next = tmp->next;
- /* Have we found a mount point ? */
- if (d_mountpoint(dentry))
- return 1;
+ /* Decrement count for unused children */
+ count += (dentry->d_count - 1);
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
goto repeat;
@@ -423,12 +407,12 @@ resume:
/*
* All done at this level ... ascend and resume the search.
*/
- if (this_parent != parent) {
+ if (this_parent != root) {
next = this_parent->d_child.next;
this_parent = this_parent->d_parent;
goto resume;
}
- return 0; /* No mount points found in tree */
+ return count;
}
/*
@@ -511,7 +495,7 @@ void shrink_dcache_parent(struct dentry * parent)
* ...
* 6 - base-level: try to shrink a bit.
*/
-int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone)
+int shrink_dcache_memory(int priority, unsigned int gfp_mask)
{
int count = 0;
lock_kernel();
@@ -574,8 +558,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
} else
INIT_LIST_HEAD(&dentry->d_child);
- dentry->d_mounts = dentry;
- dentry->d_covers = dentry;
+ INIT_LIST_HEAD(&dentry->d_vfsmnt);
INIT_LIST_HEAD(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
@@ -895,6 +878,7 @@ char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
{
char * end = buffer+buflen;
char * retval;
+ int namelen;
*--end = '\0';
buflen--;
@@ -910,14 +894,18 @@ char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
for (;;) {
struct dentry * parent;
- int namelen;
- if (dentry == root)
+ if (dentry == root && vfsmnt == rootmnt)
break;
- dentry = dentry->d_covers;
+ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+ /* Global root? */
+ if (vfsmnt->mnt_parent == vfsmnt)
+ goto global_root;
+ dentry = vfsmnt->mnt_mountpoint;
+ vfsmnt = vfsmnt->mnt_parent;
+ continue;
+ }
parent = dentry->d_parent;
- if (dentry == parent)
- break;
namelen = dentry->d_name.len;
buflen -= namelen + 1;
if (buflen < 0)
@@ -929,6 +917,14 @@ char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
dentry = parent;
}
return retval;
+global_root:
+ namelen = dentry->d_name.len;
+ buflen -= namelen;
+ if (buflen >= 0) {
+ end -= namelen;
+ memcpy(end, dentry->d_name.name, namelen);
+ }
+ return end;
}
/*
@@ -1100,11 +1096,12 @@ void __init dcache_init(unsigned long mempages)
__get_free_pages(GFP_ATOMIC, order);
} while (dentry_hashtable == NULL && --order >= 0);
+ printk("Dentry-cache hash table entries: %d (order: %ld, %ld bytes)\n",
+ nr_hash, order, (PAGE_SIZE << order));
+
if (!dentry_hashtable)
panic("Failed to allocate dcache hash table\n");
- printk("VFS: DCACHE hash table configured to %d entries\n", nr_hash);
-
d = dentry_hashtable;
i = nr_hash;
do {