diff options
| -rw-r--r-- | fs/gfs2/aops.c | 4 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 40 | ||||
| -rw-r--r-- | fs/gfs2/glock.h | 7 | ||||
| -rw-r--r-- | fs/gfs2/glops.c | 16 | ||||
| -rw-r--r-- | fs/gfs2/incore.h | 4 | ||||
| -rw-r--r-- | fs/gfs2/inode.c | 6 | ||||
| -rw-r--r-- | fs/gfs2/lock_dlm.c | 5 | ||||
| -rw-r--r-- | fs/gfs2/main.c | 28 | ||||
| -rw-r--r-- | fs/gfs2/meta_io.c | 46 | ||||
| -rw-r--r-- | fs/gfs2/meta_io.h | 12 | ||||
| -rw-r--r-- | fs/gfs2/super.c | 26 | ||||
| -rw-r--r-- | fs/gfs2/util.c | 1 | ||||
| -rw-r--r-- | fs/gfs2/util.h | 1 |
13 files changed, 101 insertions, 95 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 7b8da9415267..0c1d0b82dcf1 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -1061,8 +1061,8 @@ out: | |||
| 1061 | 1061 | ||
| 1062 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | 1062 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) |
| 1063 | { | 1063 | { |
| 1064 | struct inode *aspace = page->mapping->host; | 1064 | struct address_space *mapping = page->mapping; |
| 1065 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 1065 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); |
| 1066 | struct buffer_head *bh, *head; | 1066 | struct buffer_head *bh, *head; |
| 1067 | struct gfs2_bufdata *bd; | 1067 | struct gfs2_bufdata *bd; |
| 1068 | 1068 | ||
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f42663325931..dfb10a4d467e 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -154,12 +154,14 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, | |||
| 154 | static void glock_free(struct gfs2_glock *gl) | 154 | static void glock_free(struct gfs2_glock *gl) |
| 155 | { | 155 | { |
| 156 | struct gfs2_sbd *sdp = gl->gl_sbd; | 156 | struct gfs2_sbd *sdp = gl->gl_sbd; |
| 157 | struct inode *aspace = gl->gl_aspace; | 157 | struct address_space *mapping = gfs2_glock2aspace(gl); |
| 158 | struct kmem_cache *cachep = gfs2_glock_cachep; | ||
| 158 | 159 | ||
| 159 | if (aspace) | 160 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); |
| 160 | gfs2_aspace_put(aspace); | ||
| 161 | trace_gfs2_glock_put(gl); | 161 | trace_gfs2_glock_put(gl); |
| 162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl); | 162 | if (mapping) |
| 163 | cachep = gfs2_glock_aspace_cachep; | ||
| 164 | sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl); | ||
| 163 | } | 165 | } |
| 164 | 166 | ||
| 165 | /** | 167 | /** |
| @@ -750,10 +752,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 750 | const struct gfs2_glock_operations *glops, int create, | 752 | const struct gfs2_glock_operations *glops, int create, |
| 751 | struct gfs2_glock **glp) | 753 | struct gfs2_glock **glp) |
| 752 | { | 754 | { |
| 755 | struct super_block *s = sdp->sd_vfs; | ||
| 753 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; | 756 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; |
| 754 | struct gfs2_glock *gl, *tmp; | 757 | struct gfs2_glock *gl, *tmp; |
| 755 | unsigned int hash = gl_hash(sdp, &name); | 758 | unsigned int hash = gl_hash(sdp, &name); |
| 756 | int error; | 759 | struct address_space *mapping; |
| 757 | 760 | ||
| 758 | read_lock(gl_lock_addr(hash)); | 761 | read_lock(gl_lock_addr(hash)); |
| 759 | gl = search_bucket(hash, sdp, &name); | 762 | gl = search_bucket(hash, sdp, &name); |
| @@ -765,7 +768,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 765 | if (!create) | 768 | if (!create) |
| 766 | return -ENOENT; | 769 | return -ENOENT; |
| 767 | 770 | ||
| 768 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | 771 | if (glops->go_flags & GLOF_ASPACE) |
| 772 | gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL); | ||
| 773 | else | ||
| 774 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | ||
| 769 | if (!gl) | 775 | if (!gl) |
| 770 | return -ENOMEM; | 776 | return -ENOMEM; |
| 771 | 777 | ||
| @@ -784,18 +790,18 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 784 | gl->gl_tchange = jiffies; | 790 | gl->gl_tchange = jiffies; |
| 785 | gl->gl_object = NULL; | 791 | gl->gl_object = NULL; |
| 786 | gl->gl_sbd = sdp; | 792 | gl->gl_sbd = sdp; |
| 787 | gl->gl_aspace = NULL; | ||
| 788 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 793 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
| 789 | INIT_WORK(&gl->gl_delete, delete_work_func); | 794 | INIT_WORK(&gl->gl_delete, delete_work_func); |
| 790 | 795 | ||
| 791 | /* If this glock protects actual on-disk data or metadata blocks, | 796 | mapping = gfs2_glock2aspace(gl); |
| 792 | create a VFS inode to manage the pages/buffers holding them. */ | 797 | if (mapping) { |
| 793 | if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) { | 798 | mapping->a_ops = &gfs2_meta_aops; |
| 794 | gl->gl_aspace = gfs2_aspace_get(sdp); | 799 | mapping->host = s->s_bdev->bd_inode; |
| 795 | if (!gl->gl_aspace) { | 800 | mapping->flags = 0; |
| 796 | error = -ENOMEM; | 801 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
| 797 | goto fail; | 802 | mapping->assoc_mapping = NULL; |
| 798 | } | 803 | mapping->backing_dev_info = s->s_bdi; |
| 804 | mapping->writeback_index = 0; | ||
| 799 | } | 805 | } |
| 800 | 806 | ||
| 801 | write_lock(gl_lock_addr(hash)); | 807 | write_lock(gl_lock_addr(hash)); |
| @@ -812,10 +818,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 812 | *glp = gl; | 818 | *glp = gl; |
| 813 | 819 | ||
| 814 | return 0; | 820 | return 0; |
| 815 | |||
| 816 | fail: | ||
| 817 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
| 818 | return error; | ||
| 819 | } | 821 | } |
| 820 | 822 | ||
| 821 | /** | 823 | /** |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index c0262faf4725..2bda1911b156 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
| @@ -180,6 +180,13 @@ static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl) | |||
| 180 | return gl->gl_state == LM_ST_SHARED; | 180 | return gl->gl_state == LM_ST_SHARED; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl) | ||
| 184 | { | ||
| 185 | if (gl->gl_ops->go_flags & GLOF_ASPACE) | ||
| 186 | return (struct address_space *)(gl + 1); | ||
| 187 | return NULL; | ||
| 188 | } | ||
| 189 | |||
| 183 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 190 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
| 184 | u64 number, const struct gfs2_glock_operations *glops, | 191 | u64 number, const struct gfs2_glock_operations *glops, |
| 185 | int create, struct gfs2_glock **glp); | 192 | int create, struct gfs2_glock **glp); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 78554acc0605..38e3749d476c 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
| @@ -87,7 +87,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
| 87 | 87 | ||
| 88 | static void rgrp_go_sync(struct gfs2_glock *gl) | 88 | static void rgrp_go_sync(struct gfs2_glock *gl) |
| 89 | { | 89 | { |
| 90 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 90 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
| 91 | int error; | 91 | int error; |
| 92 | 92 | ||
| 93 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) | 93 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) |
| @@ -113,7 +113,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl) | |||
| 113 | 113 | ||
| 114 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | 114 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) |
| 115 | { | 115 | { |
| 116 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 116 | struct address_space *mapping = gfs2_glock2aspace(gl); |
| 117 | 117 | ||
| 118 | BUG_ON(!(flags & DIO_METADATA)); | 118 | BUG_ON(!(flags & DIO_METADATA)); |
| 119 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 119 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
| @@ -134,7 +134,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | |||
| 134 | static void inode_go_sync(struct gfs2_glock *gl) | 134 | static void inode_go_sync(struct gfs2_glock *gl) |
| 135 | { | 135 | { |
| 136 | struct gfs2_inode *ip = gl->gl_object; | 136 | struct gfs2_inode *ip = gl->gl_object; |
| 137 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 137 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
| 138 | int error; | 138 | int error; |
| 139 | 139 | ||
| 140 | if (ip && !S_ISREG(ip->i_inode.i_mode)) | 140 | if (ip && !S_ISREG(ip->i_inode.i_mode)) |
| @@ -183,7 +183,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
| 183 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 183 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
| 184 | 184 | ||
| 185 | if (flags & DIO_METADATA) { | 185 | if (flags & DIO_METADATA) { |
| 186 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 186 | struct address_space *mapping = gfs2_glock2aspace(gl); |
| 187 | truncate_inode_pages(mapping, 0); | 187 | truncate_inode_pages(mapping, 0); |
| 188 | if (ip) { | 188 | if (ip) { |
| 189 | set_bit(GIF_INVALID, &ip->i_flags); | 189 | set_bit(GIF_INVALID, &ip->i_flags); |
| @@ -282,7 +282,8 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
| 282 | 282 | ||
| 283 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) | 283 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) |
| 284 | { | 284 | { |
| 285 | return !gl->gl_aspace->i_mapping->nrpages; | 285 | const struct address_space *mapping = (const struct address_space *)(gl + 1); |
| 286 | return !mapping->nrpages; | ||
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | /** | 289 | /** |
| @@ -387,8 +388,7 @@ static void iopen_go_callback(struct gfs2_glock *gl) | |||
| 387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 388 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
| 388 | 389 | ||
| 389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 390 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
| 390 | gl->gl_state == LM_ST_SHARED && | 391 | gl->gl_state == LM_ST_SHARED && ip) { |
| 391 | ip && test_bit(GIF_USER, &ip->i_flags)) { | ||
| 392 | gfs2_glock_hold(gl); | 392 | gfs2_glock_hold(gl); |
| 393 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) | 393 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) |
| 394 | gfs2_glock_put_nolock(gl); | 394 | gfs2_glock_put_nolock(gl); |
| @@ -407,6 +407,7 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
| 407 | .go_dump = inode_go_dump, | 407 | .go_dump = inode_go_dump, |
| 408 | .go_type = LM_TYPE_INODE, | 408 | .go_type = LM_TYPE_INODE, |
| 409 | .go_min_hold_time = HZ / 5, | 409 | .go_min_hold_time = HZ / 5, |
| 410 | .go_flags = GLOF_ASPACE, | ||
| 410 | }; | 411 | }; |
| 411 | 412 | ||
| 412 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 413 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
| @@ -418,6 +419,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { | |||
| 418 | .go_dump = gfs2_rgrp_dump, | 419 | .go_dump = gfs2_rgrp_dump, |
| 419 | .go_type = LM_TYPE_RGRP, | 420 | .go_type = LM_TYPE_RGRP, |
| 420 | .go_min_hold_time = HZ / 5, | 421 | .go_min_hold_time = HZ / 5, |
| 422 | .go_flags = GLOF_ASPACE, | ||
| 421 | }; | 423 | }; |
| 422 | 424 | ||
| 423 | const struct gfs2_glock_operations gfs2_trans_glops = { | 425 | const struct gfs2_glock_operations gfs2_trans_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index bc0ad158e6b4..1de7e1b7ce83 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
| @@ -162,6 +162,8 @@ struct gfs2_glock_operations { | |||
| 162 | void (*go_callback) (struct gfs2_glock *gl); | 162 | void (*go_callback) (struct gfs2_glock *gl); |
| 163 | const int go_type; | 163 | const int go_type; |
| 164 | const unsigned long go_min_hold_time; | 164 | const unsigned long go_min_hold_time; |
| 165 | const unsigned long go_flags; | ||
| 166 | #define GLOF_ASPACE 1 | ||
| 165 | }; | 167 | }; |
| 166 | 168 | ||
| 167 | enum { | 169 | enum { |
| @@ -225,7 +227,6 @@ struct gfs2_glock { | |||
| 225 | 227 | ||
| 226 | struct gfs2_sbd *gl_sbd; | 228 | struct gfs2_sbd *gl_sbd; |
| 227 | 229 | ||
| 228 | struct inode *gl_aspace; | ||
| 229 | struct list_head gl_ail_list; | 230 | struct list_head gl_ail_list; |
| 230 | atomic_t gl_ail_count; | 231 | atomic_t gl_ail_count; |
| 231 | struct delayed_work gl_work; | 232 | struct delayed_work gl_work; |
| @@ -258,7 +259,6 @@ enum { | |||
| 258 | GIF_INVALID = 0, | 259 | GIF_INVALID = 0, |
| 259 | GIF_QD_LOCKED = 1, | 260 | GIF_QD_LOCKED = 1, |
| 260 | GIF_SW_PAGED = 3, | 261 | GIF_SW_PAGED = 3, |
| 261 | GIF_USER = 4, /* user inode, not metadata addr space */ | ||
| 262 | }; | 262 | }; |
| 263 | 263 | ||
| 264 | 264 | ||
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 6e220f4eee7d..b1bf2694fb2b 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
| @@ -45,7 +45,7 @@ static int iget_test(struct inode *inode, void *opaque) | |||
| 45 | struct gfs2_inode *ip = GFS2_I(inode); | 45 | struct gfs2_inode *ip = GFS2_I(inode); |
| 46 | u64 *no_addr = opaque; | 46 | u64 *no_addr = opaque; |
| 47 | 47 | ||
| 48 | if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags)) | 48 | if (ip->i_no_addr == *no_addr) |
| 49 | return 1; | 49 | return 1; |
| 50 | 50 | ||
| 51 | return 0; | 51 | return 0; |
| @@ -58,7 +58,6 @@ static int iget_set(struct inode *inode, void *opaque) | |||
| 58 | 58 | ||
| 59 | inode->i_ino = (unsigned long)*no_addr; | 59 | inode->i_ino = (unsigned long)*no_addr; |
| 60 | ip->i_no_addr = *no_addr; | 60 | ip->i_no_addr = *no_addr; |
| 61 | set_bit(GIF_USER, &ip->i_flags); | ||
| 62 | return 0; | 61 | return 0; |
| 63 | } | 62 | } |
| 64 | 63 | ||
| @@ -84,7 +83,7 @@ static int iget_skip_test(struct inode *inode, void *opaque) | |||
| 84 | struct gfs2_inode *ip = GFS2_I(inode); | 83 | struct gfs2_inode *ip = GFS2_I(inode); |
| 85 | struct gfs2_skip_data *data = opaque; | 84 | struct gfs2_skip_data *data = opaque; |
| 86 | 85 | ||
| 87 | if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){ | 86 | if (ip->i_no_addr == data->no_addr) { |
| 88 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ | 87 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ |
| 89 | data->skipped = 1; | 88 | data->skipped = 1; |
| 90 | return 0; | 89 | return 0; |
| @@ -103,7 +102,6 @@ static int iget_skip_set(struct inode *inode, void *opaque) | |||
| 103 | return 1; | 102 | return 1; |
| 104 | inode->i_ino = (unsigned long)(data->no_addr); | 103 | inode->i_ino = (unsigned long)(data->no_addr); |
| 105 | ip->i_no_addr = data->no_addr; | 104 | ip->i_no_addr = data->no_addr; |
| 106 | set_bit(GIF_USER, &ip->i_flags); | ||
| 107 | return 0; | 105 | return 0; |
| 108 | } | 106 | } |
| 109 | 107 | ||
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 0e5e0e7022e5..569b46240f61 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
| @@ -30,7 +30,10 @@ static void gdlm_ast(void *arg) | |||
| 30 | 30 | ||
| 31 | switch (gl->gl_lksb.sb_status) { | 31 | switch (gl->gl_lksb.sb_status) { |
| 32 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ | 32 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ |
| 33 | kmem_cache_free(gfs2_glock_cachep, gl); | 33 | if (gl->gl_ops->go_flags & GLOF_ASPACE) |
| 34 | kmem_cache_free(gfs2_glock_aspace_cachep, gl); | ||
| 35 | else | ||
| 36 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
| 34 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | 37 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) |
| 35 | wake_up(&sdp->sd_glock_wait); | 38 | wake_up(&sdp->sd_glock_wait); |
| 36 | return; | 39 | return; |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 5b31f7741a8f..a88fadc704bb 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
| @@ -52,6 +52,22 @@ static void gfs2_init_glock_once(void *foo) | |||
| 52 | atomic_set(&gl->gl_ail_count, 0); | 52 | atomic_set(&gl->gl_ail_count, 0); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static void gfs2_init_gl_aspace_once(void *foo) | ||
| 56 | { | ||
| 57 | struct gfs2_glock *gl = foo; | ||
| 58 | struct address_space *mapping = (struct address_space *)(gl + 1); | ||
| 59 | |||
| 60 | gfs2_init_glock_once(gl); | ||
| 61 | memset(mapping, 0, sizeof(*mapping)); | ||
| 62 | INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); | ||
| 63 | spin_lock_init(&mapping->tree_lock); | ||
| 64 | spin_lock_init(&mapping->i_mmap_lock); | ||
| 65 | INIT_LIST_HEAD(&mapping->private_list); | ||
| 66 | spin_lock_init(&mapping->private_lock); | ||
| 67 | INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); | ||
| 68 | INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); | ||
| 69 | } | ||
| 70 | |||
| 55 | /** | 71 | /** |
| 56 | * init_gfs2_fs - Register GFS2 as a filesystem | 72 | * init_gfs2_fs - Register GFS2 as a filesystem |
| 57 | * | 73 | * |
| @@ -78,6 +94,14 @@ static int __init init_gfs2_fs(void) | |||
| 78 | if (!gfs2_glock_cachep) | 94 | if (!gfs2_glock_cachep) |
| 79 | goto fail; | 95 | goto fail; |
| 80 | 96 | ||
| 97 | gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock (aspace)", | ||
| 98 | sizeof(struct gfs2_glock) + | ||
| 99 | sizeof(struct address_space), | ||
| 100 | 0, 0, gfs2_init_gl_aspace_once); | ||
| 101 | |||
| 102 | if (!gfs2_glock_aspace_cachep) | ||
| 103 | goto fail; | ||
| 104 | |||
| 81 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", | 105 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", |
| 82 | sizeof(struct gfs2_inode), | 106 | sizeof(struct gfs2_inode), |
| 83 | 0, SLAB_RECLAIM_ACCOUNT| | 107 | 0, SLAB_RECLAIM_ACCOUNT| |
| @@ -144,6 +168,9 @@ fail: | |||
| 144 | if (gfs2_inode_cachep) | 168 | if (gfs2_inode_cachep) |
| 145 | kmem_cache_destroy(gfs2_inode_cachep); | 169 | kmem_cache_destroy(gfs2_inode_cachep); |
| 146 | 170 | ||
| 171 | if (gfs2_glock_aspace_cachep) | ||
| 172 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
| 173 | |||
| 147 | if (gfs2_glock_cachep) | 174 | if (gfs2_glock_cachep) |
| 148 | kmem_cache_destroy(gfs2_glock_cachep); | 175 | kmem_cache_destroy(gfs2_glock_cachep); |
| 149 | 176 | ||
| @@ -169,6 +196,7 @@ static void __exit exit_gfs2_fs(void) | |||
| 169 | kmem_cache_destroy(gfs2_rgrpd_cachep); | 196 | kmem_cache_destroy(gfs2_rgrpd_cachep); |
| 170 | kmem_cache_destroy(gfs2_bufdata_cachep); | 197 | kmem_cache_destroy(gfs2_bufdata_cachep); |
| 171 | kmem_cache_destroy(gfs2_inode_cachep); | 198 | kmem_cache_destroy(gfs2_inode_cachep); |
| 199 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
| 172 | kmem_cache_destroy(gfs2_glock_cachep); | 200 | kmem_cache_destroy(gfs2_glock_cachep); |
| 173 | 201 | ||
| 174 | gfs2_sys_uninit(); | 202 | gfs2_sys_uninit(); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 6f68a5f18eb8..0bb12c80937a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
| @@ -93,49 +93,13 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb | |||
| 93 | return err; | 93 | return err; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static const struct address_space_operations aspace_aops = { | 96 | const struct address_space_operations gfs2_meta_aops = { |
| 97 | .writepage = gfs2_aspace_writepage, | 97 | .writepage = gfs2_aspace_writepage, |
| 98 | .releasepage = gfs2_releasepage, | 98 | .releasepage = gfs2_releasepage, |
| 99 | .sync_page = block_sync_page, | 99 | .sync_page = block_sync_page, |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | /** | 102 | /** |
| 103 | * gfs2_aspace_get - Create and initialize a struct inode structure | ||
| 104 | * @sdp: the filesystem the aspace is in | ||
| 105 | * | ||
| 106 | * Right now a struct inode is just a struct inode. Maybe Linux | ||
| 107 | * will supply a more lightweight address space construct (that works) | ||
| 108 | * in the future. | ||
| 109 | * | ||
| 110 | * Make sure pages/buffers in this aspace aren't in high memory. | ||
| 111 | * | ||
| 112 | * Returns: the aspace | ||
| 113 | */ | ||
| 114 | |||
| 115 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp) | ||
| 116 | { | ||
| 117 | struct inode *aspace; | ||
| 118 | struct gfs2_inode *ip; | ||
| 119 | |||
| 120 | aspace = new_inode(sdp->sd_vfs); | ||
| 121 | if (aspace) { | ||
| 122 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); | ||
| 123 | aspace->i_mapping->a_ops = &aspace_aops; | ||
| 124 | aspace->i_size = MAX_LFS_FILESIZE; | ||
| 125 | ip = GFS2_I(aspace); | ||
| 126 | clear_bit(GIF_USER, &ip->i_flags); | ||
| 127 | insert_inode_hash(aspace); | ||
| 128 | } | ||
| 129 | return aspace; | ||
| 130 | } | ||
| 131 | |||
| 132 | void gfs2_aspace_put(struct inode *aspace) | ||
| 133 | { | ||
| 134 | remove_inode_hash(aspace); | ||
| 135 | iput(aspace); | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * gfs2_meta_sync - Sync all buffers associated with a glock | 103 | * gfs2_meta_sync - Sync all buffers associated with a glock |
| 140 | * @gl: The glock | 104 | * @gl: The glock |
| 141 | * | 105 | * |
| @@ -143,7 +107,7 @@ void gfs2_aspace_put(struct inode *aspace) | |||
| 143 | 107 | ||
| 144 | void gfs2_meta_sync(struct gfs2_glock *gl) | 108 | void gfs2_meta_sync(struct gfs2_glock *gl) |
| 145 | { | 109 | { |
| 146 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 110 | struct address_space *mapping = gfs2_glock2aspace(gl); |
| 147 | int error; | 111 | int error; |
| 148 | 112 | ||
| 149 | filemap_fdatawrite(mapping); | 113 | filemap_fdatawrite(mapping); |
| @@ -164,7 +128,7 @@ void gfs2_meta_sync(struct gfs2_glock *gl) | |||
| 164 | 128 | ||
| 165 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) | 129 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) |
| 166 | { | 130 | { |
| 167 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 131 | struct address_space *mapping = gfs2_glock2aspace(gl); |
| 168 | struct gfs2_sbd *sdp = gl->gl_sbd; | 132 | struct gfs2_sbd *sdp = gl->gl_sbd; |
| 169 | struct page *page; | 133 | struct page *page; |
| 170 | struct buffer_head *bh; | 134 | struct buffer_head *bh; |
| @@ -344,8 +308,10 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
| 344 | 308 | ||
| 345 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) | 309 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) |
| 346 | { | 310 | { |
| 347 | struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host); | 311 | struct address_space *mapping = bh->b_page->mapping; |
| 312 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); | ||
| 348 | struct gfs2_bufdata *bd = bh->b_private; | 313 | struct gfs2_bufdata *bd = bh->b_private; |
| 314 | |||
| 349 | if (test_clear_buffer_pinned(bh)) { | 315 | if (test_clear_buffer_pinned(bh)) { |
| 350 | list_del_init(&bd->bd_le.le_list); | 316 | list_del_init(&bd->bd_le.le_list); |
| 351 | if (meta) { | 317 | if (meta) { |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index de270c2f9b63..6a1d9ba16411 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
| @@ -37,8 +37,16 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, | |||
| 37 | 0, from_head - to_head); | 37 | 0, from_head - to_head); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp); | 40 | extern const struct address_space_operations gfs2_meta_aops; |
| 41 | void gfs2_aspace_put(struct inode *aspace); | 41 | |
| 42 | static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) | ||
| 43 | { | ||
| 44 | struct inode *inode = mapping->host; | ||
| 45 | if (mapping->a_ops == &gfs2_meta_aops) | ||
| 46 | return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; | ||
| 47 | else | ||
| 48 | return inode->i_sb->s_fs_info; | ||
| 49 | } | ||
| 42 | 50 | ||
| 43 | void gfs2_meta_sync(struct gfs2_glock *gl); | 51 | void gfs2_meta_sync(struct gfs2_glock *gl); |
| 44 | 52 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index b9dd3da22c0a..ad7bc2d25ac2 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -722,8 +722,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
| 722 | int ret = 0; | 722 | int ret = 0; |
| 723 | 723 | ||
| 724 | /* Check this is a "normal" inode, etc */ | 724 | /* Check this is a "normal" inode, etc */ |
| 725 | if (!test_bit(GIF_USER, &ip->i_flags) || | 725 | if (current->flags & PF_MEMALLOC) |
| 726 | (current->flags & PF_MEMALLOC)) | ||
| 727 | return 0; | 726 | return 0; |
| 728 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 727 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
| 729 | if (ret) | 728 | if (ret) |
| @@ -1194,7 +1193,7 @@ static void gfs2_drop_inode(struct inode *inode) | |||
| 1194 | { | 1193 | { |
| 1195 | struct gfs2_inode *ip = GFS2_I(inode); | 1194 | struct gfs2_inode *ip = GFS2_I(inode); |
| 1196 | 1195 | ||
| 1197 | if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) { | 1196 | if (inode->i_nlink) { |
| 1198 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | 1197 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
| 1199 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1198 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) |
| 1200 | clear_nlink(inode); | 1199 | clear_nlink(inode); |
| @@ -1212,18 +1211,12 @@ static void gfs2_clear_inode(struct inode *inode) | |||
| 1212 | { | 1211 | { |
| 1213 | struct gfs2_inode *ip = GFS2_I(inode); | 1212 | struct gfs2_inode *ip = GFS2_I(inode); |
| 1214 | 1213 | ||
| 1215 | /* This tells us its a "real" inode and not one which only | 1214 | ip->i_gl->gl_object = NULL; |
| 1216 | * serves to contain an address space (see rgrp.c, meta_io.c) | 1215 | gfs2_glock_put(ip->i_gl); |
| 1217 | * which therefore doesn't have its own glocks. | 1216 | ip->i_gl = NULL; |
| 1218 | */ | 1217 | if (ip->i_iopen_gh.gh_gl) { |
| 1219 | if (test_bit(GIF_USER, &ip->i_flags)) { | 1218 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
| 1220 | ip->i_gl->gl_object = NULL; | 1219 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
| 1221 | gfs2_glock_put(ip->i_gl); | ||
| 1222 | ip->i_gl = NULL; | ||
| 1223 | if (ip->i_iopen_gh.gh_gl) { | ||
| 1224 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
| 1225 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
| 1226 | } | ||
| 1227 | } | 1220 | } |
| 1228 | } | 1221 | } |
| 1229 | 1222 | ||
| @@ -1358,9 +1351,6 @@ static void gfs2_delete_inode(struct inode *inode) | |||
| 1358 | struct gfs2_holder gh; | 1351 | struct gfs2_holder gh; |
| 1359 | int error; | 1352 | int error; |
| 1360 | 1353 | ||
| 1361 | if (!test_bit(GIF_USER, &ip->i_flags)) | ||
| 1362 | goto out; | ||
| 1363 | |||
| 1364 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1354 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
| 1365 | if (unlikely(error)) { | 1355 | if (unlikely(error)) { |
| 1366 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1356 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index f6a7efa34eb9..226f2bfbf16a 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "util.h" | 21 | #include "util.h" |
| 22 | 22 | ||
| 23 | struct kmem_cache *gfs2_glock_cachep __read_mostly; | 23 | struct kmem_cache *gfs2_glock_cachep __read_mostly; |
| 24 | struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly; | ||
| 24 | struct kmem_cache *gfs2_inode_cachep __read_mostly; | 25 | struct kmem_cache *gfs2_inode_cachep __read_mostly; |
| 25 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; | 26 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; |
| 26 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; | 27 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; |
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 33e96b0ce9ab..b432e04600de 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h | |||
| @@ -145,6 +145,7 @@ gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__); | |||
| 145 | 145 | ||
| 146 | 146 | ||
| 147 | extern struct kmem_cache *gfs2_glock_cachep; | 147 | extern struct kmem_cache *gfs2_glock_cachep; |
| 148 | extern struct kmem_cache *gfs2_glock_aspace_cachep; | ||
| 148 | extern struct kmem_cache *gfs2_inode_cachep; | 149 | extern struct kmem_cache *gfs2_inode_cachep; |
| 149 | extern struct kmem_cache *gfs2_bufdata_cachep; | 150 | extern struct kmem_cache *gfs2_bufdata_cachep; |
| 150 | extern struct kmem_cache *gfs2_rgrpd_cachep; | 151 | extern struct kmem_cache *gfs2_rgrpd_cachep; |
