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