diff options
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 71 |
1 files changed, 12 insertions, 59 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 352f958769e1..bb30f9a72c65 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -37,61 +37,9 @@ | |||
37 | #include "super.h" | 37 | #include "super.h" |
38 | #include "glops.h" | 38 | #include "glops.h" |
39 | 39 | ||
40 | struct gfs2_skip_data { | 40 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) |
41 | u64 no_addr; | ||
42 | int skipped; | ||
43 | int non_block; | ||
44 | }; | ||
45 | |||
46 | static int iget_test(struct inode *inode, void *opaque) | ||
47 | { | ||
48 | struct gfs2_inode *ip = GFS2_I(inode); | ||
49 | struct gfs2_skip_data *data = opaque; | ||
50 | |||
51 | if (ip->i_no_addr == data->no_addr) { | ||
52 | if (data->non_block && | ||
53 | inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { | ||
54 | data->skipped = 1; | ||
55 | return 0; | ||
56 | } | ||
57 | return 1; | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int iget_set(struct inode *inode, void *opaque) | ||
63 | { | ||
64 | struct gfs2_inode *ip = GFS2_I(inode); | ||
65 | struct gfs2_skip_data *data = opaque; | ||
66 | |||
67 | if (data->skipped) | ||
68 | return -ENOENT; | ||
69 | inode->i_ino = (unsigned long)(data->no_addr); | ||
70 | ip->i_no_addr = data->no_addr; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int non_block) | ||
75 | { | 41 | { |
76 | unsigned long hash = (unsigned long)no_addr; | 42 | return ilookup(sb, (unsigned long)no_addr); |
77 | struct gfs2_skip_data data; | ||
78 | |||
79 | data.no_addr = no_addr; | ||
80 | data.skipped = 0; | ||
81 | data.non_block = non_block; | ||
82 | return ilookup5(sb, hash, iget_test, &data); | ||
83 | } | ||
84 | |||
85 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr, | ||
86 | int non_block) | ||
87 | { | ||
88 | struct gfs2_skip_data data; | ||
89 | unsigned long hash = (unsigned long)no_addr; | ||
90 | |||
91 | data.no_addr = no_addr; | ||
92 | data.skipped = 0; | ||
93 | data.non_block = non_block; | ||
94 | return iget5_locked(sb, hash, iget_test, iget_set, &data); | ||
95 | } | 43 | } |
96 | 44 | ||
97 | /** | 45 | /** |
@@ -132,21 +80,21 @@ static void gfs2_set_iop(struct inode *inode) | |||
132 | * @sb: The super block | 80 | * @sb: The super block |
133 | * @no_addr: The inode number | 81 | * @no_addr: The inode number |
134 | * @type: The type of the inode | 82 | * @type: The type of the inode |
135 | * non_block: Can we block on inodes that are being freed? | ||
136 | * | 83 | * |
137 | * Returns: A VFS inode, or an error | 84 | * Returns: A VFS inode, or an error |
138 | */ | 85 | */ |
139 | 86 | ||
140 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | 87 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, |
141 | u64 no_addr, u64 no_formal_ino, int non_block) | 88 | u64 no_addr, u64 no_formal_ino) |
142 | { | 89 | { |
143 | struct inode *inode; | 90 | struct inode *inode; |
144 | struct gfs2_inode *ip; | 91 | struct gfs2_inode *ip; |
145 | struct gfs2_glock *io_gl = NULL; | 92 | struct gfs2_glock *io_gl = NULL; |
146 | int error; | 93 | int error; |
147 | 94 | ||
148 | inode = gfs2_iget(sb, no_addr, non_block); | 95 | inode = iget_locked(sb, (unsigned long)no_addr); |
149 | ip = GFS2_I(inode); | 96 | ip = GFS2_I(inode); |
97 | ip->i_no_addr = no_addr; | ||
150 | 98 | ||
151 | if (!inode) | 99 | if (!inode) |
152 | return ERR_PTR(-ENOMEM); | 100 | return ERR_PTR(-ENOMEM); |
@@ -221,7 +169,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
221 | if (error) | 169 | if (error) |
222 | goto fail; | 170 | goto fail; |
223 | 171 | ||
224 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1); | 172 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0); |
225 | if (IS_ERR(inode)) | 173 | if (IS_ERR(inode)) |
226 | goto fail; | 174 | goto fail; |
227 | 175 | ||
@@ -592,7 +540,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
592 | struct inode *inode = NULL; | 540 | struct inode *inode = NULL; |
593 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | 541 | struct gfs2_inode *dip = GFS2_I(dir), *ip; |
594 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 542 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
595 | struct gfs2_glock *io_gl; | 543 | struct gfs2_glock *io_gl = NULL; |
596 | int error, free_vfs_inode = 1; | 544 | int error, free_vfs_inode = 1; |
597 | u32 aflags = 0; | 545 | u32 aflags = 0; |
598 | unsigned blocks = 1; | 546 | unsigned blocks = 1; |
@@ -729,6 +677,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
729 | if (error) | 677 | if (error) |
730 | goto fail_gunlock2; | 678 | goto fail_gunlock2; |
731 | 679 | ||
680 | BUG_ON(test_and_set_bit(GLF_INODE_CREATING, &io_gl->gl_flags)); | ||
681 | |||
732 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); | 682 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); |
733 | if (error) | 683 | if (error) |
734 | goto fail_gunlock2; | 684 | goto fail_gunlock2; |
@@ -771,12 +721,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
771 | } | 721 | } |
772 | gfs2_glock_dq_uninit(ghs); | 722 | gfs2_glock_dq_uninit(ghs); |
773 | gfs2_glock_dq_uninit(ghs + 1); | 723 | gfs2_glock_dq_uninit(ghs + 1); |
724 | clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags); | ||
774 | return error; | 725 | return error; |
775 | 726 | ||
776 | fail_gunlock3: | 727 | fail_gunlock3: |
777 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 728 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
778 | gfs2_glock_put(io_gl); | 729 | gfs2_glock_put(io_gl); |
779 | fail_gunlock2: | 730 | fail_gunlock2: |
731 | if (io_gl) | ||
732 | clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags); | ||
780 | gfs2_glock_dq_uninit(ghs + 1); | 733 | gfs2_glock_dq_uninit(ghs + 1); |
781 | fail_free_inode: | 734 | fail_free_inode: |
782 | if (ip->i_gl) | 735 | if (ip->i_gl) |