[PATCH] ncpfs: d_add + ncp_d_validate fixes

Petr Vandrovec (vandrove@vc.cvut.cz)
Wed, 7 Mar 2001 22:49:00 +0100


Hi Linus, hi Alan,
could you apply following patch into 2.4.2-ac14 and 2.4.3-pre4?
It does:

last three hunks: do not d_add() already hashed dentry.
It is fix for problem discovered by Urban
in his smbfs. Probably it is more utilized
than ncpfs...
rest: moved test for dentry->d_parent != parent before
call to d_validate(), instead of doing
it in caller after ncp_d_validate() returns.
Al Viro asked for this some time ago, but
it somewhat did not found its way into
mainstream kernel yet...
While I was on it, I changed ncp_d_validate
layout a bit to get shorter code.

Thanks,
Petr Vandrovec
vandrove@vc.cvut.cz

--- linux/fs/ncpfs/dir.c Fri Feb 9 20:29:44 2001
+++ linux/fs/ncpfs/dir.c Wed Mar 7 22:40:12 2001
@@ -328,19 +328,18 @@

/* most parts from nfsd_d_validate() */
static int
-ncp_d_validate(struct dentry *dentry)
+ncp_d_validate(struct dentry *dentry, struct dentry* parent)
{
unsigned long dent_addr = (unsigned long) dentry;
- unsigned long min_addr = PAGE_OFFSET;
- unsigned long align_mask = 0x0F;
+ const unsigned long min_addr = PAGE_OFFSET;
+ const unsigned long align_mask = 0x0F;
unsigned int len;
- int valid = 0;

if (dent_addr < min_addr)
goto bad_addr;
if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry))
goto bad_addr;
- if ((dent_addr & ~align_mask) != dent_addr)
+ if (dent_addr & align_mask)
goto bad_align;
if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 +
sizeof(struct dentry))))
@@ -351,20 +350,21 @@
len = dentry->d_name.len;
if (len > NCP_MAXPATHLEN)
goto out;
+ if (dentry->d_parent != parent)
+ goto out;
/*
* Note: d_validate doesn't dereference the parent pointer ...
* just combines it with the name hash to find the hash chain.
*/
- valid = d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);
-out:
- return valid;
+ return d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);

bad_addr:
PRINTK("ncp_d_validate: invalid address %lx\n", dent_addr);
goto out;
bad_align:
PRINTK("ncp_d_validate: unaligned address %lx\n", dent_addr);
- goto out;
+out:
+ return 0;
}

static struct dentry *
@@ -373,9 +373,8 @@
struct dentry *dent = dentry;
struct list_head *next;

- if (ncp_d_validate(dent)) {
- if (dent->d_parent == parent &&
- (unsigned long)dent->d_fsdata == fpos) {
+ if (ncp_d_validate(dent, parent)) {
+ if ((unsigned long)dent->d_fsdata == fpos) {
if (!dent->d_inode) {
dput(dent);
dent = NULL;
@@ -580,6 +579,7 @@
struct ncp_cache_control ctl = *ctrl;
struct qstr qname;
int valid = 0;
+ int hashed = 0;
ino_t ino = 0;
__u8 __name[256];

@@ -602,9 +602,11 @@
newdent = d_alloc(dentry, &qname);
if (!newdent)
goto end_advance;
- } else
+ } else {
+ hashed = 1;
memcpy((char *) newdent->d_name.name, qname.name,
newdent->d_name.len);
+ }

if (!newdent->d_inode) {
entry->opened = 0;
@@ -612,7 +614,9 @@
newino = ncp_iget(inode->i_sb, entry);
if (newino) {
newdent->d_op = &ncp_dentry_operations;
- d_add(newdent, newino);
+ d_instantiate(newdent, newino);
+ if (!hashed)
+ d_rehash(newdent);
}
} else
ncp_update_inode2(newdent->d_inode, entry);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/