diff options
Diffstat (limited to 'fs/smbfs/cache.c')
-rw-r--r-- | fs/smbfs/cache.c | 55 |
1 files changed, 10 insertions, 45 deletions
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c index e3e9c044f..3dc17d229 100644 --- a/fs/smbfs/cache.c +++ b/fs/smbfs/cache.c @@ -48,6 +48,7 @@ out_unlock: UnlockPage(page); page_cache_release(page); out: + return; } /* @@ -71,47 +72,6 @@ smb_invalidate_dircache_entries(struct dentry *parent) spin_unlock(&dcache_lock); } - -static int -smb_d_validate(struct dentry *dentry) -{ - unsigned long dent_addr = (unsigned long) dentry; - unsigned long min_addr = PAGE_OFFSET; - 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) - goto bad_align; - if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 + - sizeof(struct dentry)))) - goto bad_addr; - /* - * Looks safe enough to dereference ... - */ - len = dentry->d_name.len; - if (len > SMB_MAXPATHLEN) - 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; - -bad_addr: - printk(KERN_ERR "smb_d_validate: invalid address %lx\n", dent_addr); - goto out; -bad_align: - printk(KERN_ERR "smb_d_validate: unaligned address %lx\n", dent_addr); - goto out; -} - /* * dget, but require that fpos and parent matches what the dentry contains. * dentry is not known to be a valid pointer at entry. @@ -122,8 +82,8 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) struct dentry *dent = dentry; struct list_head *next; - if (smb_d_validate(dent)) { - if (dent->d_parent == parent && + if (d_validate(dent, parent)) { + if (dent->d_name.len <= SMB_MAXPATHLEN && (unsigned long)dent->d_fsdata == fpos) { if (!dent->d_inode) { dput(dent); @@ -167,6 +127,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct inode *newino, *inode = dentry->d_inode; struct smb_cache_control ctl = *ctrl; int valid = 0; + int hashed = 0; ino_t ino = 0; qname->hash = full_name_hash(qname->name, qname->len); @@ -181,9 +142,11 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 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) { smb_renew_times(newdent); @@ -191,7 +154,9 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, newino = smb_iget(inode->i_sb, entry); if (newino) { smb_new_dentry(newdent); - d_add(newdent, newino); + d_instantiate(newdent, newino); + if (!hashed) + d_rehash(newdent); } } else smb_set_inode_attr(newdent->d_inode, entry); |