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

📄 jfs_imap.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *   Copyright (C) International Business Machines Corp., 2000-2003 * *   This program is free software;  you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or  *   (at your option) any later version. *  *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY;  without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See *   the GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program;  if not, write to the Free Software  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *	jfs_imap.c: inode allocation map manager * * Serialization: *   Each AG has a simple lock which is used to control the serialization of *	the AG level lists.  This lock should be taken first whenever an AG *	level list will be modified or accessed. * *   Each IAG is locked by obtaining the buffer for the IAG page. * *   There is also a inode lock for the inode map inode.  A read lock needs to *	be taken whenever an IAG is read from the map or the global level *	information is read.  A write lock needs to be taken whenever the global *	level information is modified or an atomic operation needs to be used. * *	If more than one IAG is read at one time, the read lock may not *	be given up until all of the IAG's are read.  Otherwise, a deadlock *	may occur when trying to obtain the read lock while another thread *	holding the read lock is waiting on the IAG already being held. * *   The control page of the inode map is read into memory by diMount(). *	Thereafter it should only be modified in memory and then it will be *	written out when the filesystem is unmounted by diUnmount(). */#include <linux/fs.h>#include <linux/locks.h>#include "jfs_incore.h"#include "jfs_filsys.h"#include "jfs_dinode.h"#include "jfs_dmap.h"#include "jfs_imap.h"#include "jfs_metapage.h"#include "jfs_superblock.h"#include "jfs_debug.h"/* * imap locks *//* iag free list lock */#define IAGFREE_LOCK_INIT(imap)		init_MUTEX(&imap->im_freelock)#define IAGFREE_LOCK(imap)		down(&imap->im_freelock)#define IAGFREE_UNLOCK(imap)		up(&imap->im_freelock)/* per ag iag list locks */#define AG_LOCK_INIT(imap,index)	init_MUTEX(&(imap->im_aglock[index]))#define AG_LOCK(imap,agno)		down(&imap->im_aglock[agno])#define AG_UNLOCK(imap,agno)		up(&imap->im_aglock[agno])/* * external references */extern struct address_space_operations jfs_aops;/* * forward references */static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);static int diAllocAny(struct inomap *, int, boolean_t, struct inode *);static int diAllocBit(struct inomap *, struct iag *, int);static int diAllocExt(struct inomap *, int, struct inode *);static int diAllocIno(struct inomap *, int, struct inode *);static int diFindFree(u32, int);static int diNewExt(struct inomap *, struct iag *, int);static int diNewIAG(struct inomap *, int *, int, struct metapage **);static void duplicateIXtree(struct super_block *, s64, int, s64 *);static int diIAGRead(struct inomap * imap, int, struct metapage **);static int copy_from_dinode(struct dinode *, struct inode *);static void copy_to_dinode(struct dinode *, struct inode *);/* *	debug code for double-checking inode map *//* #define	_JFS_DEBUG_IMAP	1 */#ifdef	_JFS_DEBUG_IMAP#define DBG_DIINIT(imap)	DBGdiInit(imap)#define DBG_DIALLOC(imap, ino)	DBGdiAlloc(imap, ino)#define DBG_DIFREE(imap, ino)	DBGdiFree(imap, ino)static void *DBGdiInit(struct inomap * imap);static void DBGdiAlloc(struct inomap * imap, ino_t ino);static void DBGdiFree(struct inomap * imap, ino_t ino);#else#define DBG_DIINIT(imap)#define DBG_DIALLOC(imap, ino)#define DBG_DIFREE(imap, ino)#endif				/* _JFS_DEBUG_IMAP *//* * NAME:        diMount() * * FUNCTION:    initialize the incore inode map control structures for *		a fileset or aggregate init time. * *              the inode map's control structure (dinomap) is  *              brought in from disk and placed in virtual memory. * * PARAMETERS: *      ipimap  - pointer to inode map inode for the aggregate or fileset. * * RETURN VALUES: *      0       - success *      -ENOMEM  - insufficient free virtual memory. *      -EIO  	- i/o error. */int diMount(struct inode *ipimap){	struct inomap *imap;	struct metapage *mp;	int index;	struct dinomap *dinom_le;	/*	 * allocate/initialize the in-memory inode map control structure	 */	/* allocate the in-memory inode map control structure. */	imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL);	if (imap == NULL) {		jfs_err("diMount: kmalloc returned NULL!");		return -ENOMEM;	}	/* read the on-disk inode map control structure. */	mp = read_metapage(ipimap,			   IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage,			   PSIZE, 0);	if (mp == NULL) {		kfree(imap);		return -EIO;	}	/* copy the on-disk version to the in-memory version. */	dinom_le = (struct dinomap *) mp->data;	imap->im_freeiag = le32_to_cpu(dinom_le->in_freeiag);	imap->im_nextiag = le32_to_cpu(dinom_le->in_nextiag);	atomic_set(&imap->im_numinos, le32_to_cpu(dinom_le->in_numinos));	atomic_set(&imap->im_numfree, le32_to_cpu(dinom_le->in_numfree));	imap->im_nbperiext = le32_to_cpu(dinom_le->in_nbperiext);	imap->im_l2nbperiext = le32_to_cpu(dinom_le->in_l2nbperiext);	for (index = 0; index < MAXAG; index++) {		imap->im_agctl[index].inofree =		    le32_to_cpu(dinom_le->in_agctl[index].inofree);		imap->im_agctl[index].extfree =		    le32_to_cpu(dinom_le->in_agctl[index].extfree);		imap->im_agctl[index].numinos =		    le32_to_cpu(dinom_le->in_agctl[index].numinos);		imap->im_agctl[index].numfree =		    le32_to_cpu(dinom_le->in_agctl[index].numfree);	}	/* release the buffer. */	release_metapage(mp);	/*	 * allocate/initialize inode allocation map locks	 */	/* allocate and init iag free list lock */	IAGFREE_LOCK_INIT(imap);	/* allocate and init ag list locks */	for (index = 0; index < MAXAG; index++) {		AG_LOCK_INIT(imap, index);	}	/* bind the inode map inode and inode map control structure	 * to each other.	 */	imap->im_ipimap = ipimap;	JFS_IP(ipimap)->i_imap = imap;//      DBG_DIINIT(imap);	return (0);}/* * NAME:        diUnmount() * * FUNCTION:    write to disk the incore inode map control structures for *		a fileset or aggregate at unmount time. * * PARAMETERS: *      ipimap  - pointer to inode map inode for the aggregate or fileset. * * RETURN VALUES: *      0       - success *      -ENOMEM  - insufficient free virtual memory. *      -EIO  	- i/o error. */int diUnmount(struct inode *ipimap, int mounterror){	struct inomap *imap = JFS_IP(ipimap)->i_imap;	/*	 * update the on-disk inode map control structure	 */	if (!(mounterror || isReadOnly(ipimap)))		diSync(ipimap);	/*	 * Invalidate the page cache buffers	 */	truncate_inode_pages(ipimap->i_mapping, 0);	/*	 * free in-memory control structure	 */	kfree(imap);	return (0);}/* *	diSync() */int diSync(struct inode *ipimap){	struct dinomap *dinom_le;	struct inomap *imp = JFS_IP(ipimap)->i_imap;	struct metapage *mp;	int index;	/*	 * write imap global conrol page	 */	/* read the on-disk inode map control structure */	mp = get_metapage(ipimap,			  IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage,			  PSIZE, 0);	if (mp == NULL) {		jfs_err("diSync: get_metapage failed!");		return -EIO;	}	/* copy the in-memory version to the on-disk version */	dinom_le = (struct dinomap *) mp->data;	dinom_le->in_freeiag = cpu_to_le32(imp->im_freeiag);	dinom_le->in_nextiag = cpu_to_le32(imp->im_nextiag);	dinom_le->in_numinos = cpu_to_le32(atomic_read(&imp->im_numinos));	dinom_le->in_numfree = cpu_to_le32(atomic_read(&imp->im_numfree));	dinom_le->in_nbperiext = cpu_to_le32(imp->im_nbperiext);	dinom_le->in_l2nbperiext = cpu_to_le32(imp->im_l2nbperiext);	for (index = 0; index < MAXAG; index++) {		dinom_le->in_agctl[index].inofree =		    cpu_to_le32(imp->im_agctl[index].inofree);		dinom_le->in_agctl[index].extfree =		    cpu_to_le32(imp->im_agctl[index].extfree);		dinom_le->in_agctl[index].numinos =		    cpu_to_le32(imp->im_agctl[index].numinos);		dinom_le->in_agctl[index].numfree =		    cpu_to_le32(imp->im_agctl[index].numfree);	}	/* write out the control structure */	write_metapage(mp);	/*	 * write out dirty pages of imap	 */	fsync_inode_data_buffers(ipimap);	diWriteSpecial(ipimap, 0);	return (0);}/* * NAME:        diRead() * * FUNCTION:    initialize an incore inode from disk. * *		on entry, the specifed incore inode should itself *		specify the disk inode number corresponding to the *		incore inode (i.e. i_number should be initialized). *		 *		this routine handles incore inode initialization for *		both "special" and "regular" inodes.  special inodes *		are those required early in the mount process and *	        require special handling since much of the file system *		is not yet initialized.  these "special" inodes are *		identified by a NULL inode map inode pointer and are *		actually initialized by a call to diReadSpecial(). *		 *		for regular inodes, the iag describing the disk inode *		is read from disk to determine the inode extent address *		for the disk inode.  with the inode extent address in *		hand, the page of the extent that contains the disk *		inode is read and the disk inode is copied to the *		incore inode. * * PARAMETERS: *      ip  -  pointer to incore inode to be initialized from disk. * * RETURN VALUES: *      0       - success *      -EIO  	- i/o error. *      -ENOMEM	- insufficient memory *       */int diRead(struct inode *ip){	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);	int iagno, ino, extno, rc;	struct inode *ipimap;	struct dinode *dp;	struct iag *iagp;	struct metapage *mp;	s64 blkno, agstart;	struct inomap *imap;	int block_offset;	int inodes_left;	uint pageno;	int rel_inode;	jfs_info("diRead: ino = %ld", ip->i_ino);	ipimap = sbi->ipimap;	JFS_IP(ip)->ipimap = ipimap;	/* determine the iag number for this inode (number) */	iagno = INOTOIAG(ip->i_ino);	/* read the iag */	imap = JFS_IP(ipimap)->i_imap;	IREAD_LOCK(ipimap);	rc = diIAGRead(imap, iagno, &mp);	IREAD_UNLOCK(ipimap);	if (rc) {		jfs_err("diRead: diIAGRead returned %d", rc);		return (rc);	}	iagp = (struct iag *) mp->data;	/* determine inode extent that holds the disk inode */	ino = ip->i_ino & (INOSPERIAG - 1);	extno = ino >> L2INOSPEREXT;	if ((lengthPXD(&iagp->inoext[extno]) != imap->im_nbperiext) ||	    (addressPXD(&iagp->inoext[extno]) == 0)) {		release_metapage(mp);		return -ESTALE;	}	/* get disk block number of the page within the inode extent	 * that holds the disk inode.	 */	blkno = INOPBLK(&iagp->inoext[extno], ino, sbi->l2nbperpage);	/* get the ag for the iag */	agstart = le64_to_cpu(iagp->agstart);	release_metapage(mp);	rel_inode = (ino & (INOSPERPAGE - 1));	pageno = blkno >> sbi->l2nbperpage;	if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) {		/*		 * OS/2 didn't always align inode extents on page boundaries		 */		inodes_left =		     (sbi->nbperpage - block_offset) << sbi->l2niperblk;		if (rel_inode < inodes_left)			rel_inode += block_offset << sbi->l2niperblk;		else {			pageno += 1;			rel_inode -= inodes_left;		}	}	/* read the page of disk inode */	mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);	if (mp == 0) {		jfs_err("diRead: read_metapage failed");		return -EIO;	}	/* locate the the disk inode requested */	dp = (struct dinode *) mp->data;	dp += rel_inode;	if (ip->i_ino != le32_to_cpu(dp->di_number)) {		jfs_error(ip->i_sb, "diRead: i_ino != di_number");		rc = -EIO;	} else if (le32_to_cpu(dp->di_nlink) == 0)		rc = -ESTALE;	else		/* copy the disk inode to the in-memory inode */		rc = copy_from_dinode(dp, ip);	release_metapage(mp);	/* set the ag for the inode */	JFS_IP(ip)->agno = BLKTOAG(agstart, sbi);	JFS_IP(ip)->active_ag = -1;	return (rc);}/* * NAME:        diReadSpecial() * * FUNCTION:    initialize a 'special' inode from disk. * *		this routines handles aggregate level inodes.  The *		inode cache cannot differentiate between the *		aggregate inodes and the filesystem inodes, so we *		handle these here.  We don't actually use the aggregate *	        inode map, since these inodes are at a fixed location *		and in some cases the aggregate inode map isn't initialized *		yet. * * PARAMETERS: *      sb - filesystem superblock *	inum - aggregate inode number *	secondary - 1 if secondary aggregate inode table * * RETURN VALUES: *      new inode	- success *      NULL		- i/o error. */struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary){	struct jfs_sb_info *sbi = JFS_SBI(sb);	uint address;	struct dinode *dp;	struct inode *ip;	struct metapage *mp;	int rc;	ip = new_inode(sb);	if (ip == NULL) {		jfs_err("diReadSpecial: new_inode returned NULL!");		return ip;	}	rc = alloc_jfs_inode(ip);	if (rc) {		make_bad_inode(ip);		iput(ip);		return NULL;	}	if (secondary) {		address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;		JFS_IP(ip)->ipimap = sbi->ipaimap2;	} else {		address = AITBL_OFF >> L2PSIZE;		JFS_IP(ip)->ipimap = sbi->ipaimap;	}	ASSERT(inum < INOSPEREXT);

⌨️ 快捷键说明

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