patch-2.3.99-pre9 linux/fs/dcache.c
Next file: linux/fs/devfs/base.c
Previous file: linux/fs/cramfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 180
- Date:
Sun May 21 20:34:37 2000
- Orig file:
v2.3.99-pre8/linux/fs/dcache.c
- Orig date:
Thu May 11 15:30:08 2000
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/dcache.c linux/fs/dcache.c
@@ -131,7 +131,8 @@
* Each fs will have to watch for this.
*/
if (dentry->d_op && dentry->d_op->d_delete) {
- dentry->d_op->d_delete(dentry);
+ if (dentry->d_op->d_delete(dentry))
+ d_drop(dentry);
count = dentry->d_count - 1;
if (count != 0)
@@ -220,6 +221,53 @@
return 0;
}
+/**
+ * d_find_alias - grab a hashed alias of inode
+ * @inode: inode in question
+ *
+ * If inode has a hashed alias - acquire the reference to alias and
+ * return it. Otherwise return NULL. Notice that if inode is a directory
+ * there can be only one alias and it can be unhashed only if it has
+ * no children.
+ */
+
+struct dentry * d_find_alias(struct inode *inode)
+{
+ struct list_head *head, *next, *tmp;
+ struct dentry *alias;
+
+ head = &inode->i_dentry;
+ next = inode->i_dentry.next;
+ while (next != head) {
+ tmp = next;
+ next = tmp->next;
+ alias = list_entry(tmp, struct dentry, d_alias);
+ if (!d_unhashed(alias))
+ return dget(alias);
+ }
+ return NULL;
+}
+
+/*
+ * Try to kill dentries associated with this inode.
+ * WARNING: you must own a reference to inode.
+ */
+void d_prune_aliases(struct inode *inode)
+{
+ struct list_head *tmp, *head = &inode->i_dentry;
+restart:
+ tmp = head;
+ while ((tmp = tmp->next) != head) {
+ struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+ if (!dentry->d_count) {
+ dget(dentry);
+ d_drop(dentry);
+ dput(dentry);
+ goto restart;
+ }
+ }
+}
+
/*
* Throw away a dentry - free the inode, dput the parent.
* This requires that the LRU list has already been
@@ -384,37 +432,6 @@
return 0; /* No mount points found in tree */
}
-int d_active_refs(struct dentry *root)
-{
- struct dentry *this_parent = root;
- struct list_head *next;
- int count = root->d_count;
-
-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;
- /* Decrement count for unused children */
- count += (dentry->d_count - 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 != root) {
- next = this_parent->d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
- }
- return count;
-}
-
/*
* Search the dentry child list for the specified parent,
* and move any unused dentries to the end of the unused
@@ -788,7 +805,7 @@
* Note that we have to be a lot more careful about getting the hash
* switched - we have to switch the hash value properly even if it
* then no longer matches the actual (corrupted) string of the target.
- * The has value has to match the hash queue that the dentry is on..
+ * The hash value has to match the hash queue that the dentry is on..
*/
static inline void switch_names(struct dentry * dentry, struct dentry * target)
{
@@ -948,7 +965,12 @@
asmlinkage long sys_getcwd(char *buf, unsigned long size)
{
int error;
- struct dentry *pwd = current->fs->pwd;
+ struct vfsmount *pwdmnt;
+ struct dentry *pwd;
+
+ lock_kernel();
+ pwdmnt = mntget(current->fs->pwdmnt);
+ pwd = dget(current->fs->pwd);
error = -ENOENT;
/* Has the current directory has been unlinked? */
@@ -959,9 +981,7 @@
unsigned long len;
char * cwd;
- lock_kernel();
cwd = d_path(pwd, current->fs->pwdmnt, page, PAGE_SIZE);
- unlock_kernel();
error = -ERANGE;
len = PAGE_SIZE + page - cwd;
@@ -973,6 +993,9 @@
free_page((unsigned long) page);
}
}
+ dput(pwd);
+ mntput(pwdmnt);
+ unlock_kernel();
return error;
}
@@ -1008,6 +1031,34 @@
break;
}
return result;
+}
+
+void d_genocide(struct dentry *root)
+{
+ struct dentry *this_parent = root;
+ struct list_head *next;
+
+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;
+ if (d_unhashed(dentry)||!dentry->d_inode)
+ continue;
+ if (!list_empty(&dentry->d_subdirs)) {
+ this_parent = dentry;
+ goto repeat;
+ }
+ dentry->d_count--;
+ }
+ if (this_parent != root) {
+ next = this_parent->d_child.next;
+ this_parent->d_count--;
+ this_parent = this_parent->d_parent;
+ goto resume;
+ }
}
/**
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)