Loading drivers/staging/smbfs/cache.c +2 −2 Original line number Diff line number Diff line Loading @@ -145,8 +145,8 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, goto end_advance; } else { hashed = 1; memcpy((char *) newdent->d_name.name, qname->name, newdent->d_name.len); /* dir i_mutex is locked because we're in readdir */ dentry_update_name_case(newdent, qname); } if (!newdent->d_inode) { Loading fs/dcache.c +27 −0 Original line number Diff line number Diff line Loading @@ -1589,6 +1589,33 @@ void d_rehash(struct dentry * entry) } EXPORT_SYMBOL(d_rehash); /** * dentry_update_name_case - update case insensitive dentry with a new name * @dentry: dentry to be updated * @name: new name * * Update a case insensitive dentry with new case of name. * * dentry must have been returned by d_lookup with name @name. Old and new * name lengths must match (ie. no d_compare which allows mismatched name * lengths). * * Parent inode i_mutex must be held over d_lookup and into this call (to * keep renames and concurrent inserts, and readdir(2) away). */ void dentry_update_name_case(struct dentry *dentry, struct qstr *name) { BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */ spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); memcpy((unsigned char *)dentry->d_name.name, name->name, name->len); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } EXPORT_SYMBOL(dentry_update_name_case); /* * When switching names, the actual string doesn't strictly have to * be preserved in the target - because we're dropping the target Loading fs/ncpfs/dir.c +6 −29 Original line number Diff line number Diff line Loading @@ -611,35 +611,12 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, shrink_dcache_parent(newdent); /* * It is not as dangerous as it looks. NetWare's OS2 namespace is * case preserving yet case insensitive. So we update dentry's name * as received from server. We found dentry via d_lookup with our * hash, so we know that hash does not change, and so replacing name * should be reasonably safe. * NetWare's OS2 namespace is case preserving yet case * insensitive. So we update dentry's name as received from * server. Parent dir's i_mutex is locked because we're in * readdir. */ if (qname.len == newdent->d_name.len && memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) { struct inode *inode = newdent->d_inode; /* * Inside ncpfs all uses of d_name are either for debugging, * or on functions which acquire inode mutex (mknod, creat, * lookup). So grab i_mutex here, to be sure. d_path * uses dcache_lock when generating path, so we should too. * And finally d_compare is protected by dentry's d_lock, so * here we go. */ if (inode) mutex_lock(&inode->i_mutex); spin_lock(&dcache_lock); spin_lock(&newdent->d_lock); memcpy((char *) newdent->d_name.name, qname.name, newdent->d_name.len); spin_unlock(&newdent->d_lock); spin_unlock(&dcache_lock); if (inode) mutex_unlock(&inode->i_mutex); } dentry_update_name_case(newdent, &qname); } if (!newdent->d_inode) { Loading @@ -657,7 +634,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, } else { struct inode *inode = newdent->d_inode; mutex_lock(&inode->i_mutex); mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); ncp_update_inode2(inode, entry); mutex_unlock(&inode->i_mutex); } Loading include/linux/dcache.h +2 −0 Original line number Diff line number Diff line Loading @@ -290,6 +290,8 @@ static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *in return res; } extern void dentry_update_name_case(struct dentry *, struct qstr *); /* used for rename() and baskets */ extern void d_move(struct dentry *, struct dentry *); extern struct dentry *d_ancestor(struct dentry *, struct dentry *); Loading Loading
drivers/staging/smbfs/cache.c +2 −2 Original line number Diff line number Diff line Loading @@ -145,8 +145,8 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, goto end_advance; } else { hashed = 1; memcpy((char *) newdent->d_name.name, qname->name, newdent->d_name.len); /* dir i_mutex is locked because we're in readdir */ dentry_update_name_case(newdent, qname); } if (!newdent->d_inode) { Loading
fs/dcache.c +27 −0 Original line number Diff line number Diff line Loading @@ -1589,6 +1589,33 @@ void d_rehash(struct dentry * entry) } EXPORT_SYMBOL(d_rehash); /** * dentry_update_name_case - update case insensitive dentry with a new name * @dentry: dentry to be updated * @name: new name * * Update a case insensitive dentry with new case of name. * * dentry must have been returned by d_lookup with name @name. Old and new * name lengths must match (ie. no d_compare which allows mismatched name * lengths). * * Parent inode i_mutex must be held over d_lookup and into this call (to * keep renames and concurrent inserts, and readdir(2) away). */ void dentry_update_name_case(struct dentry *dentry, struct qstr *name) { BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */ spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); memcpy((unsigned char *)dentry->d_name.name, name->name, name->len); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } EXPORT_SYMBOL(dentry_update_name_case); /* * When switching names, the actual string doesn't strictly have to * be preserved in the target - because we're dropping the target Loading
fs/ncpfs/dir.c +6 −29 Original line number Diff line number Diff line Loading @@ -611,35 +611,12 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, shrink_dcache_parent(newdent); /* * It is not as dangerous as it looks. NetWare's OS2 namespace is * case preserving yet case insensitive. So we update dentry's name * as received from server. We found dentry via d_lookup with our * hash, so we know that hash does not change, and so replacing name * should be reasonably safe. * NetWare's OS2 namespace is case preserving yet case * insensitive. So we update dentry's name as received from * server. Parent dir's i_mutex is locked because we're in * readdir. */ if (qname.len == newdent->d_name.len && memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) { struct inode *inode = newdent->d_inode; /* * Inside ncpfs all uses of d_name are either for debugging, * or on functions which acquire inode mutex (mknod, creat, * lookup). So grab i_mutex here, to be sure. d_path * uses dcache_lock when generating path, so we should too. * And finally d_compare is protected by dentry's d_lock, so * here we go. */ if (inode) mutex_lock(&inode->i_mutex); spin_lock(&dcache_lock); spin_lock(&newdent->d_lock); memcpy((char *) newdent->d_name.name, qname.name, newdent->d_name.len); spin_unlock(&newdent->d_lock); spin_unlock(&dcache_lock); if (inode) mutex_unlock(&inode->i_mutex); } dentry_update_name_case(newdent, &qname); } if (!newdent->d_inode) { Loading @@ -657,7 +634,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, } else { struct inode *inode = newdent->d_inode; mutex_lock(&inode->i_mutex); mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); ncp_update_inode2(inode, entry); mutex_unlock(&inode->i_mutex); } Loading
include/linux/dcache.h +2 −0 Original line number Diff line number Diff line Loading @@ -290,6 +290,8 @@ static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *in return res; } extern void dentry_update_name_case(struct dentry *, struct qstr *); /* used for rename() and baskets */ extern void d_move(struct dentry *, struct dentry *); extern struct dentry *d_ancestor(struct dentry *, struct dentry *); Loading