summaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
commitd3e71cb08747743fce908122bab08b479eb403a5 (patch)
treecbec6948fdbdee9af81cf3ecfb504070d2745d7b /fs/dcache.c
parentfe7ff1706e323d0e5ed83972960a1ecc1ee538b3 (diff)
Merge with Linux 2.3.99-pre3.
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index dc424305f..d4aef49e7 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -27,6 +27,9 @@
#define DCACHE_PARANOIA 1
/* #define DCACHE_DEBUG 1 */
+/* Right now the dcache depends on the kernel lock */
+#define check_lock() if (!kernel_locked()) BUG()
+
/* For managing the dcache */
extern unsigned long num_physpages, page_cache_size;
extern int inodes_stat[];
@@ -104,6 +107,8 @@ void dput(struct dentry *dentry)
{
int count;
+ check_lock();
+
if (!dentry)
return;
@@ -158,7 +163,7 @@ out:
count,
dentry->d_parent->d_name.name,
dentry->d_name.name);
- *(int *)0 = 0;
+ BUG();
}
/*
@@ -168,6 +173,8 @@ out:
*/
int d_invalidate(struct dentry * dentry)
{
+ check_lock();
+
/*
* If it's already been dropped, return OK.
*/
@@ -226,6 +233,7 @@ static inline void prune_one_dentry(struct dentry * dentry)
*/
void prune_dcache(int count)
{
+ check_lock();
for (;;) {
struct dentry *dentry;
struct list_head *tmp = dentry_unused.prev;
@@ -261,6 +269,8 @@ void shrink_dcache_sb(struct super_block * sb)
struct list_head *tmp, *next;
struct dentry *dentry;
+ check_lock();
+
/*
* Pass one ... move the dentries for the specified
* superblock to the most recent end of the unused list.
@@ -308,6 +318,8 @@ int is_root_busy(struct dentry *root)
struct list_head *next;
int count = root->d_count;
+ check_lock();
+
repeat:
next = this_parent->d_subdirs.next;
resume:
@@ -337,6 +349,44 @@ resume:
}
/*
+ * 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.
+ */
+int have_submounts(struct dentry *parent)
+{
+ struct dentry *this_parent = parent;
+ struct list_head *next;
+
+ if (parent->d_mounts != parent)
+ return 1;
+repeat:
+ next = this_parent->d_subdirs.next;
+resume:
+ while (next != &this_parent->d_subdirs) {
+ 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 (dentry->d_mounts != dentry)
+ return 1;
+ if (!list_empty(&dentry->d_subdirs)) {
+ this_parent = dentry;
+ goto repeat;
+ }
+ }
+ /*
+ * All done at this level ... ascend and resume the search.
+ */
+ if (this_parent != parent) {
+ next = this_parent->d_child.next;
+ this_parent = this_parent->d_parent;
+ goto resume;
+ }
+ return 0; /* No mount points found in tree */
+}
+
+/*
* Search the dentry child list for the specified parent,
* and move any unused dentries to the end of the unused
* list for prune_dcache(). We descend to the next level
@@ -349,6 +399,8 @@ static int select_parent(struct dentry * parent)
struct list_head *next;
int found = 0;
+ check_lock();
+
repeat:
next = this_parent->d_subdirs.next;
resume:
@@ -525,6 +577,8 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
struct list_head *head = d_hash(parent,hash);
struct list_head *tmp = head->next;
+ check_lock();
+
for (;;) {
struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);
if (tmp == head)
@@ -564,6 +618,8 @@ int d_validate(struct dentry *dentry, struct dentry *dparent,
struct list_head *base, *lhp;
int valid = 1;
+ check_lock();
+
if (dentry != dparent) {
base = d_hash(dparent, hash);
lhp = base;
@@ -605,6 +661,10 @@ out:
*/
void d_delete(struct dentry * dentry)
{
+ check_lock();
+
+ check_lock();
+
/*
* Are we the only user?
*/
@@ -646,6 +706,7 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target)
{
const unsigned char *old_name, *new_name;
+ check_lock();
memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
old_name = target->d_name.name;
new_name = dentry->d_name.name;
@@ -674,6 +735,8 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target)
*/
void d_move(struct dentry * dentry, struct dentry * target)
{
+ check_lock();
+
if (!dentry->d_inode)
printk(KERN_WARNING "VFS: moving negative dcache entry\n");
@@ -773,7 +836,11 @@ asmlinkage long sys_getcwd(char *buf, unsigned long size)
error = -ENOMEM;
if (page) {
unsigned long len;
- char * cwd = d_path(pwd, page, PAGE_SIZE);
+ char * cwd;
+
+ lock_kernel();
+ cwd = d_path(pwd, page, PAGE_SIZE);
+ unlock_kernel();
error = -ERANGE;
len = PAGE_SIZE + page - cwd;