patch-2.1.49 linux/fs/dcache.c
Next file: linux/fs/ext2/namei.c
Previous file: linux/fs/buffer.c
Back to the patch index
Back to the overall index
- Lines: 139
- Date:
Mon Aug 11 14:11:44 1997
- Orig file:
v2.1.48/linux/fs/dcache.c
- Orig date:
Mon Aug 4 16:25:38 1997
diff -u --recursive --new-file v2.1.48/linux/fs/dcache.c linux/fs/dcache.c
@@ -92,6 +92,25 @@
}
/*
+ * Try to invalidate the dentry if it turns out to be
+ * possible. If there are other users of the dentry we
+ * can't invalidate it.
+ *
+ * This is currently incorrect. We should try to see if
+ * we can invalidate any unused children - right now we
+ * refuse to invalidate way too much.
+ */
+int d_invalidate(struct dentry * dentry)
+{
+ /* We should do a partial shrink_dcache here */
+ if (dentry->d_count != 1)
+ return -EBUSY;
+
+ d_drop(dentry);
+ return 0;
+}
+
+/*
* Shrink the dcache. This is done when we need
* more memory, or simply when we need to unmount
* something (at which point we need to unuse
@@ -270,18 +289,6 @@
(dentry->d_name.len == len);
}
-static inline void d_insert_to_parent(struct dentry * entry, struct dentry * parent)
-{
- list_add(&entry->d_hash, d_hash(dget(parent), entry->d_name.hash));
-}
-
-static inline void d_remove_from_parent(struct dentry * dentry, struct dentry * parent)
-{
- list_del(&dentry->d_hash);
- dput(parent);
-}
-
-
/*
* When a file is deleted, we have two options:
* - turn this dentry into a negative dentry
@@ -317,42 +324,55 @@
void d_add(struct dentry * entry, struct inode * inode)
{
- d_insert_to_parent(entry, entry->d_parent);
+ struct dentry * parent = dget(entry->d_parent);
+
+ list_add(&entry->d_hash, d_hash(parent, entry->d_name.hash));
d_instantiate(entry, inode);
}
-static inline void alloc_new_name(struct dentry * entry, struct qstr *newname)
-{
- int len = newname->len;
- int hash = newname->hash;
- char *name = (char *) entry->d_name.name;
-
- if (NAME_ALLOC_LEN(len) != NAME_ALLOC_LEN(entry->d_name.len)) {
- name = kmalloc(NAME_ALLOC_LEN(len), GFP_KERNEL);
- if (!name)
- printk("out of memory for dcache\n");
- kfree(entry->d_name.name);
- entry->d_name.name = name;
- }
- memcpy(name, newname->name, len);
- name[len] = 0;
- entry->d_name.len = len;
- entry->d_name.hash = hash;
-}
+#define switch(x,y) do { \
+ __typeof__ (x) __tmp = x; \
+ x = y; y = __tmp; } while (0)
-void d_move(struct dentry * dentry, struct dentry * newdir, struct qstr * newname)
+/*
+ * We cannibalize "newdentry" when moving dentry on top of it,
+ * because it's going to be thrown away anyway. We could be more
+ * polite about it, though.
+ *
+ * This forceful removal will result in ugly /proc output if
+ * somebody holds a file open that got deleted due to a rename.
+ * We could be nicer about the deleted file, and let it show
+ * up under the name it got deleted rather than the name that
+ * deleted it.
+ *
+ * Careful with the hash switch. The hash switch depends on
+ * the fact that any list-entry can be a head of the list.
+ * Think about it.
+ */
+void d_move(struct dentry * dentry, struct dentry * target)
{
- if (!dentry)
- return;
+ struct list_head * oldhead;
if (!dentry->d_inode)
printk("VFS: moving negative dcache entry\n");
- d_remove_from_parent(dentry, dentry->d_parent);
- alloc_new_name(dentry, newname);
- dentry->d_parent = newdir;
- d_insert_to_parent(dentry, newdir);
+ /* Switch the hashes.. */
+ oldhead = dentry->d_hash.prev;
+ list_del(&dentry->d_hash);
+ list_add(&dentry->d_hash, &target->d_hash);
+ list_del(&target->d_hash);
+ list_add(&target->d_hash, oldhead);
+
+ /* Switch the parents and the names.. */
+ switch(dentry->d_parent, target->d_parent);
+ switch(dentry->d_name.name, target->d_name.name);
+ switch(dentry->d_name.len, target->d_name.len);
+ switch(dentry->d_name.hash, target->d_name.hash);
+
+ /* Mark the (now overwritten) target deleted. */
+ d_delete(target);
}
+
/*
* "buflen" should be PAGE_SIZE or more.
*/
@@ -364,6 +384,11 @@
*--end = '\0';
buflen--;
+ if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
+ buflen -= 10;
+ end -= 10;
+ memcpy(end, " (deleted)", 10);
+ }
/* Get '/' right */
retval = end-1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov