diff options
Diffstat (limited to 'fs/gfs2/ops_fstype.c')
| -rw-r--r-- | fs/gfs2/ops_fstype.c | 186 | 
1 files changed, 62 insertions, 124 deletions
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 19ff5e8c285..bc564c0d6d1 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -7,6 +7,8 @@   * of the GNU General Public License version 2.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/spinlock.h> @@ -36,6 +38,7 @@  #include "log.h"  #include "quota.h"  #include "dir.h" +#include "meta_io.h"  #include "trace_gfs2.h"  #define DO 0 @@ -51,7 +54,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt)  {  	spin_lock_init(>->gt_spin); -	gt->gt_quota_simul_sync = 64;  	gt->gt_quota_warn_period = 10;  	gt->gt_quota_scale_num = 1;  	gt->gt_quota_scale_den = 1; @@ -63,6 +65,7 @@ static void gfs2_tune_init(struct gfs2_tune *gt)  static struct gfs2_sbd *init_sbd(struct super_block *sb)  {  	struct gfs2_sbd *sdp; +	struct address_space *mapping;  	sdp = kzalloc(sizeof(struct gfs2_sbd), GFP_KERNEL);  	if (!sdp) @@ -91,18 +94,30 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)  	INIT_LIST_HEAD(&sdp->sd_jindex_list);  	spin_lock_init(&sdp->sd_jindex_spin);  	mutex_init(&sdp->sd_jindex_mutex); +	init_completion(&sdp->sd_journal_ready);  	INIT_LIST_HEAD(&sdp->sd_quota_list);  	mutex_init(&sdp->sd_quota_mutex); +	mutex_init(&sdp->sd_quota_sync_mutex);  	init_waitqueue_head(&sdp->sd_quota_wait);  	INIT_LIST_HEAD(&sdp->sd_trunc_list);  	spin_lock_init(&sdp->sd_trunc_lock); +	spin_lock_init(&sdp->sd_bitmap_lock); + +	mapping = &sdp->sd_aspace; + +	address_space_init_once(mapping); +	mapping->a_ops = &gfs2_rgrp_aops; +	mapping->host = sb->s_bdev->bd_inode; +	mapping->flags = 0; +	mapping_set_gfp_mask(mapping, GFP_NOFS); +	mapping->private_data = NULL; +	mapping->backing_dev_info = sb->s_bdi; +	mapping->writeback_index = 0;  	spin_lock_init(&sdp->sd_log_lock);  	atomic_set(&sdp->sd_log_pinned, 0); -	INIT_LIST_HEAD(&sdp->sd_log_le_buf);  	INIT_LIST_HEAD(&sdp->sd_log_le_revoke); -	INIT_LIST_HEAD(&sdp->sd_log_le_databuf);  	INIT_LIST_HEAD(&sdp->sd_log_le_ordered);  	spin_lock_init(&sdp->sd_ordered_lock); @@ -115,8 +130,10 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)  	init_rwsem(&sdp->sd_log_flush_lock);  	atomic_set(&sdp->sd_log_in_flight, 0);  	init_waitqueue_head(&sdp->sd_log_flush_wait); - -	INIT_LIST_HEAD(&sdp->sd_revoke_list); +	init_waitqueue_head(&sdp->sd_log_frozen_wait); +	atomic_set(&sdp->sd_log_freeze, 0); +	atomic_set(&sdp->sd_frozen_root, 0); +	init_waitqueue_head(&sdp->sd_frozen_root_wait);  	return sdp;  } @@ -140,7 +157,7 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)  	if (sb->sb_magic != GFS2_MAGIC ||  	    sb->sb_type != GFS2_METATYPE_SB) {  		if (!silent) -			printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); +			pr_warn("not a GFS2 filesystem\n");  		return -EINVAL;  	} @@ -162,7 +179,7 @@ static void end_bio_io_page(struct bio *bio, int error)  	if (!error)  		SetPageUptodate(page);  	else -		printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); +		pr_warn("error %d reading superblock\n", error);  	unlock_page(page);  } @@ -217,14 +234,14 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)  	page = alloc_page(GFP_NOFS);  	if (unlikely(!page)) -		return -ENOBUFS; +		return -ENOMEM;  	ClearPageUptodate(page);  	ClearPageDirty(page);  	lock_page(page);  	bio = bio_alloc(GFP_NOFS, 1); -	bio->bi_sector = sector * (sb->s_blocksize >> 9); +	bio->bi_iter.bi_sector = sector * (sb->s_blocksize >> 9);  	bio->bi_bdev = sb->s_bdev;  	bio_add_page(bio, page, PAGE_SIZE, 0); @@ -407,8 +424,8 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh,  		goto fail_live;  	} -	error = gfs2_glock_get(sdp, GFS2_TRANS_LOCK, &gfs2_trans_glops, -			       CREATE, &sdp->sd_trans_gl); +	error = gfs2_glock_get(sdp, GFS2_FREEZE_LOCK, &gfs2_freeze_glops, +			       CREATE, &sdp->sd_freeze_gl);  	if (error) {  		fs_err(sdp, "can't create transaction glock: %d\n", error);  		goto fail_rename; @@ -417,7 +434,7 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh,  	return 0;  fail_trans: -	gfs2_glock_put(sdp->sd_trans_gl); +	gfs2_glock_put(sdp->sd_freeze_gl);  fail_rename:  	gfs2_glock_put(sdp->sd_rename_gl);  fail_live: @@ -505,67 +522,6 @@ out:  	return ret;  } -/** - * map_journal_extents - create a reusable "extent" mapping from all logical - * blocks to all physical blocks for the given journal.  This will save - * us time when writing journal blocks.  Most journals will have only one - * extent that maps all their logical blocks.  That's because gfs2.mkfs - * arranges the journal blocks sequentially to maximize performance. - * So the extent would map the first block for the entire file length. - * However, gfs2_jadd can happen while file activity is happening, so - * those journals may not be sequential.  Less likely is the case where - * the users created their own journals by mounting the metafs and - * laying it out.  But it's still possible.  These journals might have - * several extents. - * - * TODO: This should be done in bigger chunks rather than one block at a time, - *       but since it's only done at mount time, I'm not worried about the - *       time it takes. - */ -static int map_journal_extents(struct gfs2_sbd *sdp) -{ -	struct gfs2_jdesc *jd = sdp->sd_jdesc; -	unsigned int lb; -	u64 db, prev_db; /* logical block, disk block, prev disk block */ -	struct gfs2_inode *ip = GFS2_I(jd->jd_inode); -	struct gfs2_journal_extent *jext = NULL; -	struct buffer_head bh; -	int rc = 0; - -	prev_db = 0; - -	for (lb = 0; lb < i_size_read(jd->jd_inode) >> sdp->sd_sb.sb_bsize_shift; lb++) { -		bh.b_state = 0; -		bh.b_blocknr = 0; -		bh.b_size = 1 << ip->i_inode.i_blkbits; -		rc = gfs2_block_map(jd->jd_inode, lb, &bh, 0); -		db = bh.b_blocknr; -		if (rc || !db) { -			printk(KERN_INFO "GFS2 journal mapping error %d: lb=" -			       "%u db=%llu\n", rc, lb, (unsigned long long)db); -			break; -		} -		if (!prev_db || db != prev_db + 1) { -			jext = kzalloc(sizeof(struct gfs2_journal_extent), -				       GFP_KERNEL); -			if (!jext) { -				printk(KERN_INFO "GFS2 error: out of memory " -				       "mapping journal extents.\n"); -				rc = -ENOMEM; -				break; -			} -			jext->dblock = db; -			jext->lblock = lb; -			jext->blocks = 1; -			list_add_tail(&jext->extent_list, &jd->extent_list); -		} else { -			jext->blocks++; -		} -		prev_db = db; -	} -	return rc; -} -  static void gfs2_others_may_mount(struct gfs2_sbd *sdp)  {  	char *message = "FIRSTMOUNT=Done"; @@ -624,6 +580,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)  			break;  		INIT_LIST_HEAD(&jd->extent_list); +		INIT_LIST_HEAD(&jd->jd_revoke_list); +  		INIT_WORK(&jd->jd_work, gfs2_recover_func);  		jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);  		if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { @@ -767,7 +725,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)  		atomic_set(&sdp->sd_log_thresh2, 4*sdp->sd_jdesc->jd_blocks/5);  		/* Map the extents for this journal's blocks */ -		map_journal_extents(sdp); +		gfs2_map_journal_extents(sdp, sdp->sd_jdesc);  	}  	trace_gfs2_log_blocks(sdp, atomic_read(&sdp->sd_log_blks_free)); @@ -802,7 +760,15 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)  	set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags);  	gfs2_glock_dq_uninit(&ji_gh);  	jindex = 0; - +	if (!sdp->sd_args.ar_spectator) { +		error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, +					   &sdp->sd_thaw_gh); +		if (error) { +			fs_err(sdp, "can't acquire freeze glock: %d\n", error); +			goto fail_jinode_gh; +		} +	} +	gfs2_glock_dq_uninit(&sdp->sd_thaw_gh);  	return 0;  fail_jinode_gh: @@ -831,6 +797,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)  		goto fail_qinode;  	error = init_journal(sdp, undo); +	complete_all(&sdp->sd_journal_ready);  	if (error)  		goto fail; @@ -956,40 +923,6 @@ fail:  	return error;  } -static int init_threads(struct gfs2_sbd *sdp, int undo) -{ -	struct task_struct *p; -	int error = 0; - -	if (undo) -		goto fail_quotad; - -	p = kthread_run(gfs2_logd, sdp, "gfs2_logd"); -	if (IS_ERR(p)) { -		error = PTR_ERR(p); -		fs_err(sdp, "can't start logd thread: %d\n", error); -		return error; -	} -	sdp->sd_logd_process = p; - -	p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad"); -	if (IS_ERR(p)) { -		error = PTR_ERR(p); -		fs_err(sdp, "can't start quotad thread: %d\n", error); -		goto fail; -	} -	sdp->sd_quotad_process = p; - -	return 0; - - -fail_quotad: -	kthread_stop(sdp->sd_quotad_process); -fail: -	kthread_stop(sdp->sd_logd_process); -	return error; -} -  static const match_table_t nolock_tokens = {  	{ Opt_jid, "jid=%d\n", },  	{ Opt_err, NULL }, @@ -1028,7 +961,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)  		lm = &gfs2_dlm_ops;  #endif  	} else { -		printk(KERN_INFO "GFS2: can't find protocol %s\n", proto); +		pr_info("can't find protocol %s\n", proto);  		return -ENOENT;  	} @@ -1135,7 +1068,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent  	sdp = init_sbd(sb);  	if (!sdp) { -		printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); +		pr_warn("can't alloc struct gfs2_sbd\n");  		return -ENOMEM;  	}  	sdp->sd_args = *args; @@ -1254,15 +1187,11 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent  		goto fail_per_node;  	} -	error = init_threads(sdp, DO); -	if (error) -		goto fail_per_node; -  	if (!(sb->s_flags & MS_RDONLY)) {  		error = gfs2_make_fs_rw(sdp);  		if (error) {  			fs_err(sdp, "can't make FS RW: %d\n", error); -			goto fail_threads; +			goto fail_per_node;  		}  	} @@ -1270,8 +1199,6 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent  	gfs2_online_uevent(sdp);  	return 0; -fail_threads: -	init_threads(sdp, UNDO);  fail_per_node:  	init_per_node(sdp, UNDO);  fail_inodes: @@ -1287,6 +1214,7 @@ fail_sb:  fail_locking:  	init_locking(sdp, &mount_gh, UNDO);  fail_lm: +	complete_all(&sdp->sd_journal_ready);  	gfs2_gl_hash_clear(sdp);  	gfs2_lm_unmount(sdp);  fail_debug: @@ -1366,8 +1294,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,  	if (IS_ERR(s))  		goto error_bdev; -	if (s->s_root) +	if (s->s_root) { +		/* +		 * s_umount nests inside bd_mutex during +		 * __invalidate_device().  blkdev_put() acquires +		 * bd_mutex and can't be called under s_umount.  Drop +		 * s_umount temporarily.  This is safe as we're +		 * holding an active reference. +		 */ +		up_write(&s->s_umount);  		blkdev_put(bdev, mode); +		down_write(&s->s_umount); +	}  	memset(&args, 0, sizeof(args));  	args.ar_quota = GFS2_QUOTA_DEFAULT; @@ -1379,7 +1317,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,  	error = gfs2_mount_args(&args, data);  	if (error) { -		printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); +		pr_warn("can't parse mount arguments\n");  		goto error_super;  	} @@ -1429,15 +1367,15 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,  	error = kern_path(dev_name, LOOKUP_FOLLOW, &path);  	if (error) { -		printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", -		       dev_name, error); +		pr_warn("path_lookup on %s returned error %d\n", +			dev_name, error);  		return ERR_PTR(error);  	}  	s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,  		 path.dentry->d_inode->i_sb->s_bdev);  	path_put(&path);  	if (IS_ERR(s)) { -		printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); +		pr_warn("gfs2 mount does not exist\n");  		return ERR_CAST(s);  	}  	if ((flags ^ s->s_flags) & MS_RDONLY) { @@ -1457,7 +1395,7 @@ static void gfs2_kill_sb(struct super_block *sb)  		return;  	} -	gfs2_meta_syncfs(sdp); +	gfs2_log_flush(sdp, NULL, SYNC_FLUSH);  	dput(sdp->sd_root_dir);  	dput(sdp->sd_master_dir);  	sdp->sd_root_dir = NULL;  | 
