⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved. * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU General Public License version 2. */#include <linux/sched.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/completion.h>#include <linux/buffer_head.h>#include <linux/gfs2_ondisk.h>#include <linux/lm_interface.h>#include "gfs2.h"#include "incore.h"#include "inode.h"#include "glock.h"#include "log.h"#include "lops.h"#include "meta_io.h"#include "recovery.h"#include "rgrp.h"#include "trans.h"#include "util.h"/** * gfs2_pin - Pin a buffer in memory * @sdp: The superblock * @bh: The buffer to be pinned * * The log lock must be held when calling this function */static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh){	struct gfs2_bufdata *bd;	gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags));	clear_buffer_dirty(bh);	if (test_set_buffer_pinned(bh))		gfs2_assert_withdraw(sdp, 0);	if (!buffer_uptodate(bh))		gfs2_io_error_bh(sdp, bh);	bd = bh->b_private;	/* If this buffer is in the AIL and it has already been written	 * to in-place disk block, remove it from the AIL.	 */	if (bd->bd_ail)		list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list);	get_bh(bh);}/** * gfs2_unpin - Unpin a buffer * @sdp: the filesystem the buffer belongs to * @bh: The buffer to unpin * @ai: * */static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,		       struct gfs2_ail *ai){	struct gfs2_bufdata *bd = bh->b_private;	gfs2_assert_withdraw(sdp, buffer_uptodate(bh));	if (!buffer_pinned(bh))		gfs2_assert_withdraw(sdp, 0);	lock_buffer(bh);	mark_buffer_dirty(bh);	clear_buffer_pinned(bh);	gfs2_log_lock(sdp);	if (bd->bd_ail) {		list_del(&bd->bd_ail_st_list);		brelse(bh);	} else {		struct gfs2_glock *gl = bd->bd_gl;		list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list);		atomic_inc(&gl->gl_ail_count);	}	bd->bd_ail = ai;	list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);	gfs2_log_unlock(sdp);	unlock_buffer(bh);}static inline struct gfs2_log_descriptor *bh_log_desc(struct buffer_head *bh){	return (struct gfs2_log_descriptor *)bh->b_data;}static inline __be64 *bh_log_ptr(struct buffer_head *bh){	struct gfs2_log_descriptor *ld = bh_log_desc(bh);	return (__force __be64 *)(ld + 1);}static inline __be64 *bh_ptr_end(struct buffer_head *bh){	return (__force __be64 *)(bh->b_data + bh->b_size);}static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type){	struct buffer_head *bh = gfs2_log_get_buf(sdp);	struct gfs2_log_descriptor *ld = bh_log_desc(bh);	ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);	ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);	ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);	ld->ld_type = cpu_to_be32(ld_type);	ld->ld_length = 0;	ld->ld_data1 = 0;	ld->ld_data2 = 0;	memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));	return bh;}static void __glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le){	struct gfs2_glock *gl;	struct gfs2_trans *tr = current->journal_info;	tr->tr_touched = 1;	gl = container_of(le, struct gfs2_glock, gl_le);	if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))		return;	if (!list_empty(&le->le_list))		return;	gfs2_glock_hold(gl);	set_bit(GLF_DIRTY, &gl->gl_flags);	sdp->sd_log_num_gl++;	list_add(&le->le_list, &sdp->sd_log_le_gl);}static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le){	gfs2_log_lock(sdp);	__glock_lo_add(sdp, le);	gfs2_log_unlock(sdp);}static void glock_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai){	struct list_head *head = &sdp->sd_log_le_gl;	struct gfs2_glock *gl;	while (!list_empty(head)) {		gl = list_entry(head->next, struct gfs2_glock, gl_le.le_list);		list_del_init(&gl->gl_le.le_list);		sdp->sd_log_num_gl--;		gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl));		gfs2_glock_put(gl);	}	gfs2_assert_warn(sdp, !sdp->sd_log_num_gl);}static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le){	struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);	struct gfs2_trans *tr;	lock_buffer(bd->bd_bh);	gfs2_log_lock(sdp);	if (!list_empty(&bd->bd_list_tr))		goto out;	tr = current->journal_info;	tr->tr_touched = 1;	tr->tr_num_buf++;	list_add(&bd->bd_list_tr, &tr->tr_list_buf);	if (!list_empty(&le->le_list))		goto out;	__glock_lo_add(sdp, &bd->bd_gl->gl_le);	gfs2_meta_check(sdp, bd->bd_bh);	gfs2_pin(sdp, bd->bd_bh);	sdp->sd_log_num_buf++;	list_add(&le->le_list, &sdp->sd_log_le_buf);	tr->tr_num_buf_new++;out:	gfs2_log_unlock(sdp);	unlock_buffer(bd->bd_bh);}static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr){	struct list_head *head = &tr->tr_list_buf;	struct gfs2_bufdata *bd;	gfs2_log_lock(sdp);	while (!list_empty(head)) {		bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);		list_del_init(&bd->bd_list_tr);		tr->tr_num_buf--;	}	gfs2_log_unlock(sdp);	gfs2_assert_warn(sdp, !tr->tr_num_buf);}static void buf_lo_before_commit(struct gfs2_sbd *sdp){	struct buffer_head *bh;	struct gfs2_log_descriptor *ld;	struct gfs2_bufdata *bd1 = NULL, *bd2;	unsigned int total;	unsigned int limit;	unsigned int num;	unsigned n;	__be64 *ptr;	limit = buf_limit(sdp);	/* for 4k blocks, limit = 503 */	gfs2_log_lock(sdp);	total = sdp->sd_log_num_buf;	bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);	while(total) {		num = total;		if (total > limit)			num = limit;		gfs2_log_unlock(sdp);		bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA);		gfs2_log_lock(sdp);		ld = bh_log_desc(bh);		ptr = bh_log_ptr(bh);		ld->ld_length = cpu_to_be32(num + 1);		ld->ld_data1 = cpu_to_be32(num);		n = 0;		list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf,					     bd_le.le_list) {			*ptr++ = cpu_to_be64(bd1->bd_bh->b_blocknr);			if (++n >= num)				break;		}		gfs2_log_unlock(sdp);		submit_bh(WRITE, bh);		gfs2_log_lock(sdp);		n = 0;		list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf,					     bd_le.le_list) {			get_bh(bd2->bd_bh);			gfs2_log_unlock(sdp);			lock_buffer(bd2->bd_bh);			bh = gfs2_log_fake_buf(sdp, bd2->bd_bh);			submit_bh(WRITE, bh);			gfs2_log_lock(sdp);			if (++n >= num)				break;		}		BUG_ON(total < num);		total -= num;	}	gfs2_log_unlock(sdp);}static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai){	struct list_head *head = &sdp->sd_log_le_buf;	struct gfs2_bufdata *bd;	while (!list_empty(head)) {		bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);		list_del_init(&bd->bd_le.le_list);		sdp->sd_log_num_buf--;		gfs2_unpin(sdp, bd->bd_bh, ai);	}	gfs2_assert_warn(sdp, !sdp->sd_log_num_buf);}static void buf_lo_before_scan(struct gfs2_jdesc *jd,			       struct gfs2_log_header_host *head, int pass){	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);	if (pass != 0)		return;	sdp->sd_found_blocks = 0;	sdp->sd_replayed_blocks = 0;}static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,				struct gfs2_log_descriptor *ld, __be64 *ptr,				int pass){	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);	struct gfs2_glock *gl = ip->i_gl;	unsigned int blks = be32_to_cpu(ld->ld_data1);	struct buffer_head *bh_log, *bh_ip;	u64 blkno;	int error = 0;	if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_METADATA)		return 0;	gfs2_replay_incr_blk(sdp, &start);	for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {		blkno = be64_to_cpu(*ptr++);		sdp->sd_found_blocks++;		if (gfs2_revoke_check(sdp, blkno, start))			continue;		error = gfs2_replay_read_block(jd, start, &bh_log);		if (error)			return error;		bh_ip = gfs2_meta_new(gl, blkno);		memcpy(bh_ip->b_data, bh_log->b_data, bh_log->b_size);		if (gfs2_meta_check(sdp, bh_ip))			error = -EIO;		else			mark_buffer_dirty(bh_ip);		brelse(bh_log);		brelse(bh_ip);		if (error)			break;		sdp->sd_replayed_blocks++;	}	return error;}static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass){	struct gfs2_inode *ip = GFS2_I(jd->jd_inode);	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);	if (error) {		gfs2_meta_sync(ip->i_gl);		return;	}	if (pass != 1)		return;	gfs2_meta_sync(ip->i_gl);	fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",	        jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);}static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le){	struct gfs2_trans *tr;	tr = current->journal_info;	tr->tr_touched = 1;	tr->tr_num_revoke++;	sdp->sd_log_num_revoke++;	list_add(&le->le_list, &sdp->sd_log_le_revoke);}static void revoke_lo_before_commit(struct gfs2_sbd *sdp){	struct gfs2_log_descriptor *ld;	struct gfs2_meta_header *mh;	struct buffer_head *bh;	unsigned int offset;	struct list_head *head = &sdp->sd_log_le_revoke;	struct gfs2_bufdata *bd;	if (!sdp->sd_log_num_revoke)		return;	bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE);	ld = bh_log_desc(bh);	ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke,						    sizeof(u64)));	ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke);	offset = sizeof(struct gfs2_log_descriptor);	while (!list_empty(head)) {		bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);		list_del_init(&bd->bd_le.le_list);		sdp->sd_log_num_revoke--;		if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) {			submit_bh(WRITE, bh);			bh = gfs2_log_get_buf(sdp);			mh = (struct gfs2_meta_header *)bh->b_data;			mh->mh_magic = cpu_to_be32(GFS2_MAGIC);			mh->mh_type = cpu_to_be32(GFS2_METATYPE_LB);			mh->mh_format = cpu_to_be32(GFS2_FORMAT_LB);			offset = sizeof(struct gfs2_meta_header);		}		*(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno);		kmem_cache_free(gfs2_bufdata_cachep, bd);		offset += sizeof(u64);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -