diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/bmap.c | 2 | ||||
-rw-r--r-- | fs/gfs2/file.c | 38 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 4 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 2 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 2 | ||||
-rw-r--r-- | fs/gfs2/lock_dlm.c | 11 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 14 | ||||
-rw-r--r-- | fs/gfs2/ops_inode.c | 9 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 8 | ||||
-rw-r--r-- | fs/gfs2/super.c | 1 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 21 |
12 files changed, 85 insertions, 29 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 6d47379e794b..583e823307ae 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -541,7 +541,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | |||
541 | *ptr++ = cpu_to_be64(bn++); | 541 | *ptr++ = cpu_to_be64(bn++); |
542 | break; | 542 | break; |
543 | } | 543 | } |
544 | } while (state != ALLOC_DATA); | 544 | } while ((state != ALLOC_DATA) || !dblock); |
545 | 545 | ||
546 | ip->i_height = height; | 546 | ip->i_height = height; |
547 | gfs2_add_inode_blocks(&ip->i_inode, alloced); | 547 | gfs2_add_inode_blocks(&ip->i_inode, alloced); |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 4eb308aa3234..a6abbae8a278 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -569,6 +569,40 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | /** | ||
573 | * gfs2_file_aio_write - Perform a write to a file | ||
574 | * @iocb: The io context | ||
575 | * @iov: The data to write | ||
576 | * @nr_segs: Number of @iov segments | ||
577 | * @pos: The file position | ||
578 | * | ||
579 | * We have to do a lock/unlock here to refresh the inode size for | ||
580 | * O_APPEND writes, otherwise we can land up writing at the wrong | ||
581 | * offset. There is still a race, but provided the app is using its | ||
582 | * own file locking, this will make O_APPEND work as expected. | ||
583 | * | ||
584 | */ | ||
585 | |||
586 | static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | ||
587 | unsigned long nr_segs, loff_t pos) | ||
588 | { | ||
589 | struct file *file = iocb->ki_filp; | ||
590 | |||
591 | if (file->f_flags & O_APPEND) { | ||
592 | struct dentry *dentry = file->f_dentry; | ||
593 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
594 | struct gfs2_holder gh; | ||
595 | int ret; | ||
596 | |||
597 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
598 | if (ret) | ||
599 | return ret; | ||
600 | gfs2_glock_dq_uninit(&gh); | ||
601 | } | ||
602 | |||
603 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
604 | } | ||
605 | |||
572 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM | 606 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM |
573 | 607 | ||
574 | /** | 608 | /** |
@@ -711,7 +745,7 @@ const struct file_operations gfs2_file_fops = { | |||
711 | .read = do_sync_read, | 745 | .read = do_sync_read, |
712 | .aio_read = generic_file_aio_read, | 746 | .aio_read = generic_file_aio_read, |
713 | .write = do_sync_write, | 747 | .write = do_sync_write, |
714 | .aio_write = generic_file_aio_write, | 748 | .aio_write = gfs2_file_aio_write, |
715 | .unlocked_ioctl = gfs2_ioctl, | 749 | .unlocked_ioctl = gfs2_ioctl, |
716 | .mmap = gfs2_mmap, | 750 | .mmap = gfs2_mmap, |
717 | .open = gfs2_open, | 751 | .open = gfs2_open, |
@@ -741,7 +775,7 @@ const struct file_operations gfs2_file_fops_nolock = { | |||
741 | .read = do_sync_read, | 775 | .read = do_sync_read, |
742 | .aio_read = generic_file_aio_read, | 776 | .aio_read = generic_file_aio_read, |
743 | .write = do_sync_write, | 777 | .write = do_sync_write, |
744 | .aio_write = generic_file_aio_write, | 778 | .aio_write = gfs2_file_aio_write, |
745 | .unlocked_ioctl = gfs2_ioctl, | 779 | .unlocked_ioctl = gfs2_ioctl, |
746 | .mmap = gfs2_mmap, | 780 | .mmap = gfs2_mmap, |
747 | .open = gfs2_open, | 781 | .open = gfs2_open, |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f455a03a09e2..f42663325931 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -769,6 +769,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
769 | if (!gl) | 769 | if (!gl) |
770 | return -ENOMEM; | 770 | return -ENOMEM; |
771 | 771 | ||
772 | atomic_inc(&sdp->sd_glock_disposal); | ||
772 | gl->gl_flags = 0; | 773 | gl->gl_flags = 0; |
773 | gl->gl_name = name; | 774 | gl->gl_name = name; |
774 | atomic_set(&gl->gl_ref, 1); | 775 | atomic_set(&gl->gl_ref, 1); |
@@ -1538,6 +1539,9 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | |||
1538 | up_write(&gfs2_umount_flush_sem); | 1539 | up_write(&gfs2_umount_flush_sem); |
1539 | msleep(10); | 1540 | msleep(10); |
1540 | } | 1541 | } |
1542 | flush_workqueue(glock_workqueue); | ||
1543 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); | ||
1544 | gfs2_dump_lockstate(sdp); | ||
1541 | } | 1545 | } |
1542 | 1546 | ||
1543 | void gfs2_glock_finish_truncate(struct gfs2_inode *ip) | 1547 | void gfs2_glock_finish_truncate(struct gfs2_inode *ip) |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 13f0bd228132..c0262faf4725 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -123,7 +123,7 @@ struct lm_lockops { | |||
123 | int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); | 123 | int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname); |
124 | void (*lm_unmount) (struct gfs2_sbd *sdp); | 124 | void (*lm_unmount) (struct gfs2_sbd *sdp); |
125 | void (*lm_withdraw) (struct gfs2_sbd *sdp); | 125 | void (*lm_withdraw) (struct gfs2_sbd *sdp); |
126 | void (*lm_put_lock) (struct kmem_cache *cachep, void *gl); | 126 | void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl); |
127 | unsigned int (*lm_lock) (struct gfs2_glock *gl, | 127 | unsigned int (*lm_lock) (struct gfs2_glock *gl, |
128 | unsigned int req_state, unsigned int flags); | 128 | unsigned int req_state, unsigned int flags); |
129 | void (*lm_cancel) (struct gfs2_glock *gl); | 129 | void (*lm_cancel) (struct gfs2_glock *gl); |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 4792200978c8..bc0ad158e6b4 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -544,6 +544,8 @@ struct gfs2_sbd { | |||
544 | struct gfs2_holder sd_live_gh; | 544 | struct gfs2_holder sd_live_gh; |
545 | struct gfs2_glock *sd_rename_gl; | 545 | struct gfs2_glock *sd_rename_gl; |
546 | struct gfs2_glock *sd_trans_gl; | 546 | struct gfs2_glock *sd_trans_gl; |
547 | wait_queue_head_t sd_glock_wait; | ||
548 | atomic_t sd_glock_disposal; | ||
547 | 549 | ||
548 | /* Inode Stuff */ | 550 | /* Inode Stuff */ |
549 | 551 | ||
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 46df988323bc..0e5e0e7022e5 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
@@ -21,6 +21,7 @@ static void gdlm_ast(void *arg) | |||
21 | { | 21 | { |
22 | struct gfs2_glock *gl = arg; | 22 | struct gfs2_glock *gl = arg; |
23 | unsigned ret = gl->gl_state; | 23 | unsigned ret = gl->gl_state; |
24 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
24 | 25 | ||
25 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); | 26 | BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); |
26 | 27 | ||
@@ -30,6 +31,8 @@ static void gdlm_ast(void *arg) | |||
30 | switch (gl->gl_lksb.sb_status) { | 31 | switch (gl->gl_lksb.sb_status) { |
31 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ | 32 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ |
32 | kmem_cache_free(gfs2_glock_cachep, gl); | 33 | kmem_cache_free(gfs2_glock_cachep, gl); |
34 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
35 | wake_up(&sdp->sd_glock_wait); | ||
33 | return; | 36 | return; |
34 | case -DLM_ECANCEL: /* Cancel while getting lock */ | 37 | case -DLM_ECANCEL: /* Cancel while getting lock */ |
35 | ret |= LM_OUT_CANCELED; | 38 | ret |= LM_OUT_CANCELED; |
@@ -164,14 +167,16 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl, | |||
164 | return LM_OUT_ASYNC; | 167 | return LM_OUT_ASYNC; |
165 | } | 168 | } |
166 | 169 | ||
167 | static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr) | 170 | static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl) |
168 | { | 171 | { |
169 | struct gfs2_glock *gl = ptr; | 172 | struct gfs2_sbd *sdp = gl->gl_sbd; |
170 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; | 173 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
171 | int error; | 174 | int error; |
172 | 175 | ||
173 | if (gl->gl_lksb.sb_lkid == 0) { | 176 | if (gl->gl_lksb.sb_lkid == 0) { |
174 | kmem_cache_free(cachep, gl); | 177 | kmem_cache_free(cachep, gl); |
178 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
179 | wake_up(&sdp->sd_glock_wait); | ||
175 | return; | 180 | return; |
176 | } | 181 | } |
177 | 182 | ||
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index cb8d7a93d5ec..6f68a5f18eb8 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -121,7 +121,7 @@ struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp) | |||
121 | if (aspace) { | 121 | if (aspace) { |
122 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); | 122 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); |
123 | aspace->i_mapping->a_ops = &aspace_aops; | 123 | aspace->i_mapping->a_ops = &aspace_aops; |
124 | aspace->i_size = ~0ULL; | 124 | aspace->i_size = MAX_LFS_FILESIZE; |
125 | ip = GFS2_I(aspace); | 125 | ip = GFS2_I(aspace); |
126 | clear_bit(GIF_USER, &ip->i_flags); | 126 | clear_bit(GIF_USER, &ip->i_flags); |
127 | insert_inode_hash(aspace); | 127 | insert_inode_hash(aspace); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index edfee24f3636..a86ed6381566 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -82,6 +82,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
82 | 82 | ||
83 | gfs2_tune_init(&sdp->sd_tune); | 83 | gfs2_tune_init(&sdp->sd_tune); |
84 | 84 | ||
85 | init_waitqueue_head(&sdp->sd_glock_wait); | ||
86 | atomic_set(&sdp->sd_glock_disposal, 0); | ||
85 | spin_lock_init(&sdp->sd_statfs_spin); | 87 | spin_lock_init(&sdp->sd_statfs_spin); |
86 | 88 | ||
87 | spin_lock_init(&sdp->sd_rindex_spin); | 89 | spin_lock_init(&sdp->sd_rindex_spin); |
@@ -723,7 +725,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
723 | goto fail; | 725 | goto fail; |
724 | } | 726 | } |
725 | 727 | ||
726 | error = -EINVAL; | 728 | error = -EUSERS; |
727 | if (!gfs2_jindex_size(sdp)) { | 729 | if (!gfs2_jindex_size(sdp)) { |
728 | fs_err(sdp, "no journals!\n"); | 730 | fs_err(sdp, "no journals!\n"); |
729 | goto fail_jindex; | 731 | goto fail_jindex; |
@@ -983,9 +985,17 @@ static const match_table_t nolock_tokens = { | |||
983 | { Opt_err, NULL }, | 985 | { Opt_err, NULL }, |
984 | }; | 986 | }; |
985 | 987 | ||
988 | static void nolock_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl) | ||
989 | { | ||
990 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
991 | kmem_cache_free(cachep, gl); | ||
992 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | ||
993 | wake_up(&sdp->sd_glock_wait); | ||
994 | } | ||
995 | |||
986 | static const struct lm_lockops nolock_ops = { | 996 | static const struct lm_lockops nolock_ops = { |
987 | .lm_proto_name = "lock_nolock", | 997 | .lm_proto_name = "lock_nolock", |
988 | .lm_put_lock = kmem_cache_free, | 998 | .lm_put_lock = nolock_put_lock, |
989 | .lm_tokens = &nolock_tokens, | 999 | .lm_tokens = &nolock_tokens, |
990 | }; | 1000 | }; |
991 | 1001 | ||
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 247436c10deb..84350e1be66d 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -748,7 +748,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
748 | struct gfs2_rgrpd *nrgd; | 748 | struct gfs2_rgrpd *nrgd; |
749 | unsigned int num_gh; | 749 | unsigned int num_gh; |
750 | int dir_rename = 0; | 750 | int dir_rename = 0; |
751 | int alloc_required; | 751 | int alloc_required = 0; |
752 | unsigned int x; | 752 | unsigned int x; |
753 | int error; | 753 | int error; |
754 | 754 | ||
@@ -867,7 +867,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
867 | goto out_gunlock; | 867 | goto out_gunlock; |
868 | } | 868 | } |
869 | 869 | ||
870 | alloc_required = error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | 870 | if (nip == NULL) |
871 | alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | ||
872 | error = alloc_required; | ||
871 | if (error < 0) | 873 | if (error < 0) |
872 | goto out_gunlock; | 874 | goto out_gunlock; |
873 | error = 0; | 875 | error = 0; |
@@ -1086,7 +1088,8 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
1086 | error = vfs_follow_link(nd, buf); | 1088 | error = vfs_follow_link(nd, buf); |
1087 | if (buf != array) | 1089 | if (buf != array) |
1088 | kfree(buf); | 1090 | kfree(buf); |
1089 | } | 1091 | } else |
1092 | path_put(&nd->path); | ||
1090 | 1093 | ||
1091 | return ERR_PTR(error); | 1094 | return ERR_PTR(error); |
1092 | } | 1095 | } |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 0608f490c295..503b842f3ba2 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -591,11 +591,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
591 | u64 rgrp_count = ip->i_disksize; | 591 | u64 rgrp_count = ip->i_disksize; |
592 | int error; | 592 | int error; |
593 | 593 | ||
594 | if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) { | 594 | do_div(rgrp_count, sizeof(struct gfs2_rindex)); |
595 | gfs2_consist_inode(ip); | ||
596 | return -EIO; | ||
597 | } | ||
598 | |||
599 | clear_rgrpdi(sdp); | 595 | clear_rgrpdi(sdp); |
600 | 596 | ||
601 | file_ra_state_init(&ra_state, inode->i_mapping); | 597 | file_ra_state_init(&ra_state, inode->i_mapping); |
@@ -915,7 +911,7 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | |||
915 | struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) | 911 | struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) |
916 | { | 912 | { |
917 | BUG_ON(ip->i_alloc != NULL); | 913 | BUG_ON(ip->i_alloc != NULL); |
918 | ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_KERNEL); | 914 | ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_NOFS); |
919 | return ip->i_alloc; | 915 | return ip->i_alloc; |
920 | } | 916 | } |
921 | 917 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index c282ad41f3d1..b9dd3da22c0a 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
22 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
23 | #include <linux/time.h> | 23 | #include <linux/time.h> |
24 | #include <linux/wait.h> | ||
24 | 25 | ||
25 | #include "gfs2.h" | 26 | #include "gfs2.h" |
26 | #include "incore.h" | 27 | #include "incore.h" |
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 8a04108e0c22..c2ebdf2c01d4 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -1296,6 +1296,7 @@ fail: | |||
1296 | 1296 | ||
1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | 1297 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) |
1298 | { | 1298 | { |
1299 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1299 | struct gfs2_ea_location el; | 1300 | struct gfs2_ea_location el; |
1300 | struct buffer_head *dibh; | 1301 | struct buffer_head *dibh; |
1301 | int error; | 1302 | int error; |
@@ -1305,16 +1306,17 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | |||
1305 | return error; | 1306 | return error; |
1306 | 1307 | ||
1307 | if (GFS2_EA_IS_STUFFED(el.el_ea)) { | 1308 | if (GFS2_EA_IS_STUFFED(el.el_ea)) { |
1308 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0); | 1309 | error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0); |
1309 | if (error) | 1310 | if (error == 0) { |
1310 | return error; | 1311 | gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1); |
1311 | 1312 | memcpy(GFS2_EA2DATA(el.el_ea), data, | |
1312 | gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1); | 1313 | GFS2_EA_DATA_LEN(el.el_ea)); |
1313 | memcpy(GFS2_EA2DATA(el.el_ea), data, | 1314 | } |
1314 | GFS2_EA_DATA_LEN(el.el_ea)); | 1315 | } else { |
1315 | } else | ||
1316 | error = ea_acl_chmod_unstuffed(ip, el.el_ea, data); | 1316 | error = ea_acl_chmod_unstuffed(ip, el.el_ea, data); |
1317 | } | ||
1317 | 1318 | ||
1319 | brelse(el.el_bh); | ||
1318 | if (error) | 1320 | if (error) |
1319 | return error; | 1321 | return error; |
1320 | 1322 | ||
@@ -1327,8 +1329,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | |||
1327 | brelse(dibh); | 1329 | brelse(dibh); |
1328 | } | 1330 | } |
1329 | 1331 | ||
1330 | gfs2_trans_end(GFS2_SB(&ip->i_inode)); | 1332 | gfs2_trans_end(sdp); |
1331 | |||
1332 | return error; | 1333 | return error; |
1333 | } | 1334 | } |
1334 | 1335 | ||