diff options
| -rw-r--r-- | fs/ocfs2/dcache.c | 33 | ||||
| -rw-r--r-- | fs/ocfs2/dcache.h | 1 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 8 | ||||
| -rw-r--r-- | fs/ocfs2/inode.c | 1 | ||||
| -rw-r--r-- | fs/ocfs2/inode.h | 1 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 3 |
6 files changed, 42 insertions, 5 deletions
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b4957c7d9fe2..edaded48e7e9 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -40,6 +40,14 @@ | |||
| 40 | #include "inode.h" | 40 | #include "inode.h" |
| 41 | #include "super.h" | 41 | #include "super.h" |
| 42 | 42 | ||
| 43 | void ocfs2_dentry_attach_gen(struct dentry *dentry) | ||
| 44 | { | ||
| 45 | unsigned long gen = | ||
| 46 | OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; | ||
| 47 | BUG_ON(dentry->d_inode); | ||
| 48 | dentry->d_fsdata = (void *)gen; | ||
| 49 | } | ||
| 50 | |||
| 43 | 51 | ||
| 44 | static int ocfs2_dentry_revalidate(struct dentry *dentry, | 52 | static int ocfs2_dentry_revalidate(struct dentry *dentry, |
| 45 | struct nameidata *nd) | 53 | struct nameidata *nd) |
| @@ -51,11 +59,20 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, | |||
| 51 | mlog_entry("(0x%p, '%.*s')\n", dentry, | 59 | mlog_entry("(0x%p, '%.*s')\n", dentry, |
| 52 | dentry->d_name.len, dentry->d_name.name); | 60 | dentry->d_name.len, dentry->d_name.name); |
| 53 | 61 | ||
| 54 | /* Never trust a negative dentry - force a new lookup. */ | 62 | /* For a negative dentry - |
| 63 | * check the generation number of the parent and compare with the | ||
| 64 | * one stored in the inode. | ||
| 65 | */ | ||
| 55 | if (inode == NULL) { | 66 | if (inode == NULL) { |
| 56 | mlog(0, "negative dentry: %.*s\n", dentry->d_name.len, | 67 | unsigned long gen = (unsigned long) dentry->d_fsdata; |
| 57 | dentry->d_name.name); | 68 | unsigned long pgen = |
| 58 | goto bail; | 69 | OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; |
| 70 | mlog(0, "negative dentry: %.*s parent gen: %lu " | ||
| 71 | "dentry gen: %lu\n", | ||
| 72 | dentry->d_name.len, dentry->d_name.name, pgen, gen); | ||
| 73 | if (gen != pgen) | ||
| 74 | goto bail; | ||
| 75 | goto valid; | ||
| 59 | } | 76 | } |
| 60 | 77 | ||
| 61 | BUG_ON(!osb); | 78 | BUG_ON(!osb); |
| @@ -96,6 +113,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, | |||
| 96 | goto bail; | 113 | goto bail; |
| 97 | } | 114 | } |
| 98 | 115 | ||
| 116 | valid: | ||
| 99 | ret = 1; | 117 | ret = 1; |
| 100 | 118 | ||
| 101 | bail: | 119 | bail: |
| @@ -227,6 +245,12 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, | |||
| 227 | if (!inode) | 245 | if (!inode) |
| 228 | return 0; | 246 | return 0; |
| 229 | 247 | ||
| 248 | if (!dentry->d_inode && dentry->d_fsdata) { | ||
| 249 | /* Converting a negative dentry to positive | ||
| 250 | Clear dentry->d_fsdata */ | ||
| 251 | dentry->d_fsdata = dl = NULL; | ||
| 252 | } | ||
| 253 | |||
| 230 | if (dl) { | 254 | if (dl) { |
| 231 | mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno, | 255 | mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno, |
| 232 | " \"%.*s\": old parent: %llu, new: %llu\n", | 256 | " \"%.*s\": old parent: %llu, new: %llu\n", |
| @@ -452,6 +476,7 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
| 452 | 476 | ||
| 453 | out: | 477 | out: |
| 454 | iput(inode); | 478 | iput(inode); |
| 479 | ocfs2_dentry_attach_gen(dentry); | ||
| 455 | } | 480 | } |
| 456 | 481 | ||
| 457 | /* | 482 | /* |
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index f5dd1789acf1..b79eff709958 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h | |||
| @@ -64,5 +64,6 @@ void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target, | |||
| 64 | struct inode *old_dir, struct inode *new_dir); | 64 | struct inode *old_dir, struct inode *new_dir); |
| 65 | 65 | ||
| 66 | extern spinlock_t dentry_attach_lock; | 66 | extern spinlock_t dentry_attach_lock; |
| 67 | void ocfs2_dentry_attach_gen(struct dentry *dentry); | ||
| 67 | 68 | ||
| 68 | #endif /* OCFS2_DCACHE_H */ | 69 | #endif /* OCFS2_DCACHE_H */ |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 5e02a893f46e..e8d94d722ecb 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -3635,10 +3635,18 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, | |||
| 3635 | { | 3635 | { |
| 3636 | struct inode *inode; | 3636 | struct inode *inode; |
| 3637 | struct address_space *mapping; | 3637 | struct address_space *mapping; |
| 3638 | struct ocfs2_inode_info *oi; | ||
| 3638 | 3639 | ||
| 3639 | inode = ocfs2_lock_res_inode(lockres); | 3640 | inode = ocfs2_lock_res_inode(lockres); |
| 3640 | mapping = inode->i_mapping; | 3641 | mapping = inode->i_mapping; |
| 3641 | 3642 | ||
| 3643 | if (S_ISDIR(inode->i_mode)) { | ||
| 3644 | oi = OCFS2_I(inode); | ||
| 3645 | oi->ip_dir_lock_gen++; | ||
| 3646 | mlog(0, "generation: %u\n", oi->ip_dir_lock_gen); | ||
| 3647 | goto out; | ||
| 3648 | } | ||
| 3649 | |||
| 3642 | if (!S_ISREG(inode->i_mode)) | 3650 | if (!S_ISREG(inode->i_mode)) |
| 3643 | goto out; | 3651 | goto out; |
| 3644 | 3652 | ||
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index eece3e05d9d0..f935fd6600dd 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
| @@ -335,6 +335,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
| 335 | else | 335 | else |
| 336 | inode->i_fop = &ocfs2_dops_no_plocks; | 336 | inode->i_fop = &ocfs2_dops_no_plocks; |
| 337 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 337 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
| 338 | OCFS2_I(inode)->ip_dir_lock_gen = 1; | ||
| 338 | break; | 339 | break; |
| 339 | case S_IFLNK: | 340 | case S_IFLNK: |
| 340 | if (ocfs2_inode_is_fast_symlink(inode)) | 341 | if (ocfs2_inode_is_fast_symlink(inode)) |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 0bc477a3aeb8..1c508b149b3a 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
| @@ -67,6 +67,7 @@ struct ocfs2_inode_info | |||
| 67 | /* Only valid if the inode is the dir. */ | 67 | /* Only valid if the inode is the dir. */ |
| 68 | u32 ip_last_used_slot; | 68 | u32 ip_last_used_slot; |
| 69 | u64 ip_last_used_group; | 69 | u64 ip_last_used_group; |
| 70 | u32 ip_dir_lock_gen; | ||
| 70 | 71 | ||
| 71 | struct ocfs2_alloc_reservation ip_la_data_resv; | 72 | struct ocfs2_alloc_reservation ip_la_data_resv; |
| 72 | }; | 73 | }; |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index a00dda2e4f16..e7bde21149ae 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -171,7 +171,8 @@ bail_add: | |||
| 171 | ret = ERR_PTR(status); | 171 | ret = ERR_PTR(status); |
| 172 | goto bail_unlock; | 172 | goto bail_unlock; |
| 173 | } | 173 | } |
| 174 | } | 174 | } else |
| 175 | ocfs2_dentry_attach_gen(dentry); | ||
| 175 | 176 | ||
| 176 | bail_unlock: | 177 | bail_unlock: |
| 177 | /* Don't drop the cluster lock until *after* the d_add -- | 178 | /* Don't drop the cluster lock until *after* the d_add -- |
