Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@math.psu.edu>2002-02-24 22:07:54 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-02-24 22:07:54 -0800
commit5e37545cf526580b165d3805652f241324a850ac (patch)
tree5114bcd1549089542dd2e19513fead782bf9669f
parent58982de08cf871d4d3b274739f0a502c9cb5e5f4 (diff)
[PATCH] ->d_parent fixes
Protect d_parent with "dparent_lock", making ready to get rid of BKL for d_move().
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/reiserfs/inode.c12
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/proc.c10
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/dnotify.h6
-rw-r--r--include/linux/fs.h4
8 files changed, 28 insertions, 12 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index a421788191fb..fab5e57765f7 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -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);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 73859637332d..10efdd661c63 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -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;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 34462717de56..9ef75e6fe69c 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -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 ;
- data[5] = inode->i_generation ;
- *lenp = 6 ;
- return 6 ;
+ if (maxlen >= 6) {
+ data[5] = inode->i_generation ;
+ *lenp = 6 ;
+ }
+ read_unlock(&dparent_lock);
+ return *lenp ;
}
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 991822bc0796..09d025004c4a 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -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 *
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 4075626db7a4..e2df6e23d73a 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -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 */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 3649086ed83f..21da57231050 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -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
diff --git a/include/linux/dnotify.h b/include/linux/dnotify.h
index 794fd096f31f..60c1e2117f10 100644
--- a/include/linux/dnotify.h
+++ b/include/linux/dnotify.h
@@ -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);
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7bb0610ba3a6..89208aabe5b8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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;
}