Commit 5e37545c authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] ->d_parent fixes

Protect d_parent with "dparent_lock", making ready to get rid of
BKL for d_move().
parent 58982de0
......@@ -30,6 +30,7 @@
/* #define DCACHE_DEBUG 1 */
spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
rwlock_t dparent_lock __cacheline_aligned_in_smp = RW_LOCK_UNLOCKED;
/* Right now the dcache depends on the kernel lock */
#define check_lock() if (!kernel_locked()) BUG()
......@@ -916,7 +917,9 @@ void d_move(struct dentry * dentry, struct dentry * target)
/* Switch the parents and the names.. */
switch_names(dentry, target);
write_lock(&dparent_lock);
do_switch(dentry->d_parent, target->d_parent);
write_unlock(&dparent_lock);
do_switch(dentry->d_name.len, target->d_name.len);
do_switch(dentry->d_name.hash, target->d_name.hash);
......
......@@ -516,7 +516,9 @@ int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent)
fh[1] = inode->i_generation;
fh[2] = MSDOS_I(inode)->i_location;
fh[3] = MSDOS_I(inode)->i_logstart;
read_lock(&dparent_lock);
fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
read_unlock(&dparent_lock);
return 3;
}
......
......@@ -1325,15 +1325,17 @@ int reiserfs_dentry_to_fh(struct dentry *dentry, __u32 *data, int *lenp, int nee
if (maxlen < 5 || ! need_parent)
return 3 ;
read_lock(&dparent_lock);
inode = dentry->d_parent->d_inode ;
data[3] = inode->i_ino ;
data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;
*lenp = 5 ;
if (maxlen < 6)
return 5 ;
if (maxlen >= 6) {
data[5] = inode->i_generation ;
*lenp = 6 ;
return 6 ;
}
read_unlock(&dparent_lock);
return *lenp ;
}
......
......@@ -378,12 +378,14 @@ smb_new_dentry(struct dentry *dentry)
void
smb_renew_times(struct dentry * dentry)
{
read_lock(&dparent_lock);
for (;;) {
dentry->d_time = jiffies;
if (IS_ROOT(dentry))
break;
dentry = dentry->d_parent;
}
read_unlock(&dparent_lock);
}
static struct dentry *
......
......@@ -245,15 +245,20 @@ static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen,
* Build the path string walking the tree backward from end to ROOT
* and store it in reversed order [see reverse_string()]
*/
read_lock(&dparent_lock);
while (!IS_ROOT(entry)) {
if (maxlen < 3)
if (maxlen < 3) {
read_unlock(&dparent_lock);
return -ENAMETOOLONG;
}
len = server->convert(path, maxlen-2,
entry->d_name.name, entry->d_name.len,
server->local_nls, server->remote_nls);
if (len < 0)
if (len < 0) {
read_unlock(&dparent_lock);
return len;
}
reverse_string(path, len);
path += len;
*path++ = '\\';
......@@ -263,6 +268,7 @@ static int smb_build_path(struct smb_sb_info *server, char * buf, int maxlen,
if (IS_ROOT(entry))
break;
}
read_unlock(&dparent_lock);
reverse_string(buf, path-buf);
/* maxlen is at least 1 */
......
......@@ -126,6 +126,7 @@ d_iput: no no yes
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
extern spinlock_t dcache_lock;
extern rwlock_t dparent_lock;
/**
* d_drop - drop a dentry
......
......@@ -33,13 +33,13 @@ static inline void inode_dir_notify(struct inode *inode, unsigned long event)
static inline void dnotify_parent(struct dentry *dentry, unsigned long event)
{
struct dentry *parent;
spin_lock(&dcache_lock);
read_lock(&dparent_lock);
parent = dentry->d_parent;
if (parent->d_inode->i_dnotify_mask & event) {
dget(parent);
spin_unlock(&dcache_lock);
read_unlock(&dparent_lock);
__inode_dir_notify(parent->d_inode, event);
dput(parent);
} else
spin_unlock(&dcache_lock);
read_unlock(&dparent_lock);
}
......@@ -1511,9 +1511,9 @@ extern int inode_setattr(struct inode *, struct iattr *);
static inline ino_t parent_ino(struct dentry *dentry)
{
ino_t res;
spin_lock(&dcache_lock);
read_lock(&dparent_lock);
res = dentry->d_parent->d_inode->i_ino;
spin_unlock(&dcache_lock);
read_unlock(&dparent_lock);
return res;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment