diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
commit | ba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch) | |
tree | 78670a0139bf4d5ace617b29b7eba82bbc74d602 /fs/dcache.c | |
parent | b77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff) |
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 101 |
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 { |