162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *   Copyright (C) International Business Machines Corp., 2000-2004
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci *	jfs_imap.c: inode allocation map manager
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Serialization:
1062306a36Sopenharmony_ci *   Each AG has a simple lock which is used to control the serialization of
1162306a36Sopenharmony_ci *	the AG level lists.  This lock should be taken first whenever an AG
1262306a36Sopenharmony_ci *	level list will be modified or accessed.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *   Each IAG is locked by obtaining the buffer for the IAG page.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *   There is also a inode lock for the inode map inode.  A read lock needs to
1762306a36Sopenharmony_ci *	be taken whenever an IAG is read from the map or the global level
1862306a36Sopenharmony_ci *	information is read.  A write lock needs to be taken whenever the global
1962306a36Sopenharmony_ci *	level information is modified or an atomic operation needs to be used.
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci *	If more than one IAG is read at one time, the read lock may not
2262306a36Sopenharmony_ci *	be given up until all of the IAG's are read.  Otherwise, a deadlock
2362306a36Sopenharmony_ci *	may occur when trying to obtain the read lock while another thread
2462306a36Sopenharmony_ci *	holding the read lock is waiting on the IAG already being held.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci *   The control page of the inode map is read into memory by diMount().
2762306a36Sopenharmony_ci *	Thereafter it should only be modified in memory and then it will be
2862306a36Sopenharmony_ci *	written out when the filesystem is unmounted by diUnmount().
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <linux/fs.h>
3262306a36Sopenharmony_ci#include <linux/buffer_head.h>
3362306a36Sopenharmony_ci#include <linux/pagemap.h>
3462306a36Sopenharmony_ci#include <linux/quotaops.h>
3562306a36Sopenharmony_ci#include <linux/slab.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include "jfs_incore.h"
3862306a36Sopenharmony_ci#include "jfs_inode.h"
3962306a36Sopenharmony_ci#include "jfs_filsys.h"
4062306a36Sopenharmony_ci#include "jfs_dinode.h"
4162306a36Sopenharmony_ci#include "jfs_dmap.h"
4262306a36Sopenharmony_ci#include "jfs_imap.h"
4362306a36Sopenharmony_ci#include "jfs_metapage.h"
4462306a36Sopenharmony_ci#include "jfs_superblock.h"
4562306a36Sopenharmony_ci#include "jfs_debug.h"
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * imap locks
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci/* iag free list lock */
5162306a36Sopenharmony_ci#define IAGFREE_LOCK_INIT(imap)		mutex_init(&imap->im_freelock)
5262306a36Sopenharmony_ci#define IAGFREE_LOCK(imap)		mutex_lock(&imap->im_freelock)
5362306a36Sopenharmony_ci#define IAGFREE_UNLOCK(imap)		mutex_unlock(&imap->im_freelock)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/* per ag iag list locks */
5662306a36Sopenharmony_ci#define AG_LOCK_INIT(imap,index)	mutex_init(&(imap->im_aglock[index]))
5762306a36Sopenharmony_ci#define AG_LOCK(imap,agno)		mutex_lock(&imap->im_aglock[agno])
5862306a36Sopenharmony_ci#define AG_UNLOCK(imap,agno)		mutex_unlock(&imap->im_aglock[agno])
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * forward references
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_cistatic int diAllocAG(struct inomap *, int, bool, struct inode *);
6462306a36Sopenharmony_cistatic int diAllocAny(struct inomap *, int, bool, struct inode *);
6562306a36Sopenharmony_cistatic int diAllocBit(struct inomap *, struct iag *, int);
6662306a36Sopenharmony_cistatic int diAllocExt(struct inomap *, int, struct inode *);
6762306a36Sopenharmony_cistatic int diAllocIno(struct inomap *, int, struct inode *);
6862306a36Sopenharmony_cistatic int diFindFree(u32, int);
6962306a36Sopenharmony_cistatic int diNewExt(struct inomap *, struct iag *, int);
7062306a36Sopenharmony_cistatic int diNewIAG(struct inomap *, int *, int, struct metapage **);
7162306a36Sopenharmony_cistatic void duplicateIXtree(struct super_block *, s64, int, s64 *);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic int diIAGRead(struct inomap * imap, int, struct metapage **);
7462306a36Sopenharmony_cistatic int copy_from_dinode(struct dinode *, struct inode *);
7562306a36Sopenharmony_cistatic void copy_to_dinode(struct dinode *, struct inode *);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci * NAME:	diMount()
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * FUNCTION:	initialize the incore inode map control structures for
8162306a36Sopenharmony_ci *		a fileset or aggregate init time.
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci *		the inode map's control structure (dinomap) is
8462306a36Sopenharmony_ci *		brought in from disk and placed in virtual memory.
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * PARAMETERS:
8762306a36Sopenharmony_ci *	ipimap	- pointer to inode map inode for the aggregate or fileset.
8862306a36Sopenharmony_ci *
8962306a36Sopenharmony_ci * RETURN VALUES:
9062306a36Sopenharmony_ci *	0	- success
9162306a36Sopenharmony_ci *	-ENOMEM	- insufficient free virtual memory.
9262306a36Sopenharmony_ci *	-EIO	- i/o error.
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_ciint diMount(struct inode *ipimap)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct inomap *imap;
9762306a36Sopenharmony_ci	struct metapage *mp;
9862306a36Sopenharmony_ci	int index;
9962306a36Sopenharmony_ci	struct dinomap_disk *dinom_le;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/*
10262306a36Sopenharmony_ci	 * allocate/initialize the in-memory inode map control structure
10362306a36Sopenharmony_ci	 */
10462306a36Sopenharmony_ci	/* allocate the in-memory inode map control structure. */
10562306a36Sopenharmony_ci	imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
10662306a36Sopenharmony_ci	if (imap == NULL)
10762306a36Sopenharmony_ci		return -ENOMEM;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* read the on-disk inode map control structure. */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	mp = read_metapage(ipimap,
11262306a36Sopenharmony_ci			   IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage,
11362306a36Sopenharmony_ci			   PSIZE, 0);
11462306a36Sopenharmony_ci	if (mp == NULL) {
11562306a36Sopenharmony_ci		kfree(imap);
11662306a36Sopenharmony_ci		return -EIO;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	/* copy the on-disk version to the in-memory version. */
12062306a36Sopenharmony_ci	dinom_le = (struct dinomap_disk *) mp->data;
12162306a36Sopenharmony_ci	imap->im_freeiag = le32_to_cpu(dinom_le->in_freeiag);
12262306a36Sopenharmony_ci	imap->im_nextiag = le32_to_cpu(dinom_le->in_nextiag);
12362306a36Sopenharmony_ci	atomic_set(&imap->im_numinos, le32_to_cpu(dinom_le->in_numinos));
12462306a36Sopenharmony_ci	atomic_set(&imap->im_numfree, le32_to_cpu(dinom_le->in_numfree));
12562306a36Sopenharmony_ci	imap->im_nbperiext = le32_to_cpu(dinom_le->in_nbperiext);
12662306a36Sopenharmony_ci	imap->im_l2nbperiext = le32_to_cpu(dinom_le->in_l2nbperiext);
12762306a36Sopenharmony_ci	for (index = 0; index < MAXAG; index++) {
12862306a36Sopenharmony_ci		imap->im_agctl[index].inofree =
12962306a36Sopenharmony_ci		    le32_to_cpu(dinom_le->in_agctl[index].inofree);
13062306a36Sopenharmony_ci		imap->im_agctl[index].extfree =
13162306a36Sopenharmony_ci		    le32_to_cpu(dinom_le->in_agctl[index].extfree);
13262306a36Sopenharmony_ci		imap->im_agctl[index].numinos =
13362306a36Sopenharmony_ci		    le32_to_cpu(dinom_le->in_agctl[index].numinos);
13462306a36Sopenharmony_ci		imap->im_agctl[index].numfree =
13562306a36Sopenharmony_ci		    le32_to_cpu(dinom_le->in_agctl[index].numfree);
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/* release the buffer. */
13962306a36Sopenharmony_ci	release_metapage(mp);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/*
14262306a36Sopenharmony_ci	 * allocate/initialize inode allocation map locks
14362306a36Sopenharmony_ci	 */
14462306a36Sopenharmony_ci	/* allocate and init iag free list lock */
14562306a36Sopenharmony_ci	IAGFREE_LOCK_INIT(imap);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* allocate and init ag list locks */
14862306a36Sopenharmony_ci	for (index = 0; index < MAXAG; index++) {
14962306a36Sopenharmony_ci		AG_LOCK_INIT(imap, index);
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* bind the inode map inode and inode map control structure
15362306a36Sopenharmony_ci	 * to each other.
15462306a36Sopenharmony_ci	 */
15562306a36Sopenharmony_ci	imap->im_ipimap = ipimap;
15662306a36Sopenharmony_ci	JFS_IP(ipimap)->i_imap = imap;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return (0);
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/*
16362306a36Sopenharmony_ci * NAME:	diUnmount()
16462306a36Sopenharmony_ci *
16562306a36Sopenharmony_ci * FUNCTION:	write to disk the incore inode map control structures for
16662306a36Sopenharmony_ci *		a fileset or aggregate at unmount time.
16762306a36Sopenharmony_ci *
16862306a36Sopenharmony_ci * PARAMETERS:
16962306a36Sopenharmony_ci *	ipimap	- pointer to inode map inode for the aggregate or fileset.
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci * RETURN VALUES:
17262306a36Sopenharmony_ci *	0	- success
17362306a36Sopenharmony_ci *	-ENOMEM	- insufficient free virtual memory.
17462306a36Sopenharmony_ci *	-EIO	- i/o error.
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_ciint diUnmount(struct inode *ipimap, int mounterror)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	struct inomap *imap = JFS_IP(ipimap)->i_imap;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/*
18162306a36Sopenharmony_ci	 * update the on-disk inode map control structure
18262306a36Sopenharmony_ci	 */
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	if (!(mounterror || isReadOnly(ipimap)))
18562306a36Sopenharmony_ci		diSync(ipimap);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/*
18862306a36Sopenharmony_ci	 * Invalidate the page cache buffers
18962306a36Sopenharmony_ci	 */
19062306a36Sopenharmony_ci	truncate_inode_pages(ipimap->i_mapping, 0);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	/*
19362306a36Sopenharmony_ci	 * free in-memory control structure
19462306a36Sopenharmony_ci	 */
19562306a36Sopenharmony_ci	kfree(imap);
19662306a36Sopenharmony_ci	JFS_IP(ipimap)->i_imap = NULL;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	return (0);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/*
20362306a36Sopenharmony_ci *	diSync()
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_ciint diSync(struct inode *ipimap)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	struct dinomap_disk *dinom_le;
20862306a36Sopenharmony_ci	struct inomap *imp = JFS_IP(ipimap)->i_imap;
20962306a36Sopenharmony_ci	struct metapage *mp;
21062306a36Sopenharmony_ci	int index;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/*
21362306a36Sopenharmony_ci	 * write imap global conrol page
21462306a36Sopenharmony_ci	 */
21562306a36Sopenharmony_ci	/* read the on-disk inode map control structure */
21662306a36Sopenharmony_ci	mp = get_metapage(ipimap,
21762306a36Sopenharmony_ci			  IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage,
21862306a36Sopenharmony_ci			  PSIZE, 0);
21962306a36Sopenharmony_ci	if (mp == NULL) {
22062306a36Sopenharmony_ci		jfs_err("diSync: get_metapage failed!");
22162306a36Sopenharmony_ci		return -EIO;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/* copy the in-memory version to the on-disk version */
22562306a36Sopenharmony_ci	dinom_le = (struct dinomap_disk *) mp->data;
22662306a36Sopenharmony_ci	dinom_le->in_freeiag = cpu_to_le32(imp->im_freeiag);
22762306a36Sopenharmony_ci	dinom_le->in_nextiag = cpu_to_le32(imp->im_nextiag);
22862306a36Sopenharmony_ci	dinom_le->in_numinos = cpu_to_le32(atomic_read(&imp->im_numinos));
22962306a36Sopenharmony_ci	dinom_le->in_numfree = cpu_to_le32(atomic_read(&imp->im_numfree));
23062306a36Sopenharmony_ci	dinom_le->in_nbperiext = cpu_to_le32(imp->im_nbperiext);
23162306a36Sopenharmony_ci	dinom_le->in_l2nbperiext = cpu_to_le32(imp->im_l2nbperiext);
23262306a36Sopenharmony_ci	for (index = 0; index < MAXAG; index++) {
23362306a36Sopenharmony_ci		dinom_le->in_agctl[index].inofree =
23462306a36Sopenharmony_ci		    cpu_to_le32(imp->im_agctl[index].inofree);
23562306a36Sopenharmony_ci		dinom_le->in_agctl[index].extfree =
23662306a36Sopenharmony_ci		    cpu_to_le32(imp->im_agctl[index].extfree);
23762306a36Sopenharmony_ci		dinom_le->in_agctl[index].numinos =
23862306a36Sopenharmony_ci		    cpu_to_le32(imp->im_agctl[index].numinos);
23962306a36Sopenharmony_ci		dinom_le->in_agctl[index].numfree =
24062306a36Sopenharmony_ci		    cpu_to_le32(imp->im_agctl[index].numfree);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* write out the control structure */
24462306a36Sopenharmony_ci	write_metapage(mp);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/*
24762306a36Sopenharmony_ci	 * write out dirty pages of imap
24862306a36Sopenharmony_ci	 */
24962306a36Sopenharmony_ci	filemap_write_and_wait(ipimap->i_mapping);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	diWriteSpecial(ipimap, 0);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	return (0);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/*
25862306a36Sopenharmony_ci * NAME:	diRead()
25962306a36Sopenharmony_ci *
26062306a36Sopenharmony_ci * FUNCTION:	initialize an incore inode from disk.
26162306a36Sopenharmony_ci *
26262306a36Sopenharmony_ci *		on entry, the specifed incore inode should itself
26362306a36Sopenharmony_ci *		specify the disk inode number corresponding to the
26462306a36Sopenharmony_ci *		incore inode (i.e. i_number should be initialized).
26562306a36Sopenharmony_ci *
26662306a36Sopenharmony_ci *		this routine handles incore inode initialization for
26762306a36Sopenharmony_ci *		both "special" and "regular" inodes.  special inodes
26862306a36Sopenharmony_ci *		are those required early in the mount process and
26962306a36Sopenharmony_ci *		require special handling since much of the file system
27062306a36Sopenharmony_ci *		is not yet initialized.  these "special" inodes are
27162306a36Sopenharmony_ci *		identified by a NULL inode map inode pointer and are
27262306a36Sopenharmony_ci *		actually initialized by a call to diReadSpecial().
27362306a36Sopenharmony_ci *
27462306a36Sopenharmony_ci *		for regular inodes, the iag describing the disk inode
27562306a36Sopenharmony_ci *		is read from disk to determine the inode extent address
27662306a36Sopenharmony_ci *		for the disk inode.  with the inode extent address in
27762306a36Sopenharmony_ci *		hand, the page of the extent that contains the disk
27862306a36Sopenharmony_ci *		inode is read and the disk inode is copied to the
27962306a36Sopenharmony_ci *		incore inode.
28062306a36Sopenharmony_ci *
28162306a36Sopenharmony_ci * PARAMETERS:
28262306a36Sopenharmony_ci *	ip	-  pointer to incore inode to be initialized from disk.
28362306a36Sopenharmony_ci *
28462306a36Sopenharmony_ci * RETURN VALUES:
28562306a36Sopenharmony_ci *	0	- success
28662306a36Sopenharmony_ci *	-EIO	- i/o error.
28762306a36Sopenharmony_ci *	-ENOMEM	- insufficient memory
28862306a36Sopenharmony_ci *
28962306a36Sopenharmony_ci */
29062306a36Sopenharmony_ciint diRead(struct inode *ip)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
29362306a36Sopenharmony_ci	int iagno, ino, extno, rc;
29462306a36Sopenharmony_ci	struct inode *ipimap;
29562306a36Sopenharmony_ci	struct dinode *dp;
29662306a36Sopenharmony_ci	struct iag *iagp;
29762306a36Sopenharmony_ci	struct metapage *mp;
29862306a36Sopenharmony_ci	s64 blkno, agstart;
29962306a36Sopenharmony_ci	struct inomap *imap;
30062306a36Sopenharmony_ci	int block_offset;
30162306a36Sopenharmony_ci	int inodes_left;
30262306a36Sopenharmony_ci	unsigned long pageno;
30362306a36Sopenharmony_ci	int rel_inode;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	jfs_info("diRead: ino = %ld", ip->i_ino);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	ipimap = sbi->ipimap;
30862306a36Sopenharmony_ci	JFS_IP(ip)->ipimap = ipimap;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* determine the iag number for this inode (number) */
31162306a36Sopenharmony_ci	iagno = INOTOIAG(ip->i_ino);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* read the iag */
31462306a36Sopenharmony_ci	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
31562306a36Sopenharmony_ci	imap = JFS_IP(ipimap)->i_imap;
31662306a36Sopenharmony_ci	rc = diIAGRead(imap, iagno, &mp);
31762306a36Sopenharmony_ci	IREAD_UNLOCK(ipimap);
31862306a36Sopenharmony_ci	if (rc) {
31962306a36Sopenharmony_ci		jfs_err("diRead: diIAGRead returned %d", rc);
32062306a36Sopenharmony_ci		return (rc);
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	/* determine inode extent that holds the disk inode */
32662306a36Sopenharmony_ci	ino = ip->i_ino & (INOSPERIAG - 1);
32762306a36Sopenharmony_ci	extno = ino >> L2INOSPEREXT;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if ((lengthPXD(&iagp->inoext[extno]) != imap->im_nbperiext) ||
33062306a36Sopenharmony_ci	    (addressPXD(&iagp->inoext[extno]) == 0)) {
33162306a36Sopenharmony_ci		release_metapage(mp);
33262306a36Sopenharmony_ci		return -ESTALE;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	/* get disk block number of the page within the inode extent
33662306a36Sopenharmony_ci	 * that holds the disk inode.
33762306a36Sopenharmony_ci	 */
33862306a36Sopenharmony_ci	blkno = INOPBLK(&iagp->inoext[extno], ino, sbi->l2nbperpage);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	/* get the ag for the iag */
34162306a36Sopenharmony_ci	agstart = le64_to_cpu(iagp->agstart);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	release_metapage(mp);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	rel_inode = (ino & (INOSPERPAGE - 1));
34662306a36Sopenharmony_ci	pageno = blkno >> sbi->l2nbperpage;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) {
34962306a36Sopenharmony_ci		/*
35062306a36Sopenharmony_ci		 * OS/2 didn't always align inode extents on page boundaries
35162306a36Sopenharmony_ci		 */
35262306a36Sopenharmony_ci		inodes_left =
35362306a36Sopenharmony_ci		     (sbi->nbperpage - block_offset) << sbi->l2niperblk;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		if (rel_inode < inodes_left)
35662306a36Sopenharmony_ci			rel_inode += block_offset << sbi->l2niperblk;
35762306a36Sopenharmony_ci		else {
35862306a36Sopenharmony_ci			pageno += 1;
35962306a36Sopenharmony_ci			rel_inode -= inodes_left;
36062306a36Sopenharmony_ci		}
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/* read the page of disk inode */
36462306a36Sopenharmony_ci	mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);
36562306a36Sopenharmony_ci	if (!mp) {
36662306a36Sopenharmony_ci		jfs_err("diRead: read_metapage failed");
36762306a36Sopenharmony_ci		return -EIO;
36862306a36Sopenharmony_ci	}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	/* locate the disk inode requested */
37162306a36Sopenharmony_ci	dp = (struct dinode *) mp->data;
37262306a36Sopenharmony_ci	dp += rel_inode;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (ip->i_ino != le32_to_cpu(dp->di_number)) {
37562306a36Sopenharmony_ci		jfs_error(ip->i_sb, "i_ino != di_number\n");
37662306a36Sopenharmony_ci		rc = -EIO;
37762306a36Sopenharmony_ci	} else if (le32_to_cpu(dp->di_nlink) == 0)
37862306a36Sopenharmony_ci		rc = -ESTALE;
37962306a36Sopenharmony_ci	else
38062306a36Sopenharmony_ci		/* copy the disk inode to the in-memory inode */
38162306a36Sopenharmony_ci		rc = copy_from_dinode(dp, ip);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	release_metapage(mp);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/* set the ag for the inode */
38662306a36Sopenharmony_ci	JFS_IP(ip)->agstart = agstart;
38762306a36Sopenharmony_ci	JFS_IP(ip)->active_ag = -1;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	return (rc);
39062306a36Sopenharmony_ci}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci/*
39462306a36Sopenharmony_ci * NAME:	diReadSpecial()
39562306a36Sopenharmony_ci *
39662306a36Sopenharmony_ci * FUNCTION:	initialize a 'special' inode from disk.
39762306a36Sopenharmony_ci *
39862306a36Sopenharmony_ci *		this routines handles aggregate level inodes.  The
39962306a36Sopenharmony_ci *		inode cache cannot differentiate between the
40062306a36Sopenharmony_ci *		aggregate inodes and the filesystem inodes, so we
40162306a36Sopenharmony_ci *		handle these here.  We don't actually use the aggregate
40262306a36Sopenharmony_ci *		inode map, since these inodes are at a fixed location
40362306a36Sopenharmony_ci *		and in some cases the aggregate inode map isn't initialized
40462306a36Sopenharmony_ci *		yet.
40562306a36Sopenharmony_ci *
40662306a36Sopenharmony_ci * PARAMETERS:
40762306a36Sopenharmony_ci *	sb - filesystem superblock
40862306a36Sopenharmony_ci *	inum - aggregate inode number
40962306a36Sopenharmony_ci *	secondary - 1 if secondary aggregate inode table
41062306a36Sopenharmony_ci *
41162306a36Sopenharmony_ci * RETURN VALUES:
41262306a36Sopenharmony_ci *	new inode	- success
41362306a36Sopenharmony_ci *	NULL		- i/o error.
41462306a36Sopenharmony_ci */
41562306a36Sopenharmony_cistruct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
41862306a36Sopenharmony_ci	uint address;
41962306a36Sopenharmony_ci	struct dinode *dp;
42062306a36Sopenharmony_ci	struct inode *ip;
42162306a36Sopenharmony_ci	struct metapage *mp;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	ip = new_inode(sb);
42462306a36Sopenharmony_ci	if (ip == NULL) {
42562306a36Sopenharmony_ci		jfs_err("diReadSpecial: new_inode returned NULL!");
42662306a36Sopenharmony_ci		return ip;
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	if (secondary) {
43062306a36Sopenharmony_ci		address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;
43162306a36Sopenharmony_ci		JFS_IP(ip)->ipimap = sbi->ipaimap2;
43262306a36Sopenharmony_ci	} else {
43362306a36Sopenharmony_ci		address = AITBL_OFF >> L2PSIZE;
43462306a36Sopenharmony_ci		JFS_IP(ip)->ipimap = sbi->ipaimap;
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	ASSERT(inum < INOSPEREXT);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	ip->i_ino = inum;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	address += inum >> 3;	/* 8 inodes per 4K page */
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	/* read the page of fixed disk inode (AIT) in raw mode */
44462306a36Sopenharmony_ci	mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1);
44562306a36Sopenharmony_ci	if (mp == NULL) {
44662306a36Sopenharmony_ci		set_nlink(ip, 1);	/* Don't want iput() deleting it */
44762306a36Sopenharmony_ci		iput(ip);
44862306a36Sopenharmony_ci		return (NULL);
44962306a36Sopenharmony_ci	}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	/* get the pointer to the disk inode of interest */
45262306a36Sopenharmony_ci	dp = (struct dinode *) (mp->data);
45362306a36Sopenharmony_ci	dp += inum % 8;		/* 8 inodes per 4K page */
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* copy on-disk inode to in-memory inode */
45662306a36Sopenharmony_ci	if ((copy_from_dinode(dp, ip)) != 0) {
45762306a36Sopenharmony_ci		/* handle bad return by returning NULL for ip */
45862306a36Sopenharmony_ci		set_nlink(ip, 1);	/* Don't want iput() deleting it */
45962306a36Sopenharmony_ci		iput(ip);
46062306a36Sopenharmony_ci		/* release the page */
46162306a36Sopenharmony_ci		release_metapage(mp);
46262306a36Sopenharmony_ci		return (NULL);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	ip->i_mapping->a_ops = &jfs_metapage_aops;
46762306a36Sopenharmony_ci	mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	/* Allocations to metadata inodes should not affect quotas */
47062306a36Sopenharmony_ci	ip->i_flags |= S_NOQUOTA;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {
47362306a36Sopenharmony_ci		sbi->gengen = le32_to_cpu(dp->di_gengen);
47462306a36Sopenharmony_ci		sbi->inostamp = le32_to_cpu(dp->di_inostamp);
47562306a36Sopenharmony_ci	}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	/* release the page */
47862306a36Sopenharmony_ci	release_metapage(mp);
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	inode_fake_hash(ip);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	return (ip);
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci/*
48662306a36Sopenharmony_ci * NAME:	diWriteSpecial()
48762306a36Sopenharmony_ci *
48862306a36Sopenharmony_ci * FUNCTION:	Write the special inode to disk
48962306a36Sopenharmony_ci *
49062306a36Sopenharmony_ci * PARAMETERS:
49162306a36Sopenharmony_ci *	ip - special inode
49262306a36Sopenharmony_ci *	secondary - 1 if secondary aggregate inode table
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * RETURN VALUES: none
49562306a36Sopenharmony_ci */
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_civoid diWriteSpecial(struct inode *ip, int secondary)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
50062306a36Sopenharmony_ci	uint address;
50162306a36Sopenharmony_ci	struct dinode *dp;
50262306a36Sopenharmony_ci	ino_t inum = ip->i_ino;
50362306a36Sopenharmony_ci	struct metapage *mp;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	if (secondary)
50662306a36Sopenharmony_ci		address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;
50762306a36Sopenharmony_ci	else
50862306a36Sopenharmony_ci		address = AITBL_OFF >> L2PSIZE;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	ASSERT(inum < INOSPEREXT);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	address += inum >> 3;	/* 8 inodes per 4K page */
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	/* read the page of fixed disk inode (AIT) in raw mode */
51562306a36Sopenharmony_ci	mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1);
51662306a36Sopenharmony_ci	if (mp == NULL) {
51762306a36Sopenharmony_ci		jfs_err("diWriteSpecial: failed to read aggregate inode extent!");
51862306a36Sopenharmony_ci		return;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	/* get the pointer to the disk inode of interest */
52262306a36Sopenharmony_ci	dp = (struct dinode *) (mp->data);
52362306a36Sopenharmony_ci	dp += inum % 8;		/* 8 inodes per 4K page */
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	/* copy on-disk inode to in-memory inode */
52662306a36Sopenharmony_ci	copy_to_dinode(dp, ip);
52762306a36Sopenharmony_ci	memcpy(&dp->di_xtroot, &JFS_IP(ip)->i_xtroot, 288);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (inum == FILESYSTEM_I)
53062306a36Sopenharmony_ci		dp->di_gengen = cpu_to_le32(sbi->gengen);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* write the page */
53362306a36Sopenharmony_ci	write_metapage(mp);
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci/*
53762306a36Sopenharmony_ci * NAME:	diFreeSpecial()
53862306a36Sopenharmony_ci *
53962306a36Sopenharmony_ci * FUNCTION:	Free allocated space for special inode
54062306a36Sopenharmony_ci */
54162306a36Sopenharmony_civoid diFreeSpecial(struct inode *ip)
54262306a36Sopenharmony_ci{
54362306a36Sopenharmony_ci	if (ip == NULL) {
54462306a36Sopenharmony_ci		jfs_err("diFreeSpecial called with NULL ip!");
54562306a36Sopenharmony_ci		return;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci	filemap_write_and_wait(ip->i_mapping);
54862306a36Sopenharmony_ci	truncate_inode_pages(ip->i_mapping, 0);
54962306a36Sopenharmony_ci	iput(ip);
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci/*
55562306a36Sopenharmony_ci * NAME:	diWrite()
55662306a36Sopenharmony_ci *
55762306a36Sopenharmony_ci * FUNCTION:	write the on-disk inode portion of the in-memory inode
55862306a36Sopenharmony_ci *		to its corresponding on-disk inode.
55962306a36Sopenharmony_ci *
56062306a36Sopenharmony_ci *		on entry, the specifed incore inode should itself
56162306a36Sopenharmony_ci *		specify the disk inode number corresponding to the
56262306a36Sopenharmony_ci *		incore inode (i.e. i_number should be initialized).
56362306a36Sopenharmony_ci *
56462306a36Sopenharmony_ci *		the inode contains the inode extent address for the disk
56562306a36Sopenharmony_ci *		inode.  with the inode extent address in hand, the
56662306a36Sopenharmony_ci *		page of the extent that contains the disk inode is
56762306a36Sopenharmony_ci *		read and the disk inode portion of the incore inode
56862306a36Sopenharmony_ci *		is copied to the disk inode.
56962306a36Sopenharmony_ci *
57062306a36Sopenharmony_ci * PARAMETERS:
57162306a36Sopenharmony_ci *	tid -  transacation id
57262306a36Sopenharmony_ci *	ip  -  pointer to incore inode to be written to the inode extent.
57362306a36Sopenharmony_ci *
57462306a36Sopenharmony_ci * RETURN VALUES:
57562306a36Sopenharmony_ci *	0	- success
57662306a36Sopenharmony_ci *	-EIO	- i/o error.
57762306a36Sopenharmony_ci */
57862306a36Sopenharmony_ciint diWrite(tid_t tid, struct inode *ip)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
58162306a36Sopenharmony_ci	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
58262306a36Sopenharmony_ci	int rc = 0;
58362306a36Sopenharmony_ci	s32 ino;
58462306a36Sopenharmony_ci	struct dinode *dp;
58562306a36Sopenharmony_ci	s64 blkno;
58662306a36Sopenharmony_ci	int block_offset;
58762306a36Sopenharmony_ci	int inodes_left;
58862306a36Sopenharmony_ci	struct metapage *mp;
58962306a36Sopenharmony_ci	unsigned long pageno;
59062306a36Sopenharmony_ci	int rel_inode;
59162306a36Sopenharmony_ci	int dioffset;
59262306a36Sopenharmony_ci	struct inode *ipimap;
59362306a36Sopenharmony_ci	uint type;
59462306a36Sopenharmony_ci	lid_t lid;
59562306a36Sopenharmony_ci	struct tlock *ditlck, *tlck;
59662306a36Sopenharmony_ci	struct linelock *dilinelock, *ilinelock;
59762306a36Sopenharmony_ci	struct lv *lv;
59862306a36Sopenharmony_ci	int n;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	ipimap = jfs_ip->ipimap;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	ino = ip->i_ino & (INOSPERIAG - 1);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (!addressPXD(&(jfs_ip->ixpxd)) ||
60562306a36Sopenharmony_ci	    (lengthPXD(&(jfs_ip->ixpxd)) !=
60662306a36Sopenharmony_ci	     JFS_IP(ipimap)->i_imap->im_nbperiext)) {
60762306a36Sopenharmony_ci		jfs_error(ip->i_sb, "ixpxd invalid\n");
60862306a36Sopenharmony_ci		return -EIO;
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	/*
61262306a36Sopenharmony_ci	 * read the page of disk inode containing the specified inode:
61362306a36Sopenharmony_ci	 */
61462306a36Sopenharmony_ci	/* compute the block address of the page */
61562306a36Sopenharmony_ci	blkno = INOPBLK(&(jfs_ip->ixpxd), ino, sbi->l2nbperpage);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	rel_inode = (ino & (INOSPERPAGE - 1));
61862306a36Sopenharmony_ci	pageno = blkno >> sbi->l2nbperpage;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) {
62162306a36Sopenharmony_ci		/*
62262306a36Sopenharmony_ci		 * OS/2 didn't always align inode extents on page boundaries
62362306a36Sopenharmony_ci		 */
62462306a36Sopenharmony_ci		inodes_left =
62562306a36Sopenharmony_ci		    (sbi->nbperpage - block_offset) << sbi->l2niperblk;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci		if (rel_inode < inodes_left)
62862306a36Sopenharmony_ci			rel_inode += block_offset << sbi->l2niperblk;
62962306a36Sopenharmony_ci		else {
63062306a36Sopenharmony_ci			pageno += 1;
63162306a36Sopenharmony_ci			rel_inode -= inodes_left;
63262306a36Sopenharmony_ci		}
63362306a36Sopenharmony_ci	}
63462306a36Sopenharmony_ci	/* read the page of disk inode */
63562306a36Sopenharmony_ci      retry:
63662306a36Sopenharmony_ci	mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);
63762306a36Sopenharmony_ci	if (!mp)
63862306a36Sopenharmony_ci		return -EIO;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	/* get the pointer to the disk inode */
64162306a36Sopenharmony_ci	dp = (struct dinode *) mp->data;
64262306a36Sopenharmony_ci	dp += rel_inode;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	dioffset = (ino & (INOSPERPAGE - 1)) << L2DISIZE;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	/*
64762306a36Sopenharmony_ci	 * acquire transaction lock on the on-disk inode;
64862306a36Sopenharmony_ci	 * N.B. tlock is acquired on ipimap not ip;
64962306a36Sopenharmony_ci	 */
65062306a36Sopenharmony_ci	if ((ditlck =
65162306a36Sopenharmony_ci	     txLock(tid, ipimap, mp, tlckINODE | tlckENTRY)) == NULL)
65262306a36Sopenharmony_ci		goto retry;
65362306a36Sopenharmony_ci	dilinelock = (struct linelock *) & ditlck->lock;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	/*
65662306a36Sopenharmony_ci	 * copy btree root from in-memory inode to on-disk inode
65762306a36Sopenharmony_ci	 *
65862306a36Sopenharmony_ci	 * (tlock is taken from inline B+-tree root in in-memory
65962306a36Sopenharmony_ci	 * inode when the B+-tree root is updated, which is pointed
66062306a36Sopenharmony_ci	 * by jfs_ip->blid as well as being on tx tlock list)
66162306a36Sopenharmony_ci	 *
66262306a36Sopenharmony_ci	 * further processing of btree root is based on the copy
66362306a36Sopenharmony_ci	 * in in-memory inode, where txLog() will log from, and,
66462306a36Sopenharmony_ci	 * for xtree root, txUpdateMap() will update map and reset
66562306a36Sopenharmony_ci	 * XAD_NEW bit;
66662306a36Sopenharmony_ci	 */
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	if (S_ISDIR(ip->i_mode) && (lid = jfs_ip->xtlid)) {
66962306a36Sopenharmony_ci		/*
67062306a36Sopenharmony_ci		 * This is the special xtree inside the directory for storing
67162306a36Sopenharmony_ci		 * the directory table
67262306a36Sopenharmony_ci		 */
67362306a36Sopenharmony_ci		xtpage_t *p, *xp;
67462306a36Sopenharmony_ci		xad_t *xad;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci		jfs_ip->xtlid = 0;
67762306a36Sopenharmony_ci		tlck = lid_to_tlock(lid);
67862306a36Sopenharmony_ci		assert(tlck->type & tlckXTREE);
67962306a36Sopenharmony_ci		tlck->type |= tlckBTROOT;
68062306a36Sopenharmony_ci		tlck->mp = mp;
68162306a36Sopenharmony_ci		ilinelock = (struct linelock *) & tlck->lock;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci		/*
68462306a36Sopenharmony_ci		 * copy xtree root from inode to dinode:
68562306a36Sopenharmony_ci		 */
68662306a36Sopenharmony_ci		p = &jfs_ip->i_xtroot;
68762306a36Sopenharmony_ci		xp = (xtpage_t *) &dp->di_dirtable;
68862306a36Sopenharmony_ci		lv = ilinelock->lv;
68962306a36Sopenharmony_ci		for (n = 0; n < ilinelock->index; n++, lv++) {
69062306a36Sopenharmony_ci			memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],
69162306a36Sopenharmony_ci			       lv->length << L2XTSLOTSIZE);
69262306a36Sopenharmony_ci		}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci		/* reset on-disk (metadata page) xtree XAD_NEW bit */
69562306a36Sopenharmony_ci		xad = &xp->xad[XTENTRYSTART];
69662306a36Sopenharmony_ci		for (n = XTENTRYSTART;
69762306a36Sopenharmony_ci		     n < le16_to_cpu(xp->header.nextindex); n++, xad++)
69862306a36Sopenharmony_ci			if (xad->flag & (XAD_NEW | XAD_EXTENDED))
69962306a36Sopenharmony_ci				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	if ((lid = jfs_ip->blid) == 0)
70362306a36Sopenharmony_ci		goto inlineData;
70462306a36Sopenharmony_ci	jfs_ip->blid = 0;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	tlck = lid_to_tlock(lid);
70762306a36Sopenharmony_ci	type = tlck->type;
70862306a36Sopenharmony_ci	tlck->type |= tlckBTROOT;
70962306a36Sopenharmony_ci	tlck->mp = mp;
71062306a36Sopenharmony_ci	ilinelock = (struct linelock *) & tlck->lock;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	/*
71362306a36Sopenharmony_ci	 *	regular file: 16 byte (XAD slot) granularity
71462306a36Sopenharmony_ci	 */
71562306a36Sopenharmony_ci	if (type & tlckXTREE) {
71662306a36Sopenharmony_ci		xtpage_t *p, *xp;
71762306a36Sopenharmony_ci		xad_t *xad;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci		/*
72062306a36Sopenharmony_ci		 * copy xtree root from inode to dinode:
72162306a36Sopenharmony_ci		 */
72262306a36Sopenharmony_ci		p = &jfs_ip->i_xtroot;
72362306a36Sopenharmony_ci		xp = &dp->di_xtroot;
72462306a36Sopenharmony_ci		lv = ilinelock->lv;
72562306a36Sopenharmony_ci		for (n = 0; n < ilinelock->index; n++, lv++) {
72662306a36Sopenharmony_ci			memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],
72762306a36Sopenharmony_ci			       lv->length << L2XTSLOTSIZE);
72862306a36Sopenharmony_ci		}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci		/* reset on-disk (metadata page) xtree XAD_NEW bit */
73162306a36Sopenharmony_ci		xad = &xp->xad[XTENTRYSTART];
73262306a36Sopenharmony_ci		for (n = XTENTRYSTART;
73362306a36Sopenharmony_ci		     n < le16_to_cpu(xp->header.nextindex); n++, xad++)
73462306a36Sopenharmony_ci			if (xad->flag & (XAD_NEW | XAD_EXTENDED))
73562306a36Sopenharmony_ci				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci	/*
73862306a36Sopenharmony_ci	 *	directory: 32 byte (directory entry slot) granularity
73962306a36Sopenharmony_ci	 */
74062306a36Sopenharmony_ci	else if (type & tlckDTREE) {
74162306a36Sopenharmony_ci		dtpage_t *p, *xp;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci		/*
74462306a36Sopenharmony_ci		 * copy dtree root from inode to dinode:
74562306a36Sopenharmony_ci		 */
74662306a36Sopenharmony_ci		p = (dtpage_t *) &jfs_ip->i_dtroot;
74762306a36Sopenharmony_ci		xp = (dtpage_t *) & dp->di_dtroot;
74862306a36Sopenharmony_ci		lv = ilinelock->lv;
74962306a36Sopenharmony_ci		for (n = 0; n < ilinelock->index; n++, lv++) {
75062306a36Sopenharmony_ci			memcpy(&xp->slot[lv->offset], &p->slot[lv->offset],
75162306a36Sopenharmony_ci			       lv->length << L2DTSLOTSIZE);
75262306a36Sopenharmony_ci		}
75362306a36Sopenharmony_ci	} else {
75462306a36Sopenharmony_ci		jfs_err("diWrite: UFO tlock");
75562306a36Sopenharmony_ci	}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci      inlineData:
75862306a36Sopenharmony_ci	/*
75962306a36Sopenharmony_ci	 * copy inline symlink from in-memory inode to on-disk inode
76062306a36Sopenharmony_ci	 */
76162306a36Sopenharmony_ci	if (S_ISLNK(ip->i_mode) && ip->i_size < IDATASIZE) {
76262306a36Sopenharmony_ci		lv = & dilinelock->lv[dilinelock->index];
76362306a36Sopenharmony_ci		lv->offset = (dioffset + 2 * 128) >> L2INODESLOTSIZE;
76462306a36Sopenharmony_ci		lv->length = 2;
76562306a36Sopenharmony_ci		memcpy(&dp->di_inline_all, jfs_ip->i_inline_all, IDATASIZE);
76662306a36Sopenharmony_ci		dilinelock->index++;
76762306a36Sopenharmony_ci	}
76862306a36Sopenharmony_ci	/*
76962306a36Sopenharmony_ci	 * copy inline data from in-memory inode to on-disk inode:
77062306a36Sopenharmony_ci	 * 128 byte slot granularity
77162306a36Sopenharmony_ci	 */
77262306a36Sopenharmony_ci	if (test_cflag(COMMIT_Inlineea, ip)) {
77362306a36Sopenharmony_ci		lv = & dilinelock->lv[dilinelock->index];
77462306a36Sopenharmony_ci		lv->offset = (dioffset + 3 * 128) >> L2INODESLOTSIZE;
77562306a36Sopenharmony_ci		lv->length = 1;
77662306a36Sopenharmony_ci		memcpy(&dp->di_inlineea, jfs_ip->i_inline_ea, INODESLOTSIZE);
77762306a36Sopenharmony_ci		dilinelock->index++;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci		clear_cflag(COMMIT_Inlineea, ip);
78062306a36Sopenharmony_ci	}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	/*
78362306a36Sopenharmony_ci	 *	lock/copy inode base: 128 byte slot granularity
78462306a36Sopenharmony_ci	 */
78562306a36Sopenharmony_ci	lv = & dilinelock->lv[dilinelock->index];
78662306a36Sopenharmony_ci	lv->offset = dioffset >> L2INODESLOTSIZE;
78762306a36Sopenharmony_ci	copy_to_dinode(dp, ip);
78862306a36Sopenharmony_ci	if (test_and_clear_cflag(COMMIT_Dirtable, ip)) {
78962306a36Sopenharmony_ci		lv->length = 2;
79062306a36Sopenharmony_ci		memcpy(&dp->di_dirtable, &jfs_ip->i_dirtable, 96);
79162306a36Sopenharmony_ci	} else
79262306a36Sopenharmony_ci		lv->length = 1;
79362306a36Sopenharmony_ci	dilinelock->index++;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	/* release the buffer holding the updated on-disk inode.
79662306a36Sopenharmony_ci	 * the buffer will be later written by commit processing.
79762306a36Sopenharmony_ci	 */
79862306a36Sopenharmony_ci	write_metapage(mp);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	return (rc);
80162306a36Sopenharmony_ci}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci/*
80562306a36Sopenharmony_ci * NAME:	diFree(ip)
80662306a36Sopenharmony_ci *
80762306a36Sopenharmony_ci * FUNCTION:	free a specified inode from the inode working map
80862306a36Sopenharmony_ci *		for a fileset or aggregate.
80962306a36Sopenharmony_ci *
81062306a36Sopenharmony_ci *		if the inode to be freed represents the first (only)
81162306a36Sopenharmony_ci *		free inode within the iag, the iag will be placed on
81262306a36Sopenharmony_ci *		the ag free inode list.
81362306a36Sopenharmony_ci *
81462306a36Sopenharmony_ci *		freeing the inode will cause the inode extent to be
81562306a36Sopenharmony_ci *		freed if the inode is the only allocated inode within
81662306a36Sopenharmony_ci *		the extent.  in this case all the disk resource backing
81762306a36Sopenharmony_ci *		up the inode extent will be freed. in addition, the iag
81862306a36Sopenharmony_ci *		will be placed on the ag extent free list if the extent
81962306a36Sopenharmony_ci *		is the first free extent in the iag.  if freeing the
82062306a36Sopenharmony_ci *		extent also means that no free inodes will exist for
82162306a36Sopenharmony_ci *		the iag, the iag will also be removed from the ag free
82262306a36Sopenharmony_ci *		inode list.
82362306a36Sopenharmony_ci *
82462306a36Sopenharmony_ci *		the iag describing the inode will be freed if the extent
82562306a36Sopenharmony_ci *		is to be freed and it is the only backed extent within
82662306a36Sopenharmony_ci *		the iag.  in this case, the iag will be removed from the
82762306a36Sopenharmony_ci *		ag free extent list and ag free inode list and placed on
82862306a36Sopenharmony_ci *		the inode map's free iag list.
82962306a36Sopenharmony_ci *
83062306a36Sopenharmony_ci *		a careful update approach is used to provide consistency
83162306a36Sopenharmony_ci *		in the face of updates to multiple buffers.  under this
83262306a36Sopenharmony_ci *		approach, all required buffers are obtained before making
83362306a36Sopenharmony_ci *		any updates and are held until all updates are complete.
83462306a36Sopenharmony_ci *
83562306a36Sopenharmony_ci * PARAMETERS:
83662306a36Sopenharmony_ci *	ip	- inode to be freed.
83762306a36Sopenharmony_ci *
83862306a36Sopenharmony_ci * RETURN VALUES:
83962306a36Sopenharmony_ci *	0	- success
84062306a36Sopenharmony_ci *	-EIO	- i/o error.
84162306a36Sopenharmony_ci */
84262306a36Sopenharmony_ciint diFree(struct inode *ip)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	int rc;
84562306a36Sopenharmony_ci	ino_t inum = ip->i_ino;
84662306a36Sopenharmony_ci	struct iag *iagp, *aiagp, *biagp, *ciagp, *diagp;
84762306a36Sopenharmony_ci	struct metapage *mp, *amp, *bmp, *cmp, *dmp;
84862306a36Sopenharmony_ci	int iagno, ino, extno, bitno, sword, agno;
84962306a36Sopenharmony_ci	int back, fwd;
85062306a36Sopenharmony_ci	u32 bitmap, mask;
85162306a36Sopenharmony_ci	struct inode *ipimap = JFS_SBI(ip->i_sb)->ipimap;
85262306a36Sopenharmony_ci	struct inomap *imap = JFS_IP(ipimap)->i_imap;
85362306a36Sopenharmony_ci	pxd_t freepxd;
85462306a36Sopenharmony_ci	tid_t tid;
85562306a36Sopenharmony_ci	struct inode *iplist[3];
85662306a36Sopenharmony_ci	struct tlock *tlck;
85762306a36Sopenharmony_ci	struct pxd_lock *pxdlock;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	/*
86062306a36Sopenharmony_ci	 * This is just to suppress compiler warnings.  The same logic that
86162306a36Sopenharmony_ci	 * references these variables is used to initialize them.
86262306a36Sopenharmony_ci	 */
86362306a36Sopenharmony_ci	aiagp = biagp = ciagp = diagp = NULL;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	/* get the iag number containing the inode.
86662306a36Sopenharmony_ci	 */
86762306a36Sopenharmony_ci	iagno = INOTOIAG(inum);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	/* make sure that the iag is contained within
87062306a36Sopenharmony_ci	 * the map.
87162306a36Sopenharmony_ci	 */
87262306a36Sopenharmony_ci	if (iagno >= imap->im_nextiag) {
87362306a36Sopenharmony_ci		print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
87462306a36Sopenharmony_ci			       imap, 32, 0);
87562306a36Sopenharmony_ci		jfs_error(ip->i_sb, "inum = %d, iagno = %d, nextiag = %d\n",
87662306a36Sopenharmony_ci			  (uint) inum, iagno, imap->im_nextiag);
87762306a36Sopenharmony_ci		return -EIO;
87862306a36Sopenharmony_ci	}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	/* get the allocation group for this ino.
88162306a36Sopenharmony_ci	 */
88262306a36Sopenharmony_ci	agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb));
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	/* Lock the AG specific inode map information
88562306a36Sopenharmony_ci	 */
88662306a36Sopenharmony_ci	AG_LOCK(imap, agno);
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	/* Obtain read lock in imap inode.  Don't release it until we have
88962306a36Sopenharmony_ci	 * read all of the IAG's that we are going to.
89062306a36Sopenharmony_ci	 */
89162306a36Sopenharmony_ci	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	/* read the iag.
89462306a36Sopenharmony_ci	 */
89562306a36Sopenharmony_ci	if ((rc = diIAGRead(imap, iagno, &mp))) {
89662306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
89762306a36Sopenharmony_ci		AG_UNLOCK(imap, agno);
89862306a36Sopenharmony_ci		return (rc);
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	/* get the inode number and extent number of the inode within
90362306a36Sopenharmony_ci	 * the iag and the inode number within the extent.
90462306a36Sopenharmony_ci	 */
90562306a36Sopenharmony_ci	ino = inum & (INOSPERIAG - 1);
90662306a36Sopenharmony_ci	extno = ino >> L2INOSPEREXT;
90762306a36Sopenharmony_ci	bitno = ino & (INOSPEREXT - 1);
90862306a36Sopenharmony_ci	mask = HIGHORDER >> bitno;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
91162306a36Sopenharmony_ci		jfs_error(ip->i_sb, "wmap shows inode already free\n");
91262306a36Sopenharmony_ci	}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (!addressPXD(&iagp->inoext[extno])) {
91562306a36Sopenharmony_ci		release_metapage(mp);
91662306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
91762306a36Sopenharmony_ci		AG_UNLOCK(imap, agno);
91862306a36Sopenharmony_ci		jfs_error(ip->i_sb, "invalid inoext\n");
91962306a36Sopenharmony_ci		return -EIO;
92062306a36Sopenharmony_ci	}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	/* compute the bitmap for the extent reflecting the freed inode.
92362306a36Sopenharmony_ci	 */
92462306a36Sopenharmony_ci	bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) {
92762306a36Sopenharmony_ci		release_metapage(mp);
92862306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
92962306a36Sopenharmony_ci		AG_UNLOCK(imap, agno);
93062306a36Sopenharmony_ci		jfs_error(ip->i_sb, "numfree > numinos\n");
93162306a36Sopenharmony_ci		return -EIO;
93262306a36Sopenharmony_ci	}
93362306a36Sopenharmony_ci	/*
93462306a36Sopenharmony_ci	 *	inode extent still has some inodes or below low water mark:
93562306a36Sopenharmony_ci	 *	keep the inode extent;
93662306a36Sopenharmony_ci	 */
93762306a36Sopenharmony_ci	if (bitmap ||
93862306a36Sopenharmony_ci	    imap->im_agctl[agno].numfree < 96 ||
93962306a36Sopenharmony_ci	    (imap->im_agctl[agno].numfree < 288 &&
94062306a36Sopenharmony_ci	     (((imap->im_agctl[agno].numfree * 100) /
94162306a36Sopenharmony_ci	       imap->im_agctl[agno].numinos) <= 25))) {
94262306a36Sopenharmony_ci		/* if the iag currently has no free inodes (i.e.,
94362306a36Sopenharmony_ci		 * the inode being freed is the first free inode of iag),
94462306a36Sopenharmony_ci		 * insert the iag at head of the inode free list for the ag.
94562306a36Sopenharmony_ci		 */
94662306a36Sopenharmony_ci		if (iagp->nfreeinos == 0) {
94762306a36Sopenharmony_ci			/* check if there are any iags on the ag inode
94862306a36Sopenharmony_ci			 * free list.  if so, read the first one so that
94962306a36Sopenharmony_ci			 * we can link the current iag onto the list at
95062306a36Sopenharmony_ci			 * the head.
95162306a36Sopenharmony_ci			 */
95262306a36Sopenharmony_ci			if ((fwd = imap->im_agctl[agno].inofree) >= 0) {
95362306a36Sopenharmony_ci				/* read the iag that currently is the head
95462306a36Sopenharmony_ci				 * of the list.
95562306a36Sopenharmony_ci				 */
95662306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, fwd, &amp))) {
95762306a36Sopenharmony_ci					IREAD_UNLOCK(ipimap);
95862306a36Sopenharmony_ci					AG_UNLOCK(imap, agno);
95962306a36Sopenharmony_ci					release_metapage(mp);
96062306a36Sopenharmony_ci					return (rc);
96162306a36Sopenharmony_ci				}
96262306a36Sopenharmony_ci				aiagp = (struct iag *) amp->data;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci				/* make current head point back to the iag.
96562306a36Sopenharmony_ci				 */
96662306a36Sopenharmony_ci				aiagp->inofreeback = cpu_to_le32(iagno);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci				write_metapage(amp);
96962306a36Sopenharmony_ci			}
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci			/* iag points forward to current head and iag
97262306a36Sopenharmony_ci			 * becomes the new head of the list.
97362306a36Sopenharmony_ci			 */
97462306a36Sopenharmony_ci			iagp->inofreefwd =
97562306a36Sopenharmony_ci			    cpu_to_le32(imap->im_agctl[agno].inofree);
97662306a36Sopenharmony_ci			iagp->inofreeback = cpu_to_le32(-1);
97762306a36Sopenharmony_ci			imap->im_agctl[agno].inofree = iagno;
97862306a36Sopenharmony_ci		}
97962306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci		/* update the free inode summary map for the extent if
98262306a36Sopenharmony_ci		 * freeing the inode means the extent will now have free
98362306a36Sopenharmony_ci		 * inodes (i.e., the inode being freed is the first free
98462306a36Sopenharmony_ci		 * inode of extent),
98562306a36Sopenharmony_ci		 */
98662306a36Sopenharmony_ci		if (iagp->wmap[extno] == cpu_to_le32(ONES)) {
98762306a36Sopenharmony_ci			sword = extno >> L2EXTSPERSUM;
98862306a36Sopenharmony_ci			bitno = extno & (EXTSPERSUM - 1);
98962306a36Sopenharmony_ci			iagp->inosmap[sword] &=
99062306a36Sopenharmony_ci			    cpu_to_le32(~(HIGHORDER >> bitno));
99162306a36Sopenharmony_ci		}
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci		/* update the bitmap.
99462306a36Sopenharmony_ci		 */
99562306a36Sopenharmony_ci		iagp->wmap[extno] = cpu_to_le32(bitmap);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci		/* update the free inode counts at the iag, ag and
99862306a36Sopenharmony_ci		 * map level.
99962306a36Sopenharmony_ci		 */
100062306a36Sopenharmony_ci		le32_add_cpu(&iagp->nfreeinos, 1);
100162306a36Sopenharmony_ci		imap->im_agctl[agno].numfree += 1;
100262306a36Sopenharmony_ci		atomic_inc(&imap->im_numfree);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		/* release the AG inode map lock
100562306a36Sopenharmony_ci		 */
100662306a36Sopenharmony_ci		AG_UNLOCK(imap, agno);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci		/* write the iag */
100962306a36Sopenharmony_ci		write_metapage(mp);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci		return (0);
101262306a36Sopenharmony_ci	}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	/*
101662306a36Sopenharmony_ci	 *	inode extent has become free and above low water mark:
101762306a36Sopenharmony_ci	 *	free the inode extent;
101862306a36Sopenharmony_ci	 */
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	/*
102162306a36Sopenharmony_ci	 *	prepare to update iag list(s) (careful update step 1)
102262306a36Sopenharmony_ci	 */
102362306a36Sopenharmony_ci	amp = bmp = cmp = dmp = NULL;
102462306a36Sopenharmony_ci	fwd = back = -1;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	/* check if the iag currently has no free extents.  if so,
102762306a36Sopenharmony_ci	 * it will be placed on the head of the ag extent free list.
102862306a36Sopenharmony_ci	 */
102962306a36Sopenharmony_ci	if (iagp->nfreeexts == 0) {
103062306a36Sopenharmony_ci		/* check if the ag extent free list has any iags.
103162306a36Sopenharmony_ci		 * if so, read the iag at the head of the list now.
103262306a36Sopenharmony_ci		 * this (head) iag will be updated later to reflect
103362306a36Sopenharmony_ci		 * the addition of the current iag at the head of
103462306a36Sopenharmony_ci		 * the list.
103562306a36Sopenharmony_ci		 */
103662306a36Sopenharmony_ci		if ((fwd = imap->im_agctl[agno].extfree) >= 0) {
103762306a36Sopenharmony_ci			if ((rc = diIAGRead(imap, fwd, &amp)))
103862306a36Sopenharmony_ci				goto error_out;
103962306a36Sopenharmony_ci			aiagp = (struct iag *) amp->data;
104062306a36Sopenharmony_ci		}
104162306a36Sopenharmony_ci	} else {
104262306a36Sopenharmony_ci		/* iag has free extents. check if the addition of a free
104362306a36Sopenharmony_ci		 * extent will cause all extents to be free within this
104462306a36Sopenharmony_ci		 * iag.  if so, the iag will be removed from the ag extent
104562306a36Sopenharmony_ci		 * free list and placed on the inode map's free iag list.
104662306a36Sopenharmony_ci		 */
104762306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) {
104862306a36Sopenharmony_ci			/* in preparation for removing the iag from the
104962306a36Sopenharmony_ci			 * ag extent free list, read the iags preceding
105062306a36Sopenharmony_ci			 * and following the iag on the ag extent free
105162306a36Sopenharmony_ci			 * list.
105262306a36Sopenharmony_ci			 */
105362306a36Sopenharmony_ci			if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) {
105462306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, fwd, &amp)))
105562306a36Sopenharmony_ci					goto error_out;
105662306a36Sopenharmony_ci				aiagp = (struct iag *) amp->data;
105762306a36Sopenharmony_ci			}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci			if ((back = le32_to_cpu(iagp->extfreeback)) >= 0) {
106062306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, back, &bmp)))
106162306a36Sopenharmony_ci					goto error_out;
106262306a36Sopenharmony_ci				biagp = (struct iag *) bmp->data;
106362306a36Sopenharmony_ci			}
106462306a36Sopenharmony_ci		}
106562306a36Sopenharmony_ci	}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	/* remove the iag from the ag inode free list if freeing
106862306a36Sopenharmony_ci	 * this extent cause the iag to have no free inodes.
106962306a36Sopenharmony_ci	 */
107062306a36Sopenharmony_ci	if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) {
107162306a36Sopenharmony_ci		int inofreeback = le32_to_cpu(iagp->inofreeback);
107262306a36Sopenharmony_ci		int inofreefwd = le32_to_cpu(iagp->inofreefwd);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		/* in preparation for removing the iag from the
107562306a36Sopenharmony_ci		 * ag inode free list, read the iags preceding
107662306a36Sopenharmony_ci		 * and following the iag on the ag inode free
107762306a36Sopenharmony_ci		 * list.  before reading these iags, we must make
107862306a36Sopenharmony_ci		 * sure that we already don't have them in hand
107962306a36Sopenharmony_ci		 * from up above, since re-reading an iag (buffer)
108062306a36Sopenharmony_ci		 * we are currently holding would cause a deadlock.
108162306a36Sopenharmony_ci		 */
108262306a36Sopenharmony_ci		if (inofreefwd >= 0) {
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci			if (inofreefwd == fwd)
108562306a36Sopenharmony_ci				ciagp = (struct iag *) amp->data;
108662306a36Sopenharmony_ci			else if (inofreefwd == back)
108762306a36Sopenharmony_ci				ciagp = (struct iag *) bmp->data;
108862306a36Sopenharmony_ci			else {
108962306a36Sopenharmony_ci				if ((rc =
109062306a36Sopenharmony_ci				     diIAGRead(imap, inofreefwd, &cmp)))
109162306a36Sopenharmony_ci					goto error_out;
109262306a36Sopenharmony_ci				ciagp = (struct iag *) cmp->data;
109362306a36Sopenharmony_ci			}
109462306a36Sopenharmony_ci			assert(ciagp != NULL);
109562306a36Sopenharmony_ci		}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci		if (inofreeback >= 0) {
109862306a36Sopenharmony_ci			if (inofreeback == fwd)
109962306a36Sopenharmony_ci				diagp = (struct iag *) amp->data;
110062306a36Sopenharmony_ci			else if (inofreeback == back)
110162306a36Sopenharmony_ci				diagp = (struct iag *) bmp->data;
110262306a36Sopenharmony_ci			else {
110362306a36Sopenharmony_ci				if ((rc =
110462306a36Sopenharmony_ci				     diIAGRead(imap, inofreeback, &dmp)))
110562306a36Sopenharmony_ci					goto error_out;
110662306a36Sopenharmony_ci				diagp = (struct iag *) dmp->data;
110762306a36Sopenharmony_ci			}
110862306a36Sopenharmony_ci			assert(diagp != NULL);
110962306a36Sopenharmony_ci		}
111062306a36Sopenharmony_ci	}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	IREAD_UNLOCK(ipimap);
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	/*
111562306a36Sopenharmony_ci	 * invalidate any page of the inode extent freed from buffer cache;
111662306a36Sopenharmony_ci	 */
111762306a36Sopenharmony_ci	freepxd = iagp->inoext[extno];
111862306a36Sopenharmony_ci	invalidate_pxd_metapages(ip, freepxd);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	/*
112162306a36Sopenharmony_ci	 *	update iag list(s) (careful update step 2)
112262306a36Sopenharmony_ci	 */
112362306a36Sopenharmony_ci	/* add the iag to the ag extent free list if this is the
112462306a36Sopenharmony_ci	 * first free extent for the iag.
112562306a36Sopenharmony_ci	 */
112662306a36Sopenharmony_ci	if (iagp->nfreeexts == 0) {
112762306a36Sopenharmony_ci		if (fwd >= 0)
112862306a36Sopenharmony_ci			aiagp->extfreeback = cpu_to_le32(iagno);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci		iagp->extfreefwd =
113162306a36Sopenharmony_ci		    cpu_to_le32(imap->im_agctl[agno].extfree);
113262306a36Sopenharmony_ci		iagp->extfreeback = cpu_to_le32(-1);
113362306a36Sopenharmony_ci		imap->im_agctl[agno].extfree = iagno;
113462306a36Sopenharmony_ci	} else {
113562306a36Sopenharmony_ci		/* remove the iag from the ag extent list if all extents
113662306a36Sopenharmony_ci		 * are now free and place it on the inode map iag free list.
113762306a36Sopenharmony_ci		 */
113862306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) {
113962306a36Sopenharmony_ci			if (fwd >= 0)
114062306a36Sopenharmony_ci				aiagp->extfreeback = iagp->extfreeback;
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci			if (back >= 0)
114362306a36Sopenharmony_ci				biagp->extfreefwd = iagp->extfreefwd;
114462306a36Sopenharmony_ci			else
114562306a36Sopenharmony_ci				imap->im_agctl[agno].extfree =
114662306a36Sopenharmony_ci				    le32_to_cpu(iagp->extfreefwd);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci			iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci			IAGFREE_LOCK(imap);
115162306a36Sopenharmony_ci			iagp->iagfree = cpu_to_le32(imap->im_freeiag);
115262306a36Sopenharmony_ci			imap->im_freeiag = iagno;
115362306a36Sopenharmony_ci			IAGFREE_UNLOCK(imap);
115462306a36Sopenharmony_ci		}
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	/* remove the iag from the ag inode free list if freeing
115862306a36Sopenharmony_ci	 * this extent causes the iag to have no free inodes.
115962306a36Sopenharmony_ci	 */
116062306a36Sopenharmony_ci	if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) {
116162306a36Sopenharmony_ci		if ((int) le32_to_cpu(iagp->inofreefwd) >= 0)
116262306a36Sopenharmony_ci			ciagp->inofreeback = iagp->inofreeback;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci		if ((int) le32_to_cpu(iagp->inofreeback) >= 0)
116562306a36Sopenharmony_ci			diagp->inofreefwd = iagp->inofreefwd;
116662306a36Sopenharmony_ci		else
116762306a36Sopenharmony_ci			imap->im_agctl[agno].inofree =
116862306a36Sopenharmony_ci			    le32_to_cpu(iagp->inofreefwd);
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci		iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
117162306a36Sopenharmony_ci	}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	/* update the inode extent address and working map
117462306a36Sopenharmony_ci	 * to reflect the free extent.
117562306a36Sopenharmony_ci	 * the permanent map should have been updated already
117662306a36Sopenharmony_ci	 * for the inode being freed.
117762306a36Sopenharmony_ci	 */
117862306a36Sopenharmony_ci	if (iagp->pmap[extno] != 0) {
117962306a36Sopenharmony_ci		jfs_error(ip->i_sb, "the pmap does not show inode free\n");
118062306a36Sopenharmony_ci	}
118162306a36Sopenharmony_ci	iagp->wmap[extno] = 0;
118262306a36Sopenharmony_ci	PXDlength(&iagp->inoext[extno], 0);
118362306a36Sopenharmony_ci	PXDaddress(&iagp->inoext[extno], 0);
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	/* update the free extent and free inode summary maps
118662306a36Sopenharmony_ci	 * to reflect the freed extent.
118762306a36Sopenharmony_ci	 * the inode summary map is marked to indicate no inodes
118862306a36Sopenharmony_ci	 * available for the freed extent.
118962306a36Sopenharmony_ci	 */
119062306a36Sopenharmony_ci	sword = extno >> L2EXTSPERSUM;
119162306a36Sopenharmony_ci	bitno = extno & (EXTSPERSUM - 1);
119262306a36Sopenharmony_ci	mask = HIGHORDER >> bitno;
119362306a36Sopenharmony_ci	iagp->inosmap[sword] |= cpu_to_le32(mask);
119462306a36Sopenharmony_ci	iagp->extsmap[sword] &= cpu_to_le32(~mask);
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	/* update the number of free inodes and number of free extents
119762306a36Sopenharmony_ci	 * for the iag.
119862306a36Sopenharmony_ci	 */
119962306a36Sopenharmony_ci	le32_add_cpu(&iagp->nfreeinos, -(INOSPEREXT - 1));
120062306a36Sopenharmony_ci	le32_add_cpu(&iagp->nfreeexts, 1);
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	/* update the number of free inodes and backed inodes
120362306a36Sopenharmony_ci	 * at the ag and inode map level.
120462306a36Sopenharmony_ci	 */
120562306a36Sopenharmony_ci	imap->im_agctl[agno].numfree -= (INOSPEREXT - 1);
120662306a36Sopenharmony_ci	imap->im_agctl[agno].numinos -= INOSPEREXT;
120762306a36Sopenharmony_ci	atomic_sub(INOSPEREXT - 1, &imap->im_numfree);
120862306a36Sopenharmony_ci	atomic_sub(INOSPEREXT, &imap->im_numinos);
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	if (amp)
121162306a36Sopenharmony_ci		write_metapage(amp);
121262306a36Sopenharmony_ci	if (bmp)
121362306a36Sopenharmony_ci		write_metapage(bmp);
121462306a36Sopenharmony_ci	if (cmp)
121562306a36Sopenharmony_ci		write_metapage(cmp);
121662306a36Sopenharmony_ci	if (dmp)
121762306a36Sopenharmony_ci		write_metapage(dmp);
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	/*
122062306a36Sopenharmony_ci	 * start transaction to update block allocation map
122162306a36Sopenharmony_ci	 * for the inode extent freed;
122262306a36Sopenharmony_ci	 *
122362306a36Sopenharmony_ci	 * N.B. AG_LOCK is released and iag will be released below, and
122462306a36Sopenharmony_ci	 * other thread may allocate inode from/reusing the ixad freed
122562306a36Sopenharmony_ci	 * BUT with new/different backing inode extent from the extent
122662306a36Sopenharmony_ci	 * to be freed by the transaction;
122762306a36Sopenharmony_ci	 */
122862306a36Sopenharmony_ci	tid = txBegin(ipimap->i_sb, COMMIT_FORCE);
122962306a36Sopenharmony_ci	mutex_lock(&JFS_IP(ipimap)->commit_mutex);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	/* acquire tlock of the iag page of the freed ixad
123262306a36Sopenharmony_ci	 * to force the page NOHOMEOK (even though no data is
123362306a36Sopenharmony_ci	 * logged from the iag page) until NOREDOPAGE|FREEXTENT log
123462306a36Sopenharmony_ci	 * for the free of the extent is committed;
123562306a36Sopenharmony_ci	 * write FREEXTENT|NOREDOPAGE log record
123662306a36Sopenharmony_ci	 * N.B. linelock is overlaid as freed extent descriptor;
123762306a36Sopenharmony_ci	 */
123862306a36Sopenharmony_ci	tlck = txLock(tid, ipimap, mp, tlckINODE | tlckFREE);
123962306a36Sopenharmony_ci	pxdlock = (struct pxd_lock *) & tlck->lock;
124062306a36Sopenharmony_ci	pxdlock->flag = mlckFREEPXD;
124162306a36Sopenharmony_ci	pxdlock->pxd = freepxd;
124262306a36Sopenharmony_ci	pxdlock->index = 1;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	write_metapage(mp);
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	iplist[0] = ipimap;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/*
124962306a36Sopenharmony_ci	 * logredo needs the IAG number and IAG extent index in order
125062306a36Sopenharmony_ci	 * to ensure that the IMap is consistent.  The least disruptive
125162306a36Sopenharmony_ci	 * way to pass these values through  to the transaction manager
125262306a36Sopenharmony_ci	 * is in the iplist array.
125362306a36Sopenharmony_ci	 *
125462306a36Sopenharmony_ci	 * It's not pretty, but it works.
125562306a36Sopenharmony_ci	 */
125662306a36Sopenharmony_ci	iplist[1] = (struct inode *) (size_t)iagno;
125762306a36Sopenharmony_ci	iplist[2] = (struct inode *) (size_t)extno;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	txEnd(tid);
126262306a36Sopenharmony_ci	mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	/* unlock the AG inode map information */
126562306a36Sopenharmony_ci	AG_UNLOCK(imap, agno);
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	return (0);
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci      error_out:
127062306a36Sopenharmony_ci	IREAD_UNLOCK(ipimap);
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	if (amp)
127362306a36Sopenharmony_ci		release_metapage(amp);
127462306a36Sopenharmony_ci	if (bmp)
127562306a36Sopenharmony_ci		release_metapage(bmp);
127662306a36Sopenharmony_ci	if (cmp)
127762306a36Sopenharmony_ci		release_metapage(cmp);
127862306a36Sopenharmony_ci	if (dmp)
127962306a36Sopenharmony_ci		release_metapage(dmp);
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	AG_UNLOCK(imap, agno);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	release_metapage(mp);
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	return (rc);
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci/*
128962306a36Sopenharmony_ci * There are several places in the diAlloc* routines where we initialize
129062306a36Sopenharmony_ci * the inode.
129162306a36Sopenharmony_ci */
129262306a36Sopenharmony_cistatic inline void
129362306a36Sopenharmony_cidiInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
129462306a36Sopenharmony_ci{
129562306a36Sopenharmony_ci	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	ip->i_ino = (iagno << L2INOSPERIAG) + ino;
129862306a36Sopenharmony_ci	jfs_ip->ixpxd = iagp->inoext[extno];
129962306a36Sopenharmony_ci	jfs_ip->agstart = le64_to_cpu(iagp->agstart);
130062306a36Sopenharmony_ci	jfs_ip->active_ag = -1;
130162306a36Sopenharmony_ci}
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci/*
130562306a36Sopenharmony_ci * NAME:	diAlloc(pip,dir,ip)
130662306a36Sopenharmony_ci *
130762306a36Sopenharmony_ci * FUNCTION:	allocate a disk inode from the inode working map
130862306a36Sopenharmony_ci *		for a fileset or aggregate.
130962306a36Sopenharmony_ci *
131062306a36Sopenharmony_ci * PARAMETERS:
131162306a36Sopenharmony_ci *	pip	- pointer to incore inode for the parent inode.
131262306a36Sopenharmony_ci *	dir	- 'true' if the new disk inode is for a directory.
131362306a36Sopenharmony_ci *	ip	- pointer to a new inode
131462306a36Sopenharmony_ci *
131562306a36Sopenharmony_ci * RETURN VALUES:
131662306a36Sopenharmony_ci *	0	- success.
131762306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
131862306a36Sopenharmony_ci *	-EIO	- i/o error.
131962306a36Sopenharmony_ci */
132062306a36Sopenharmony_ciint diAlloc(struct inode *pip, bool dir, struct inode *ip)
132162306a36Sopenharmony_ci{
132262306a36Sopenharmony_ci	int rc, ino, iagno, addext, extno, bitno, sword;
132362306a36Sopenharmony_ci	int nwords, rem, i, agno, dn_numag;
132462306a36Sopenharmony_ci	u32 mask, inosmap, extsmap;
132562306a36Sopenharmony_ci	struct inode *ipimap;
132662306a36Sopenharmony_ci	struct metapage *mp;
132762306a36Sopenharmony_ci	ino_t inum;
132862306a36Sopenharmony_ci	struct iag *iagp;
132962306a36Sopenharmony_ci	struct inomap *imap;
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	/* get the pointers to the inode map inode and the
133262306a36Sopenharmony_ci	 * corresponding imap control structure.
133362306a36Sopenharmony_ci	 */
133462306a36Sopenharmony_ci	ipimap = JFS_SBI(pip->i_sb)->ipimap;
133562306a36Sopenharmony_ci	imap = JFS_IP(ipimap)->i_imap;
133662306a36Sopenharmony_ci	JFS_IP(ip)->ipimap = ipimap;
133762306a36Sopenharmony_ci	JFS_IP(ip)->fileset = FILESYSTEM_I;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	/* for a directory, the allocation policy is to start
134062306a36Sopenharmony_ci	 * at the ag level using the preferred ag.
134162306a36Sopenharmony_ci	 */
134262306a36Sopenharmony_ci	if (dir) {
134362306a36Sopenharmony_ci		agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
134462306a36Sopenharmony_ci		AG_LOCK(imap, agno);
134562306a36Sopenharmony_ci		goto tryag;
134662306a36Sopenharmony_ci	}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	/* for files, the policy starts off by trying to allocate from
134962306a36Sopenharmony_ci	 * the same iag containing the parent disk inode:
135062306a36Sopenharmony_ci	 * try to allocate the new disk inode close to the parent disk
135162306a36Sopenharmony_ci	 * inode, using parent disk inode number + 1 as the allocation
135262306a36Sopenharmony_ci	 * hint.  (we use a left-to-right policy to attempt to avoid
135362306a36Sopenharmony_ci	 * moving backward on the disk.)  compute the hint within the
135462306a36Sopenharmony_ci	 * file system and the iag.
135562306a36Sopenharmony_ci	 */
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	/* get the ag number of this iag */
135862306a36Sopenharmony_ci	agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb));
135962306a36Sopenharmony_ci	dn_numag = JFS_SBI(pip->i_sb)->bmap->db_numag;
136062306a36Sopenharmony_ci	if (agno < 0 || agno > dn_numag)
136162306a36Sopenharmony_ci		return -EIO;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
136462306a36Sopenharmony_ci		/*
136562306a36Sopenharmony_ci		 * There is an open file actively growing.  We want to
136662306a36Sopenharmony_ci		 * allocate new inodes from a different ag to avoid
136762306a36Sopenharmony_ci		 * fragmentation problems.
136862306a36Sopenharmony_ci		 */
136962306a36Sopenharmony_ci		agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
137062306a36Sopenharmony_ci		AG_LOCK(imap, agno);
137162306a36Sopenharmony_ci		goto tryag;
137262306a36Sopenharmony_ci	}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	inum = pip->i_ino + 1;
137562306a36Sopenharmony_ci	ino = inum & (INOSPERIAG - 1);
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	/* back off the hint if it is outside of the iag */
137862306a36Sopenharmony_ci	if (ino == 0)
137962306a36Sopenharmony_ci		inum = pip->i_ino;
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	/* lock the AG inode map information */
138262306a36Sopenharmony_ci	AG_LOCK(imap, agno);
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	/* Get read lock on imap inode */
138562306a36Sopenharmony_ci	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	/* get the iag number and read the iag */
138862306a36Sopenharmony_ci	iagno = INOTOIAG(inum);
138962306a36Sopenharmony_ci	if ((rc = diIAGRead(imap, iagno, &mp))) {
139062306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
139162306a36Sopenharmony_ci		AG_UNLOCK(imap, agno);
139262306a36Sopenharmony_ci		return (rc);
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	/* determine if new inode extent is allowed to be added to the iag.
139762306a36Sopenharmony_ci	 * new inode extent can be added to the iag if the ag
139862306a36Sopenharmony_ci	 * has less than 32 free disk inodes and the iag has free extents.
139962306a36Sopenharmony_ci	 */
140062306a36Sopenharmony_ci	addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	/*
140362306a36Sopenharmony_ci	 *	try to allocate from the IAG
140462306a36Sopenharmony_ci	 */
140562306a36Sopenharmony_ci	/* check if the inode may be allocated from the iag
140662306a36Sopenharmony_ci	 * (i.e. the inode has free inodes or new extent can be added).
140762306a36Sopenharmony_ci	 */
140862306a36Sopenharmony_ci	if (iagp->nfreeinos || addext) {
140962306a36Sopenharmony_ci		/* determine the extent number of the hint.
141062306a36Sopenharmony_ci		 */
141162306a36Sopenharmony_ci		extno = ino >> L2INOSPEREXT;
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci		/* check if the extent containing the hint has backed
141462306a36Sopenharmony_ci		 * inodes.  if so, try to allocate within this extent.
141562306a36Sopenharmony_ci		 */
141662306a36Sopenharmony_ci		if (addressPXD(&iagp->inoext[extno])) {
141762306a36Sopenharmony_ci			bitno = ino & (INOSPEREXT - 1);
141862306a36Sopenharmony_ci			if ((bitno =
141962306a36Sopenharmony_ci			     diFindFree(le32_to_cpu(iagp->wmap[extno]),
142062306a36Sopenharmony_ci					bitno))
142162306a36Sopenharmony_ci			    < INOSPEREXT) {
142262306a36Sopenharmony_ci				ino = (extno << L2INOSPEREXT) + bitno;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci				/* a free inode (bit) was found within this
142562306a36Sopenharmony_ci				 * extent, so allocate it.
142662306a36Sopenharmony_ci				 */
142762306a36Sopenharmony_ci				rc = diAllocBit(imap, iagp, ino);
142862306a36Sopenharmony_ci				IREAD_UNLOCK(ipimap);
142962306a36Sopenharmony_ci				if (rc) {
143062306a36Sopenharmony_ci					assert(rc == -EIO);
143162306a36Sopenharmony_ci				} else {
143262306a36Sopenharmony_ci					/* set the results of the allocation
143362306a36Sopenharmony_ci					 * and write the iag.
143462306a36Sopenharmony_ci					 */
143562306a36Sopenharmony_ci					diInitInode(ip, iagno, ino, extno,
143662306a36Sopenharmony_ci						    iagp);
143762306a36Sopenharmony_ci					mark_metapage_dirty(mp);
143862306a36Sopenharmony_ci				}
143962306a36Sopenharmony_ci				release_metapage(mp);
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci				/* free the AG lock and return.
144262306a36Sopenharmony_ci				 */
144362306a36Sopenharmony_ci				AG_UNLOCK(imap, agno);
144462306a36Sopenharmony_ci				return (rc);
144562306a36Sopenharmony_ci			}
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci			if (!addext)
144862306a36Sopenharmony_ci				extno =
144962306a36Sopenharmony_ci				    (extno ==
145062306a36Sopenharmony_ci				     EXTSPERIAG - 1) ? 0 : extno + 1;
145162306a36Sopenharmony_ci		}
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci		/*
145462306a36Sopenharmony_ci		 * no free inodes within the extent containing the hint.
145562306a36Sopenharmony_ci		 *
145662306a36Sopenharmony_ci		 * try to allocate from the backed extents following
145762306a36Sopenharmony_ci		 * hint or, if appropriate (i.e. addext is true), allocate
145862306a36Sopenharmony_ci		 * an extent of free inodes at or following the extent
145962306a36Sopenharmony_ci		 * containing the hint.
146062306a36Sopenharmony_ci		 *
146162306a36Sopenharmony_ci		 * the free inode and free extent summary maps are used
146262306a36Sopenharmony_ci		 * here, so determine the starting summary map position
146362306a36Sopenharmony_ci		 * and the number of words we'll have to examine.  again,
146462306a36Sopenharmony_ci		 * the approach is to allocate following the hint, so we
146562306a36Sopenharmony_ci		 * might have to initially ignore prior bits of the summary
146662306a36Sopenharmony_ci		 * map that represent extents prior to the extent containing
146762306a36Sopenharmony_ci		 * the hint and later revisit these bits.
146862306a36Sopenharmony_ci		 */
146962306a36Sopenharmony_ci		bitno = extno & (EXTSPERSUM - 1);
147062306a36Sopenharmony_ci		nwords = (bitno == 0) ? SMAPSZ : SMAPSZ + 1;
147162306a36Sopenharmony_ci		sword = extno >> L2EXTSPERSUM;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci		/* mask any prior bits for the starting words of the
147462306a36Sopenharmony_ci		 * summary map.
147562306a36Sopenharmony_ci		 */
147662306a36Sopenharmony_ci		mask = (bitno == 0) ? 0 : (ONES << (EXTSPERSUM - bitno));
147762306a36Sopenharmony_ci		inosmap = le32_to_cpu(iagp->inosmap[sword]) | mask;
147862306a36Sopenharmony_ci		extsmap = le32_to_cpu(iagp->extsmap[sword]) | mask;
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci		/* scan the free inode and free extent summary maps for
148162306a36Sopenharmony_ci		 * free resources.
148262306a36Sopenharmony_ci		 */
148362306a36Sopenharmony_ci		for (i = 0; i < nwords; i++) {
148462306a36Sopenharmony_ci			/* check if this word of the free inode summary
148562306a36Sopenharmony_ci			 * map describes an extent with free inodes.
148662306a36Sopenharmony_ci			 */
148762306a36Sopenharmony_ci			if (~inosmap) {
148862306a36Sopenharmony_ci				/* an extent with free inodes has been
148962306a36Sopenharmony_ci				 * found. determine the extent number
149062306a36Sopenharmony_ci				 * and the inode number within the extent.
149162306a36Sopenharmony_ci				 */
149262306a36Sopenharmony_ci				rem = diFindFree(inosmap, 0);
149362306a36Sopenharmony_ci				extno = (sword << L2EXTSPERSUM) + rem;
149462306a36Sopenharmony_ci				rem = diFindFree(le32_to_cpu(iagp->wmap[extno]),
149562306a36Sopenharmony_ci						 0);
149662306a36Sopenharmony_ci				if (rem >= INOSPEREXT) {
149762306a36Sopenharmony_ci					IREAD_UNLOCK(ipimap);
149862306a36Sopenharmony_ci					release_metapage(mp);
149962306a36Sopenharmony_ci					AG_UNLOCK(imap, agno);
150062306a36Sopenharmony_ci					jfs_error(ip->i_sb,
150162306a36Sopenharmony_ci						  "can't find free bit in wmap\n");
150262306a36Sopenharmony_ci					return -EIO;
150362306a36Sopenharmony_ci				}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci				/* determine the inode number within the
150662306a36Sopenharmony_ci				 * iag and allocate the inode from the
150762306a36Sopenharmony_ci				 * map.
150862306a36Sopenharmony_ci				 */
150962306a36Sopenharmony_ci				ino = (extno << L2INOSPEREXT) + rem;
151062306a36Sopenharmony_ci				rc = diAllocBit(imap, iagp, ino);
151162306a36Sopenharmony_ci				IREAD_UNLOCK(ipimap);
151262306a36Sopenharmony_ci				if (rc)
151362306a36Sopenharmony_ci					assert(rc == -EIO);
151462306a36Sopenharmony_ci				else {
151562306a36Sopenharmony_ci					/* set the results of the allocation
151662306a36Sopenharmony_ci					 * and write the iag.
151762306a36Sopenharmony_ci					 */
151862306a36Sopenharmony_ci					diInitInode(ip, iagno, ino, extno,
151962306a36Sopenharmony_ci						    iagp);
152062306a36Sopenharmony_ci					mark_metapage_dirty(mp);
152162306a36Sopenharmony_ci				}
152262306a36Sopenharmony_ci				release_metapage(mp);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci				/* free the AG lock and return.
152562306a36Sopenharmony_ci				 */
152662306a36Sopenharmony_ci				AG_UNLOCK(imap, agno);
152762306a36Sopenharmony_ci				return (rc);
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci			}
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci			/* check if we may allocate an extent of free
153262306a36Sopenharmony_ci			 * inodes and whether this word of the free
153362306a36Sopenharmony_ci			 * extents summary map describes a free extent.
153462306a36Sopenharmony_ci			 */
153562306a36Sopenharmony_ci			if (addext && ~extsmap) {
153662306a36Sopenharmony_ci				/* a free extent has been found.  determine
153762306a36Sopenharmony_ci				 * the extent number.
153862306a36Sopenharmony_ci				 */
153962306a36Sopenharmony_ci				rem = diFindFree(extsmap, 0);
154062306a36Sopenharmony_ci				extno = (sword << L2EXTSPERSUM) + rem;
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci				/* allocate an extent of free inodes.
154362306a36Sopenharmony_ci				 */
154462306a36Sopenharmony_ci				if ((rc = diNewExt(imap, iagp, extno))) {
154562306a36Sopenharmony_ci					/* if there is no disk space for a
154662306a36Sopenharmony_ci					 * new extent, try to allocate the
154762306a36Sopenharmony_ci					 * disk inode from somewhere else.
154862306a36Sopenharmony_ci					 */
154962306a36Sopenharmony_ci					if (rc == -ENOSPC)
155062306a36Sopenharmony_ci						break;
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci					assert(rc == -EIO);
155362306a36Sopenharmony_ci				} else {
155462306a36Sopenharmony_ci					/* set the results of the allocation
155562306a36Sopenharmony_ci					 * and write the iag.
155662306a36Sopenharmony_ci					 */
155762306a36Sopenharmony_ci					diInitInode(ip, iagno,
155862306a36Sopenharmony_ci						    extno << L2INOSPEREXT,
155962306a36Sopenharmony_ci						    extno, iagp);
156062306a36Sopenharmony_ci					mark_metapage_dirty(mp);
156162306a36Sopenharmony_ci				}
156262306a36Sopenharmony_ci				release_metapage(mp);
156362306a36Sopenharmony_ci				/* free the imap inode & the AG lock & return.
156462306a36Sopenharmony_ci				 */
156562306a36Sopenharmony_ci				IREAD_UNLOCK(ipimap);
156662306a36Sopenharmony_ci				AG_UNLOCK(imap, agno);
156762306a36Sopenharmony_ci				return (rc);
156862306a36Sopenharmony_ci			}
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci			/* move on to the next set of summary map words.
157162306a36Sopenharmony_ci			 */
157262306a36Sopenharmony_ci			sword = (sword == SMAPSZ - 1) ? 0 : sword + 1;
157362306a36Sopenharmony_ci			inosmap = le32_to_cpu(iagp->inosmap[sword]);
157462306a36Sopenharmony_ci			extsmap = le32_to_cpu(iagp->extsmap[sword]);
157562306a36Sopenharmony_ci		}
157662306a36Sopenharmony_ci	}
157762306a36Sopenharmony_ci	/* unlock imap inode */
157862306a36Sopenharmony_ci	IREAD_UNLOCK(ipimap);
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	/* nothing doing in this iag, so release it. */
158162306a36Sopenharmony_ci	release_metapage(mp);
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci      tryag:
158462306a36Sopenharmony_ci	/*
158562306a36Sopenharmony_ci	 * try to allocate anywhere within the same AG as the parent inode.
158662306a36Sopenharmony_ci	 */
158762306a36Sopenharmony_ci	rc = diAllocAG(imap, agno, dir, ip);
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	AG_UNLOCK(imap, agno);
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	if (rc != -ENOSPC)
159262306a36Sopenharmony_ci		return (rc);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	/*
159562306a36Sopenharmony_ci	 * try to allocate in any AG.
159662306a36Sopenharmony_ci	 */
159762306a36Sopenharmony_ci	return (diAllocAny(imap, agno, dir, ip));
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci/*
160262306a36Sopenharmony_ci * NAME:	diAllocAG(imap,agno,dir,ip)
160362306a36Sopenharmony_ci *
160462306a36Sopenharmony_ci * FUNCTION:	allocate a disk inode from the allocation group.
160562306a36Sopenharmony_ci *
160662306a36Sopenharmony_ci *		this routine first determines if a new extent of free
160762306a36Sopenharmony_ci *		inodes should be added for the allocation group, with
160862306a36Sopenharmony_ci *		the current request satisfied from this extent. if this
160962306a36Sopenharmony_ci *		is the case, an attempt will be made to do just that.  if
161062306a36Sopenharmony_ci *		this attempt fails or it has been determined that a new
161162306a36Sopenharmony_ci *		extent should not be added, an attempt is made to satisfy
161262306a36Sopenharmony_ci *		the request by allocating an existing (backed) free inode
161362306a36Sopenharmony_ci *		from the allocation group.
161462306a36Sopenharmony_ci *
161562306a36Sopenharmony_ci * PRE CONDITION: Already have the AG lock for this AG.
161662306a36Sopenharmony_ci *
161762306a36Sopenharmony_ci * PARAMETERS:
161862306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
161962306a36Sopenharmony_ci *	agno	- allocation group to allocate from.
162062306a36Sopenharmony_ci *	dir	- 'true' if the new disk inode is for a directory.
162162306a36Sopenharmony_ci *	ip	- pointer to the new inode to be filled in on successful return
162262306a36Sopenharmony_ci *		  with the disk inode number allocated, its extent address
162362306a36Sopenharmony_ci *		  and the start of the ag.
162462306a36Sopenharmony_ci *
162562306a36Sopenharmony_ci * RETURN VALUES:
162662306a36Sopenharmony_ci *	0	- success.
162762306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
162862306a36Sopenharmony_ci *	-EIO	- i/o error.
162962306a36Sopenharmony_ci */
163062306a36Sopenharmony_cistatic int
163162306a36Sopenharmony_cidiAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
163262306a36Sopenharmony_ci{
163362306a36Sopenharmony_ci	int rc, addext, numfree, numinos;
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	/* get the number of free and the number of backed disk
163662306a36Sopenharmony_ci	 * inodes currently within the ag.
163762306a36Sopenharmony_ci	 */
163862306a36Sopenharmony_ci	numfree = imap->im_agctl[agno].numfree;
163962306a36Sopenharmony_ci	numinos = imap->im_agctl[agno].numinos;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	if (numfree > numinos) {
164262306a36Sopenharmony_ci		jfs_error(ip->i_sb, "numfree > numinos\n");
164362306a36Sopenharmony_ci		return -EIO;
164462306a36Sopenharmony_ci	}
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	/* determine if we should allocate a new extent of free inodes
164762306a36Sopenharmony_ci	 * within the ag: for directory inodes, add a new extent
164862306a36Sopenharmony_ci	 * if there are a small number of free inodes or number of free
164962306a36Sopenharmony_ci	 * inodes is a small percentage of the number of backed inodes.
165062306a36Sopenharmony_ci	 */
165162306a36Sopenharmony_ci	if (dir)
165262306a36Sopenharmony_ci		addext = (numfree < 64 ||
165362306a36Sopenharmony_ci			  (numfree < 256
165462306a36Sopenharmony_ci			   && ((numfree * 100) / numinos) <= 20));
165562306a36Sopenharmony_ci	else
165662306a36Sopenharmony_ci		addext = (numfree == 0);
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	/*
165962306a36Sopenharmony_ci	 * try to allocate a new extent of free inodes.
166062306a36Sopenharmony_ci	 */
166162306a36Sopenharmony_ci	if (addext) {
166262306a36Sopenharmony_ci		/* if free space is not available for this new extent, try
166362306a36Sopenharmony_ci		 * below to allocate a free and existing (already backed)
166462306a36Sopenharmony_ci		 * inode from the ag.
166562306a36Sopenharmony_ci		 */
166662306a36Sopenharmony_ci		if ((rc = diAllocExt(imap, agno, ip)) != -ENOSPC)
166762306a36Sopenharmony_ci			return (rc);
166862306a36Sopenharmony_ci	}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/*
167162306a36Sopenharmony_ci	 * try to allocate an existing free inode from the ag.
167262306a36Sopenharmony_ci	 */
167362306a36Sopenharmony_ci	return (diAllocIno(imap, agno, ip));
167462306a36Sopenharmony_ci}
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci/*
167862306a36Sopenharmony_ci * NAME:	diAllocAny(imap,agno,dir,iap)
167962306a36Sopenharmony_ci *
168062306a36Sopenharmony_ci * FUNCTION:	allocate a disk inode from any other allocation group.
168162306a36Sopenharmony_ci *
168262306a36Sopenharmony_ci *		this routine is called when an allocation attempt within
168362306a36Sopenharmony_ci *		the primary allocation group has failed. if attempts to
168462306a36Sopenharmony_ci *		allocate an inode from any allocation group other than the
168562306a36Sopenharmony_ci *		specified primary group.
168662306a36Sopenharmony_ci *
168762306a36Sopenharmony_ci * PARAMETERS:
168862306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
168962306a36Sopenharmony_ci *	agno	- primary allocation group (to avoid).
169062306a36Sopenharmony_ci *	dir	- 'true' if the new disk inode is for a directory.
169162306a36Sopenharmony_ci *	ip	- pointer to a new inode to be filled in on successful return
169262306a36Sopenharmony_ci *		  with the disk inode number allocated, its extent address
169362306a36Sopenharmony_ci *		  and the start of the ag.
169462306a36Sopenharmony_ci *
169562306a36Sopenharmony_ci * RETURN VALUES:
169662306a36Sopenharmony_ci *	0	- success.
169762306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
169862306a36Sopenharmony_ci *	-EIO	- i/o error.
169962306a36Sopenharmony_ci */
170062306a36Sopenharmony_cistatic int
170162306a36Sopenharmony_cidiAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
170262306a36Sopenharmony_ci{
170362306a36Sopenharmony_ci	int ag, rc;
170462306a36Sopenharmony_ci	int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag;
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_ci	/* try to allocate from the ags following agno up to
170862306a36Sopenharmony_ci	 * the maximum ag number.
170962306a36Sopenharmony_ci	 */
171062306a36Sopenharmony_ci	for (ag = agno + 1; ag <= maxag; ag++) {
171162306a36Sopenharmony_ci		AG_LOCK(imap, ag);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci		rc = diAllocAG(imap, ag, dir, ip);
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci		AG_UNLOCK(imap, ag);
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci		if (rc != -ENOSPC)
171862306a36Sopenharmony_ci			return (rc);
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	/* try to allocate from the ags in front of agno.
172262306a36Sopenharmony_ci	 */
172362306a36Sopenharmony_ci	for (ag = 0; ag < agno; ag++) {
172462306a36Sopenharmony_ci		AG_LOCK(imap, ag);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci		rc = diAllocAG(imap, ag, dir, ip);
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci		AG_UNLOCK(imap, ag);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci		if (rc != -ENOSPC)
173162306a36Sopenharmony_ci			return (rc);
173262306a36Sopenharmony_ci	}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	/* no free disk inodes.
173562306a36Sopenharmony_ci	 */
173662306a36Sopenharmony_ci	return -ENOSPC;
173762306a36Sopenharmony_ci}
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci/*
174162306a36Sopenharmony_ci * NAME:	diAllocIno(imap,agno,ip)
174262306a36Sopenharmony_ci *
174362306a36Sopenharmony_ci * FUNCTION:	allocate a disk inode from the allocation group's free
174462306a36Sopenharmony_ci *		inode list, returning an error if this free list is
174562306a36Sopenharmony_ci *		empty (i.e. no iags on the list).
174662306a36Sopenharmony_ci *
174762306a36Sopenharmony_ci *		allocation occurs from the first iag on the list using
174862306a36Sopenharmony_ci *		the iag's free inode summary map to find the leftmost
174962306a36Sopenharmony_ci *		free inode in the iag.
175062306a36Sopenharmony_ci *
175162306a36Sopenharmony_ci * PRE CONDITION: Already have AG lock for this AG.
175262306a36Sopenharmony_ci *
175362306a36Sopenharmony_ci * PARAMETERS:
175462306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
175562306a36Sopenharmony_ci *	agno	- allocation group.
175662306a36Sopenharmony_ci *	ip	- pointer to new inode to be filled in on successful return
175762306a36Sopenharmony_ci *		  with the disk inode number allocated, its extent address
175862306a36Sopenharmony_ci *		  and the start of the ag.
175962306a36Sopenharmony_ci *
176062306a36Sopenharmony_ci * RETURN VALUES:
176162306a36Sopenharmony_ci *	0	- success.
176262306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
176362306a36Sopenharmony_ci *	-EIO	- i/o error.
176462306a36Sopenharmony_ci */
176562306a36Sopenharmony_cistatic int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
176662306a36Sopenharmony_ci{
176762306a36Sopenharmony_ci	int iagno, ino, rc, rem, extno, sword;
176862306a36Sopenharmony_ci	struct metapage *mp;
176962306a36Sopenharmony_ci	struct iag *iagp;
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	/* check if there are iags on the ag's free inode list.
177262306a36Sopenharmony_ci	 */
177362306a36Sopenharmony_ci	if ((iagno = imap->im_agctl[agno].inofree) < 0)
177462306a36Sopenharmony_ci		return -ENOSPC;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	/* obtain read lock on imap inode */
177762306a36Sopenharmony_ci	IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	/* read the iag at the head of the list.
178062306a36Sopenharmony_ci	 */
178162306a36Sopenharmony_ci	if ((rc = diIAGRead(imap, iagno, &mp))) {
178262306a36Sopenharmony_ci		IREAD_UNLOCK(imap->im_ipimap);
178362306a36Sopenharmony_ci		return (rc);
178462306a36Sopenharmony_ci	}
178562306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	/* better be free inodes in this iag if it is on the
178862306a36Sopenharmony_ci	 * list.
178962306a36Sopenharmony_ci	 */
179062306a36Sopenharmony_ci	if (!iagp->nfreeinos) {
179162306a36Sopenharmony_ci		IREAD_UNLOCK(imap->im_ipimap);
179262306a36Sopenharmony_ci		release_metapage(mp);
179362306a36Sopenharmony_ci		jfs_error(ip->i_sb, "nfreeinos = 0, but iag on freelist\n");
179462306a36Sopenharmony_ci		return -EIO;
179562306a36Sopenharmony_ci	}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	/* scan the free inode summary map to find an extent
179862306a36Sopenharmony_ci	 * with free inodes.
179962306a36Sopenharmony_ci	 */
180062306a36Sopenharmony_ci	for (sword = 0;; sword++) {
180162306a36Sopenharmony_ci		if (sword >= SMAPSZ) {
180262306a36Sopenharmony_ci			IREAD_UNLOCK(imap->im_ipimap);
180362306a36Sopenharmony_ci			release_metapage(mp);
180462306a36Sopenharmony_ci			jfs_error(ip->i_sb,
180562306a36Sopenharmony_ci				  "free inode not found in summary map\n");
180662306a36Sopenharmony_ci			return -EIO;
180762306a36Sopenharmony_ci		}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci		if (~iagp->inosmap[sword])
181062306a36Sopenharmony_ci			break;
181162306a36Sopenharmony_ci	}
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	/* found a extent with free inodes. determine
181462306a36Sopenharmony_ci	 * the extent number.
181562306a36Sopenharmony_ci	 */
181662306a36Sopenharmony_ci	rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0);
181762306a36Sopenharmony_ci	if (rem >= EXTSPERSUM) {
181862306a36Sopenharmony_ci		IREAD_UNLOCK(imap->im_ipimap);
181962306a36Sopenharmony_ci		release_metapage(mp);
182062306a36Sopenharmony_ci		jfs_error(ip->i_sb, "no free extent found\n");
182162306a36Sopenharmony_ci		return -EIO;
182262306a36Sopenharmony_ci	}
182362306a36Sopenharmony_ci	extno = (sword << L2EXTSPERSUM) + rem;
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci	/* find the first free inode in the extent.
182662306a36Sopenharmony_ci	 */
182762306a36Sopenharmony_ci	rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0);
182862306a36Sopenharmony_ci	if (rem >= INOSPEREXT) {
182962306a36Sopenharmony_ci		IREAD_UNLOCK(imap->im_ipimap);
183062306a36Sopenharmony_ci		release_metapage(mp);
183162306a36Sopenharmony_ci		jfs_error(ip->i_sb, "free inode not found\n");
183262306a36Sopenharmony_ci		return -EIO;
183362306a36Sopenharmony_ci	}
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	/* compute the inode number within the iag.
183662306a36Sopenharmony_ci	 */
183762306a36Sopenharmony_ci	ino = (extno << L2INOSPEREXT) + rem;
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci	/* allocate the inode.
184062306a36Sopenharmony_ci	 */
184162306a36Sopenharmony_ci	rc = diAllocBit(imap, iagp, ino);
184262306a36Sopenharmony_ci	IREAD_UNLOCK(imap->im_ipimap);
184362306a36Sopenharmony_ci	if (rc) {
184462306a36Sopenharmony_ci		release_metapage(mp);
184562306a36Sopenharmony_ci		return (rc);
184662306a36Sopenharmony_ci	}
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	/* set the results of the allocation and write the iag.
184962306a36Sopenharmony_ci	 */
185062306a36Sopenharmony_ci	diInitInode(ip, iagno, ino, extno, iagp);
185162306a36Sopenharmony_ci	write_metapage(mp);
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	return (0);
185462306a36Sopenharmony_ci}
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci/*
185862306a36Sopenharmony_ci * NAME:	diAllocExt(imap,agno,ip)
185962306a36Sopenharmony_ci *
186062306a36Sopenharmony_ci * FUNCTION:	add a new extent of free inodes to an iag, allocating
186162306a36Sopenharmony_ci *		an inode from this extent to satisfy the current allocation
186262306a36Sopenharmony_ci *		request.
186362306a36Sopenharmony_ci *
186462306a36Sopenharmony_ci *		this routine first tries to find an existing iag with free
186562306a36Sopenharmony_ci *		extents through the ag free extent list.  if list is not
186662306a36Sopenharmony_ci *		empty, the head of the list will be selected as the home
186762306a36Sopenharmony_ci *		of the new extent of free inodes.  otherwise (the list is
186862306a36Sopenharmony_ci *		empty), a new iag will be allocated for the ag to contain
186962306a36Sopenharmony_ci *		the extent.
187062306a36Sopenharmony_ci *
187162306a36Sopenharmony_ci *		once an iag has been selected, the free extent summary map
187262306a36Sopenharmony_ci *		is used to locate a free extent within the iag and diNewExt()
187362306a36Sopenharmony_ci *		is called to initialize the extent, with initialization
187462306a36Sopenharmony_ci *		including the allocation of the first inode of the extent
187562306a36Sopenharmony_ci *		for the purpose of satisfying this request.
187662306a36Sopenharmony_ci *
187762306a36Sopenharmony_ci * PARAMETERS:
187862306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
187962306a36Sopenharmony_ci *	agno	- allocation group number.
188062306a36Sopenharmony_ci *	ip	- pointer to new inode to be filled in on successful return
188162306a36Sopenharmony_ci *		  with the disk inode number allocated, its extent address
188262306a36Sopenharmony_ci *		  and the start of the ag.
188362306a36Sopenharmony_ci *
188462306a36Sopenharmony_ci * RETURN VALUES:
188562306a36Sopenharmony_ci *	0	- success.
188662306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
188762306a36Sopenharmony_ci *	-EIO	- i/o error.
188862306a36Sopenharmony_ci */
188962306a36Sopenharmony_cistatic int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
189062306a36Sopenharmony_ci{
189162306a36Sopenharmony_ci	int rem, iagno, sword, extno, rc;
189262306a36Sopenharmony_ci	struct metapage *mp;
189362306a36Sopenharmony_ci	struct iag *iagp;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	/* check if the ag has any iags with free extents.  if not,
189662306a36Sopenharmony_ci	 * allocate a new iag for the ag.
189762306a36Sopenharmony_ci	 */
189862306a36Sopenharmony_ci	if ((iagno = imap->im_agctl[agno].extfree) < 0) {
189962306a36Sopenharmony_ci		/* If successful, diNewIAG will obtain the read lock on the
190062306a36Sopenharmony_ci		 * imap inode.
190162306a36Sopenharmony_ci		 */
190262306a36Sopenharmony_ci		if ((rc = diNewIAG(imap, &iagno, agno, &mp))) {
190362306a36Sopenharmony_ci			return (rc);
190462306a36Sopenharmony_ci		}
190562306a36Sopenharmony_ci		iagp = (struct iag *) mp->data;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci		/* set the ag number if this a brand new iag
190862306a36Sopenharmony_ci		 */
190962306a36Sopenharmony_ci		iagp->agstart =
191062306a36Sopenharmony_ci		    cpu_to_le64(AGTOBLK(agno, imap->im_ipimap));
191162306a36Sopenharmony_ci	} else {
191262306a36Sopenharmony_ci		/* read the iag.
191362306a36Sopenharmony_ci		 */
191462306a36Sopenharmony_ci		IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);
191562306a36Sopenharmony_ci		if ((rc = diIAGRead(imap, iagno, &mp))) {
191662306a36Sopenharmony_ci			IREAD_UNLOCK(imap->im_ipimap);
191762306a36Sopenharmony_ci			jfs_error(ip->i_sb, "error reading iag\n");
191862306a36Sopenharmony_ci			return rc;
191962306a36Sopenharmony_ci		}
192062306a36Sopenharmony_ci		iagp = (struct iag *) mp->data;
192162306a36Sopenharmony_ci	}
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	/* using the free extent summary map, find a free extent.
192462306a36Sopenharmony_ci	 */
192562306a36Sopenharmony_ci	for (sword = 0;; sword++) {
192662306a36Sopenharmony_ci		if (sword >= SMAPSZ) {
192762306a36Sopenharmony_ci			release_metapage(mp);
192862306a36Sopenharmony_ci			IREAD_UNLOCK(imap->im_ipimap);
192962306a36Sopenharmony_ci			jfs_error(ip->i_sb, "free ext summary map not found\n");
193062306a36Sopenharmony_ci			return -EIO;
193162306a36Sopenharmony_ci		}
193262306a36Sopenharmony_ci		if (~iagp->extsmap[sword])
193362306a36Sopenharmony_ci			break;
193462306a36Sopenharmony_ci	}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	/* determine the extent number of the free extent.
193762306a36Sopenharmony_ci	 */
193862306a36Sopenharmony_ci	rem = diFindFree(le32_to_cpu(iagp->extsmap[sword]), 0);
193962306a36Sopenharmony_ci	if (rem >= EXTSPERSUM) {
194062306a36Sopenharmony_ci		release_metapage(mp);
194162306a36Sopenharmony_ci		IREAD_UNLOCK(imap->im_ipimap);
194262306a36Sopenharmony_ci		jfs_error(ip->i_sb, "free extent not found\n");
194362306a36Sopenharmony_ci		return -EIO;
194462306a36Sopenharmony_ci	}
194562306a36Sopenharmony_ci	extno = (sword << L2EXTSPERSUM) + rem;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	/* initialize the new extent.
194862306a36Sopenharmony_ci	 */
194962306a36Sopenharmony_ci	rc = diNewExt(imap, iagp, extno);
195062306a36Sopenharmony_ci	IREAD_UNLOCK(imap->im_ipimap);
195162306a36Sopenharmony_ci	if (rc) {
195262306a36Sopenharmony_ci		/* something bad happened.  if a new iag was allocated,
195362306a36Sopenharmony_ci		 * place it back on the inode map's iag free list, and
195462306a36Sopenharmony_ci		 * clear the ag number information.
195562306a36Sopenharmony_ci		 */
195662306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
195762306a36Sopenharmony_ci			IAGFREE_LOCK(imap);
195862306a36Sopenharmony_ci			iagp->iagfree = cpu_to_le32(imap->im_freeiag);
195962306a36Sopenharmony_ci			imap->im_freeiag = iagno;
196062306a36Sopenharmony_ci			IAGFREE_UNLOCK(imap);
196162306a36Sopenharmony_ci		}
196262306a36Sopenharmony_ci		write_metapage(mp);
196362306a36Sopenharmony_ci		return (rc);
196462306a36Sopenharmony_ci	}
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	/* set the results of the allocation and write the iag.
196762306a36Sopenharmony_ci	 */
196862306a36Sopenharmony_ci	diInitInode(ip, iagno, extno << L2INOSPEREXT, extno, iagp);
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	write_metapage(mp);
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	return (0);
197362306a36Sopenharmony_ci}
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci/*
197762306a36Sopenharmony_ci * NAME:	diAllocBit(imap,iagp,ino)
197862306a36Sopenharmony_ci *
197962306a36Sopenharmony_ci * FUNCTION:	allocate a backed inode from an iag.
198062306a36Sopenharmony_ci *
198162306a36Sopenharmony_ci *		this routine performs the mechanics of allocating a
198262306a36Sopenharmony_ci *		specified inode from a backed extent.
198362306a36Sopenharmony_ci *
198462306a36Sopenharmony_ci *		if the inode to be allocated represents the last free
198562306a36Sopenharmony_ci *		inode within the iag, the iag will be removed from the
198662306a36Sopenharmony_ci *		ag free inode list.
198762306a36Sopenharmony_ci *
198862306a36Sopenharmony_ci *		a careful update approach is used to provide consistency
198962306a36Sopenharmony_ci *		in the face of updates to multiple buffers.  under this
199062306a36Sopenharmony_ci *		approach, all required buffers are obtained before making
199162306a36Sopenharmony_ci *		any updates and are held all are updates are complete.
199262306a36Sopenharmony_ci *
199362306a36Sopenharmony_ci * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on
199462306a36Sopenharmony_ci *	this AG.  Must have read lock on imap inode.
199562306a36Sopenharmony_ci *
199662306a36Sopenharmony_ci * PARAMETERS:
199762306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
199862306a36Sopenharmony_ci *	iagp	- pointer to iag.
199962306a36Sopenharmony_ci *	ino	- inode number to be allocated within the iag.
200062306a36Sopenharmony_ci *
200162306a36Sopenharmony_ci * RETURN VALUES:
200262306a36Sopenharmony_ci *	0	- success.
200362306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
200462306a36Sopenharmony_ci *	-EIO	- i/o error.
200562306a36Sopenharmony_ci */
200662306a36Sopenharmony_cistatic int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
200762306a36Sopenharmony_ci{
200862306a36Sopenharmony_ci	int extno, bitno, agno, sword, rc;
200962306a36Sopenharmony_ci	struct metapage *amp = NULL, *bmp = NULL;
201062306a36Sopenharmony_ci	struct iag *aiagp = NULL, *biagp = NULL;
201162306a36Sopenharmony_ci	u32 mask;
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci	/* check if this is the last free inode within the iag.
201462306a36Sopenharmony_ci	 * if so, it will have to be removed from the ag free
201562306a36Sopenharmony_ci	 * inode list, so get the iags preceding and following
201662306a36Sopenharmony_ci	 * it on the list.
201762306a36Sopenharmony_ci	 */
201862306a36Sopenharmony_ci	if (iagp->nfreeinos == cpu_to_le32(1)) {
201962306a36Sopenharmony_ci		if ((int) le32_to_cpu(iagp->inofreefwd) >= 0) {
202062306a36Sopenharmony_ci			if ((rc =
202162306a36Sopenharmony_ci			     diIAGRead(imap, le32_to_cpu(iagp->inofreefwd),
202262306a36Sopenharmony_ci				       &amp)))
202362306a36Sopenharmony_ci				return (rc);
202462306a36Sopenharmony_ci			aiagp = (struct iag *) amp->data;
202562306a36Sopenharmony_ci		}
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci		if ((int) le32_to_cpu(iagp->inofreeback) >= 0) {
202862306a36Sopenharmony_ci			if ((rc =
202962306a36Sopenharmony_ci			     diIAGRead(imap,
203062306a36Sopenharmony_ci				       le32_to_cpu(iagp->inofreeback),
203162306a36Sopenharmony_ci				       &bmp))) {
203262306a36Sopenharmony_ci				if (amp)
203362306a36Sopenharmony_ci					release_metapage(amp);
203462306a36Sopenharmony_ci				return (rc);
203562306a36Sopenharmony_ci			}
203662306a36Sopenharmony_ci			biagp = (struct iag *) bmp->data;
203762306a36Sopenharmony_ci		}
203862306a36Sopenharmony_ci	}
203962306a36Sopenharmony_ci
204062306a36Sopenharmony_ci	/* get the ag number, extent number, inode number within
204162306a36Sopenharmony_ci	 * the extent.
204262306a36Sopenharmony_ci	 */
204362306a36Sopenharmony_ci	agno = BLKTOAG(le64_to_cpu(iagp->agstart), JFS_SBI(imap->im_ipimap->i_sb));
204462306a36Sopenharmony_ci	extno = ino >> L2INOSPEREXT;
204562306a36Sopenharmony_ci	bitno = ino & (INOSPEREXT - 1);
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	/* compute the mask for setting the map.
204862306a36Sopenharmony_ci	 */
204962306a36Sopenharmony_ci	mask = HIGHORDER >> bitno;
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	/* the inode should be free and backed.
205262306a36Sopenharmony_ci	 */
205362306a36Sopenharmony_ci	if (((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) ||
205462306a36Sopenharmony_ci	    ((le32_to_cpu(iagp->wmap[extno]) & mask) != 0) ||
205562306a36Sopenharmony_ci	    (addressPXD(&iagp->inoext[extno]) == 0)) {
205662306a36Sopenharmony_ci		if (amp)
205762306a36Sopenharmony_ci			release_metapage(amp);
205862306a36Sopenharmony_ci		if (bmp)
205962306a36Sopenharmony_ci			release_metapage(bmp);
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci		jfs_error(imap->im_ipimap->i_sb, "iag inconsistent\n");
206262306a36Sopenharmony_ci		return -EIO;
206362306a36Sopenharmony_ci	}
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	/* mark the inode as allocated in the working map.
206662306a36Sopenharmony_ci	 */
206762306a36Sopenharmony_ci	iagp->wmap[extno] |= cpu_to_le32(mask);
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	/* check if all inodes within the extent are now
207062306a36Sopenharmony_ci	 * allocated.  if so, update the free inode summary
207162306a36Sopenharmony_ci	 * map to reflect this.
207262306a36Sopenharmony_ci	 */
207362306a36Sopenharmony_ci	if (iagp->wmap[extno] == cpu_to_le32(ONES)) {
207462306a36Sopenharmony_ci		sword = extno >> L2EXTSPERSUM;
207562306a36Sopenharmony_ci		bitno = extno & (EXTSPERSUM - 1);
207662306a36Sopenharmony_ci		iagp->inosmap[sword] |= cpu_to_le32(HIGHORDER >> bitno);
207762306a36Sopenharmony_ci	}
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	/* if this was the last free inode in the iag, remove the
208062306a36Sopenharmony_ci	 * iag from the ag free inode list.
208162306a36Sopenharmony_ci	 */
208262306a36Sopenharmony_ci	if (iagp->nfreeinos == cpu_to_le32(1)) {
208362306a36Sopenharmony_ci		if (amp) {
208462306a36Sopenharmony_ci			aiagp->inofreeback = iagp->inofreeback;
208562306a36Sopenharmony_ci			write_metapage(amp);
208662306a36Sopenharmony_ci		}
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci		if (bmp) {
208962306a36Sopenharmony_ci			biagp->inofreefwd = iagp->inofreefwd;
209062306a36Sopenharmony_ci			write_metapage(bmp);
209162306a36Sopenharmony_ci		} else {
209262306a36Sopenharmony_ci			imap->im_agctl[agno].inofree =
209362306a36Sopenharmony_ci			    le32_to_cpu(iagp->inofreefwd);
209462306a36Sopenharmony_ci		}
209562306a36Sopenharmony_ci		iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
209662306a36Sopenharmony_ci	}
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	/* update the free inode count at the iag, ag, inode
209962306a36Sopenharmony_ci	 * map levels.
210062306a36Sopenharmony_ci	 */
210162306a36Sopenharmony_ci	le32_add_cpu(&iagp->nfreeinos, -1);
210262306a36Sopenharmony_ci	imap->im_agctl[agno].numfree -= 1;
210362306a36Sopenharmony_ci	atomic_dec(&imap->im_numfree);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	return (0);
210662306a36Sopenharmony_ci}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci/*
211062306a36Sopenharmony_ci * NAME:	diNewExt(imap,iagp,extno)
211162306a36Sopenharmony_ci *
211262306a36Sopenharmony_ci * FUNCTION:	initialize a new extent of inodes for an iag, allocating
211362306a36Sopenharmony_ci *		the first inode of the extent for use for the current
211462306a36Sopenharmony_ci *		allocation request.
211562306a36Sopenharmony_ci *
211662306a36Sopenharmony_ci *		disk resources are allocated for the new extent of inodes
211762306a36Sopenharmony_ci *		and the inodes themselves are initialized to reflect their
211862306a36Sopenharmony_ci *		existence within the extent (i.e. their inode numbers and
211962306a36Sopenharmony_ci *		inode extent addresses are set) and their initial state
212062306a36Sopenharmony_ci *		(mode and link count are set to zero).
212162306a36Sopenharmony_ci *
212262306a36Sopenharmony_ci *		if the iag is new, it is not yet on an ag extent free list
212362306a36Sopenharmony_ci *		but will now be placed on this list.
212462306a36Sopenharmony_ci *
212562306a36Sopenharmony_ci *		if the allocation of the new extent causes the iag to
212662306a36Sopenharmony_ci *		have no free extent, the iag will be removed from the
212762306a36Sopenharmony_ci *		ag extent free list.
212862306a36Sopenharmony_ci *
212962306a36Sopenharmony_ci *		if the iag has no free backed inodes, it will be placed
213062306a36Sopenharmony_ci *		on the ag free inode list, since the addition of the new
213162306a36Sopenharmony_ci *		extent will now cause it to have free inodes.
213262306a36Sopenharmony_ci *
213362306a36Sopenharmony_ci *		a careful update approach is used to provide consistency
213462306a36Sopenharmony_ci *		(i.e. list consistency) in the face of updates to multiple
213562306a36Sopenharmony_ci *		buffers.  under this approach, all required buffers are
213662306a36Sopenharmony_ci *		obtained before making any updates and are held until all
213762306a36Sopenharmony_ci *		updates are complete.
213862306a36Sopenharmony_ci *
213962306a36Sopenharmony_ci * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on
214062306a36Sopenharmony_ci *	this AG.  Must have read lock on imap inode.
214162306a36Sopenharmony_ci *
214262306a36Sopenharmony_ci * PARAMETERS:
214362306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
214462306a36Sopenharmony_ci *	iagp	- pointer to iag.
214562306a36Sopenharmony_ci *	extno	- extent number.
214662306a36Sopenharmony_ci *
214762306a36Sopenharmony_ci * RETURN VALUES:
214862306a36Sopenharmony_ci *	0	- success.
214962306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
215062306a36Sopenharmony_ci *	-EIO	- i/o error.
215162306a36Sopenharmony_ci */
215262306a36Sopenharmony_cistatic int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
215362306a36Sopenharmony_ci{
215462306a36Sopenharmony_ci	int agno, iagno, fwd, back, freei = 0, sword, rc;
215562306a36Sopenharmony_ci	struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL;
215662306a36Sopenharmony_ci	struct metapage *amp, *bmp, *cmp, *dmp;
215762306a36Sopenharmony_ci	struct inode *ipimap;
215862306a36Sopenharmony_ci	s64 blkno, hint;
215962306a36Sopenharmony_ci	int i, j;
216062306a36Sopenharmony_ci	u32 mask;
216162306a36Sopenharmony_ci	ino_t ino;
216262306a36Sopenharmony_ci	struct dinode *dp;
216362306a36Sopenharmony_ci	struct jfs_sb_info *sbi;
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	/* better have free extents.
216662306a36Sopenharmony_ci	 */
216762306a36Sopenharmony_ci	if (!iagp->nfreeexts) {
216862306a36Sopenharmony_ci		jfs_error(imap->im_ipimap->i_sb, "no free extents\n");
216962306a36Sopenharmony_ci		return -EIO;
217062306a36Sopenharmony_ci	}
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	/* get the inode map inode.
217362306a36Sopenharmony_ci	 */
217462306a36Sopenharmony_ci	ipimap = imap->im_ipimap;
217562306a36Sopenharmony_ci	sbi = JFS_SBI(ipimap->i_sb);
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	amp = bmp = cmp = NULL;
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	/* get the ag and iag numbers for this iag.
218062306a36Sopenharmony_ci	 */
218162306a36Sopenharmony_ci	agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
218262306a36Sopenharmony_ci	if (agno >= MAXAG || agno < 0)
218362306a36Sopenharmony_ci		return -EIO;
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci	iagno = le32_to_cpu(iagp->iagnum);
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci	/* check if this is the last free extent within the
218862306a36Sopenharmony_ci	 * iag.  if so, the iag must be removed from the ag
218962306a36Sopenharmony_ci	 * free extent list, so get the iags preceding and
219062306a36Sopenharmony_ci	 * following the iag on this list.
219162306a36Sopenharmony_ci	 */
219262306a36Sopenharmony_ci	if (iagp->nfreeexts == cpu_to_le32(1)) {
219362306a36Sopenharmony_ci		if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) {
219462306a36Sopenharmony_ci			if ((rc = diIAGRead(imap, fwd, &amp)))
219562306a36Sopenharmony_ci				return (rc);
219662306a36Sopenharmony_ci			aiagp = (struct iag *) amp->data;
219762306a36Sopenharmony_ci		}
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci		if ((back = le32_to_cpu(iagp->extfreeback)) >= 0) {
220062306a36Sopenharmony_ci			if ((rc = diIAGRead(imap, back, &bmp)))
220162306a36Sopenharmony_ci				goto error_out;
220262306a36Sopenharmony_ci			biagp = (struct iag *) bmp->data;
220362306a36Sopenharmony_ci		}
220462306a36Sopenharmony_ci	} else {
220562306a36Sopenharmony_ci		/* the iag has free extents.  if all extents are free
220662306a36Sopenharmony_ci		 * (as is the case for a newly allocated iag), the iag
220762306a36Sopenharmony_ci		 * must be added to the ag free extent list, so get
220862306a36Sopenharmony_ci		 * the iag at the head of the list in preparation for
220962306a36Sopenharmony_ci		 * adding this iag to this list.
221062306a36Sopenharmony_ci		 */
221162306a36Sopenharmony_ci		fwd = back = -1;
221262306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
221362306a36Sopenharmony_ci			if ((fwd = imap->im_agctl[agno].extfree) >= 0) {
221462306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, fwd, &amp)))
221562306a36Sopenharmony_ci					goto error_out;
221662306a36Sopenharmony_ci				aiagp = (struct iag *) amp->data;
221762306a36Sopenharmony_ci			}
221862306a36Sopenharmony_ci		}
221962306a36Sopenharmony_ci	}
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	/* check if the iag has no free inodes.  if so, the iag
222262306a36Sopenharmony_ci	 * will have to be added to the ag free inode list, so get
222362306a36Sopenharmony_ci	 * the iag at the head of the list in preparation for
222462306a36Sopenharmony_ci	 * adding this iag to this list.  in doing this, we must
222562306a36Sopenharmony_ci	 * check if we already have the iag at the head of
222662306a36Sopenharmony_ci	 * the list in hand.
222762306a36Sopenharmony_ci	 */
222862306a36Sopenharmony_ci	if (iagp->nfreeinos == 0) {
222962306a36Sopenharmony_ci		freei = imap->im_agctl[agno].inofree;
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci		if (freei >= 0) {
223262306a36Sopenharmony_ci			if (freei == fwd) {
223362306a36Sopenharmony_ci				ciagp = aiagp;
223462306a36Sopenharmony_ci			} else if (freei == back) {
223562306a36Sopenharmony_ci				ciagp = biagp;
223662306a36Sopenharmony_ci			} else {
223762306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, freei, &cmp)))
223862306a36Sopenharmony_ci					goto error_out;
223962306a36Sopenharmony_ci				ciagp = (struct iag *) cmp->data;
224062306a36Sopenharmony_ci			}
224162306a36Sopenharmony_ci			if (ciagp == NULL) {
224262306a36Sopenharmony_ci				jfs_error(imap->im_ipimap->i_sb,
224362306a36Sopenharmony_ci					  "ciagp == NULL\n");
224462306a36Sopenharmony_ci				rc = -EIO;
224562306a36Sopenharmony_ci				goto error_out;
224662306a36Sopenharmony_ci			}
224762306a36Sopenharmony_ci		}
224862306a36Sopenharmony_ci	}
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_ci	/* allocate disk space for the inode extent.
225162306a36Sopenharmony_ci	 */
225262306a36Sopenharmony_ci	if ((extno == 0) || (addressPXD(&iagp->inoext[extno - 1]) == 0))
225362306a36Sopenharmony_ci		hint = ((s64) agno << sbi->bmap->db_agl2size) - 1;
225462306a36Sopenharmony_ci	else
225562306a36Sopenharmony_ci		hint = addressPXD(&iagp->inoext[extno - 1]) +
225662306a36Sopenharmony_ci		    lengthPXD(&iagp->inoext[extno - 1]) - 1;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	if ((rc = dbAlloc(ipimap, hint, (s64) imap->im_nbperiext, &blkno)))
225962306a36Sopenharmony_ci		goto error_out;
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	/* compute the inode number of the first inode within the
226262306a36Sopenharmony_ci	 * extent.
226362306a36Sopenharmony_ci	 */
226462306a36Sopenharmony_ci	ino = (iagno << L2INOSPERIAG) + (extno << L2INOSPEREXT);
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	/* initialize the inodes within the newly allocated extent a
226762306a36Sopenharmony_ci	 * page at a time.
226862306a36Sopenharmony_ci	 */
226962306a36Sopenharmony_ci	for (i = 0; i < imap->im_nbperiext; i += sbi->nbperpage) {
227062306a36Sopenharmony_ci		/* get a buffer for this page of disk inodes.
227162306a36Sopenharmony_ci		 */
227262306a36Sopenharmony_ci		dmp = get_metapage(ipimap, blkno + i, PSIZE, 1);
227362306a36Sopenharmony_ci		if (dmp == NULL) {
227462306a36Sopenharmony_ci			rc = -EIO;
227562306a36Sopenharmony_ci			goto error_out;
227662306a36Sopenharmony_ci		}
227762306a36Sopenharmony_ci		dp = (struct dinode *) dmp->data;
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci		/* initialize the inode number, mode, link count and
228062306a36Sopenharmony_ci		 * inode extent address.
228162306a36Sopenharmony_ci		 */
228262306a36Sopenharmony_ci		for (j = 0; j < INOSPERPAGE; j++, dp++, ino++) {
228362306a36Sopenharmony_ci			dp->di_inostamp = cpu_to_le32(sbi->inostamp);
228462306a36Sopenharmony_ci			dp->di_number = cpu_to_le32(ino);
228562306a36Sopenharmony_ci			dp->di_fileset = cpu_to_le32(FILESYSTEM_I);
228662306a36Sopenharmony_ci			dp->di_mode = 0;
228762306a36Sopenharmony_ci			dp->di_nlink = 0;
228862306a36Sopenharmony_ci			PXDaddress(&(dp->di_ixpxd), blkno);
228962306a36Sopenharmony_ci			PXDlength(&(dp->di_ixpxd), imap->im_nbperiext);
229062306a36Sopenharmony_ci		}
229162306a36Sopenharmony_ci		write_metapage(dmp);
229262306a36Sopenharmony_ci	}
229362306a36Sopenharmony_ci
229462306a36Sopenharmony_ci	/* if this is the last free extent within the iag, remove the
229562306a36Sopenharmony_ci	 * iag from the ag free extent list.
229662306a36Sopenharmony_ci	 */
229762306a36Sopenharmony_ci	if (iagp->nfreeexts == cpu_to_le32(1)) {
229862306a36Sopenharmony_ci		if (fwd >= 0)
229962306a36Sopenharmony_ci			aiagp->extfreeback = iagp->extfreeback;
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci		if (back >= 0)
230262306a36Sopenharmony_ci			biagp->extfreefwd = iagp->extfreefwd;
230362306a36Sopenharmony_ci		else
230462306a36Sopenharmony_ci			imap->im_agctl[agno].extfree =
230562306a36Sopenharmony_ci			    le32_to_cpu(iagp->extfreefwd);
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci		iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
230862306a36Sopenharmony_ci	} else {
230962306a36Sopenharmony_ci		/* if the iag has all free extents (newly allocated iag),
231062306a36Sopenharmony_ci		 * add the iag to the ag free extent list.
231162306a36Sopenharmony_ci		 */
231262306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
231362306a36Sopenharmony_ci			if (fwd >= 0)
231462306a36Sopenharmony_ci				aiagp->extfreeback = cpu_to_le32(iagno);
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci			iagp->extfreefwd = cpu_to_le32(fwd);
231762306a36Sopenharmony_ci			iagp->extfreeback = cpu_to_le32(-1);
231862306a36Sopenharmony_ci			imap->im_agctl[agno].extfree = iagno;
231962306a36Sopenharmony_ci		}
232062306a36Sopenharmony_ci	}
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	/* if the iag has no free inodes, add the iag to the
232362306a36Sopenharmony_ci	 * ag free inode list.
232462306a36Sopenharmony_ci	 */
232562306a36Sopenharmony_ci	if (iagp->nfreeinos == 0) {
232662306a36Sopenharmony_ci		if (freei >= 0)
232762306a36Sopenharmony_ci			ciagp->inofreeback = cpu_to_le32(iagno);
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci		iagp->inofreefwd =
233062306a36Sopenharmony_ci		    cpu_to_le32(imap->im_agctl[agno].inofree);
233162306a36Sopenharmony_ci		iagp->inofreeback = cpu_to_le32(-1);
233262306a36Sopenharmony_ci		imap->im_agctl[agno].inofree = iagno;
233362306a36Sopenharmony_ci	}
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci	/* initialize the extent descriptor of the extent. */
233662306a36Sopenharmony_ci	PXDlength(&iagp->inoext[extno], imap->im_nbperiext);
233762306a36Sopenharmony_ci	PXDaddress(&iagp->inoext[extno], blkno);
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	/* initialize the working and persistent map of the extent.
234062306a36Sopenharmony_ci	 * the working map will be initialized such that
234162306a36Sopenharmony_ci	 * it indicates the first inode of the extent is allocated.
234262306a36Sopenharmony_ci	 */
234362306a36Sopenharmony_ci	iagp->wmap[extno] = cpu_to_le32(HIGHORDER);
234462306a36Sopenharmony_ci	iagp->pmap[extno] = 0;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	/* update the free inode and free extent summary maps
234762306a36Sopenharmony_ci	 * for the extent to indicate the extent has free inodes
234862306a36Sopenharmony_ci	 * and no longer represents a free extent.
234962306a36Sopenharmony_ci	 */
235062306a36Sopenharmony_ci	sword = extno >> L2EXTSPERSUM;
235162306a36Sopenharmony_ci	mask = HIGHORDER >> (extno & (EXTSPERSUM - 1));
235262306a36Sopenharmony_ci	iagp->extsmap[sword] |= cpu_to_le32(mask);
235362306a36Sopenharmony_ci	iagp->inosmap[sword] &= cpu_to_le32(~mask);
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_ci	/* update the free inode and free extent counts for the
235662306a36Sopenharmony_ci	 * iag.
235762306a36Sopenharmony_ci	 */
235862306a36Sopenharmony_ci	le32_add_cpu(&iagp->nfreeinos, (INOSPEREXT - 1));
235962306a36Sopenharmony_ci	le32_add_cpu(&iagp->nfreeexts, -1);
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	/* update the free and backed inode counts for the ag.
236262306a36Sopenharmony_ci	 */
236362306a36Sopenharmony_ci	imap->im_agctl[agno].numfree += (INOSPEREXT - 1);
236462306a36Sopenharmony_ci	imap->im_agctl[agno].numinos += INOSPEREXT;
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	/* update the free and backed inode counts for the inode map.
236762306a36Sopenharmony_ci	 */
236862306a36Sopenharmony_ci	atomic_add(INOSPEREXT - 1, &imap->im_numfree);
236962306a36Sopenharmony_ci	atomic_add(INOSPEREXT, &imap->im_numinos);
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	/* write the iags.
237262306a36Sopenharmony_ci	 */
237362306a36Sopenharmony_ci	if (amp)
237462306a36Sopenharmony_ci		write_metapage(amp);
237562306a36Sopenharmony_ci	if (bmp)
237662306a36Sopenharmony_ci		write_metapage(bmp);
237762306a36Sopenharmony_ci	if (cmp)
237862306a36Sopenharmony_ci		write_metapage(cmp);
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	return (0);
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci      error_out:
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	/* release the iags.
238562306a36Sopenharmony_ci	 */
238662306a36Sopenharmony_ci	if (amp)
238762306a36Sopenharmony_ci		release_metapage(amp);
238862306a36Sopenharmony_ci	if (bmp)
238962306a36Sopenharmony_ci		release_metapage(bmp);
239062306a36Sopenharmony_ci	if (cmp)
239162306a36Sopenharmony_ci		release_metapage(cmp);
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	return (rc);
239462306a36Sopenharmony_ci}
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci/*
239862306a36Sopenharmony_ci * NAME:	diNewIAG(imap,iagnop,agno)
239962306a36Sopenharmony_ci *
240062306a36Sopenharmony_ci * FUNCTION:	allocate a new iag for an allocation group.
240162306a36Sopenharmony_ci *
240262306a36Sopenharmony_ci *		first tries to allocate the iag from the inode map
240362306a36Sopenharmony_ci *		iagfree list:
240462306a36Sopenharmony_ci *		if the list has free iags, the head of the list is removed
240562306a36Sopenharmony_ci *		and returned to satisfy the request.
240662306a36Sopenharmony_ci *		if the inode map's iag free list is empty, the inode map
240762306a36Sopenharmony_ci *		is extended to hold a new iag. this new iag is initialized
240862306a36Sopenharmony_ci *		and returned to satisfy the request.
240962306a36Sopenharmony_ci *
241062306a36Sopenharmony_ci * PARAMETERS:
241162306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
241262306a36Sopenharmony_ci *	iagnop	- pointer to an iag number set with the number of the
241362306a36Sopenharmony_ci *		  newly allocated iag upon successful return.
241462306a36Sopenharmony_ci *	agno	- allocation group number.
241562306a36Sopenharmony_ci *	bpp	- Buffer pointer to be filled in with new IAG's buffer
241662306a36Sopenharmony_ci *
241762306a36Sopenharmony_ci * RETURN VALUES:
241862306a36Sopenharmony_ci *	0	- success.
241962306a36Sopenharmony_ci *	-ENOSPC	- insufficient disk resources.
242062306a36Sopenharmony_ci *	-EIO	- i/o error.
242162306a36Sopenharmony_ci *
242262306a36Sopenharmony_ci * serialization:
242362306a36Sopenharmony_ci *	AG lock held on entry/exit;
242462306a36Sopenharmony_ci *	write lock on the map is held inside;
242562306a36Sopenharmony_ci *	read lock on the map is held on successful completion;
242662306a36Sopenharmony_ci *
242762306a36Sopenharmony_ci * note: new iag transaction:
242862306a36Sopenharmony_ci * . synchronously write iag;
242962306a36Sopenharmony_ci * . write log of xtree and inode of imap;
243062306a36Sopenharmony_ci * . commit;
243162306a36Sopenharmony_ci * . synchronous write of xtree (right to left, bottom to top);
243262306a36Sopenharmony_ci * . at start of logredo(): init in-memory imap with one additional iag page;
243362306a36Sopenharmony_ci * . at end of logredo(): re-read imap inode to determine
243462306a36Sopenharmony_ci *   new imap size;
243562306a36Sopenharmony_ci */
243662306a36Sopenharmony_cistatic int
243762306a36Sopenharmony_cidiNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
243862306a36Sopenharmony_ci{
243962306a36Sopenharmony_ci	int rc;
244062306a36Sopenharmony_ci	int iagno, i, xlen;
244162306a36Sopenharmony_ci	struct inode *ipimap;
244262306a36Sopenharmony_ci	struct super_block *sb;
244362306a36Sopenharmony_ci	struct jfs_sb_info *sbi;
244462306a36Sopenharmony_ci	struct metapage *mp;
244562306a36Sopenharmony_ci	struct iag *iagp;
244662306a36Sopenharmony_ci	s64 xaddr = 0;
244762306a36Sopenharmony_ci	s64 blkno;
244862306a36Sopenharmony_ci	tid_t tid;
244962306a36Sopenharmony_ci	struct inode *iplist[1];
245062306a36Sopenharmony_ci
245162306a36Sopenharmony_ci	/* pick up pointers to the inode map and mount inodes */
245262306a36Sopenharmony_ci	ipimap = imap->im_ipimap;
245362306a36Sopenharmony_ci	sb = ipimap->i_sb;
245462306a36Sopenharmony_ci	sbi = JFS_SBI(sb);
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	/* acquire the free iag lock */
245762306a36Sopenharmony_ci	IAGFREE_LOCK(imap);
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	/* if there are any iags on the inode map free iag list,
246062306a36Sopenharmony_ci	 * allocate the iag from the head of the list.
246162306a36Sopenharmony_ci	 */
246262306a36Sopenharmony_ci	if (imap->im_freeiag >= 0) {
246362306a36Sopenharmony_ci		/* pick up the iag number at the head of the list */
246462306a36Sopenharmony_ci		iagno = imap->im_freeiag;
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci		/* determine the logical block number of the iag */
246762306a36Sopenharmony_ci		blkno = IAGTOLBLK(iagno, sbi->l2nbperpage);
246862306a36Sopenharmony_ci	} else {
246962306a36Sopenharmony_ci		/* no free iags. the inode map will have to be extented
247062306a36Sopenharmony_ci		 * to include a new iag.
247162306a36Sopenharmony_ci		 */
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci		/* acquire inode map lock */
247462306a36Sopenharmony_ci		IWRITE_LOCK(ipimap, RDWRLOCK_IMAP);
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci		if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) {
247762306a36Sopenharmony_ci			IWRITE_UNLOCK(ipimap);
247862306a36Sopenharmony_ci			IAGFREE_UNLOCK(imap);
247962306a36Sopenharmony_ci			jfs_error(imap->im_ipimap->i_sb,
248062306a36Sopenharmony_ci				  "ipimap->i_size is wrong\n");
248162306a36Sopenharmony_ci			return -EIO;
248262306a36Sopenharmony_ci		}
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci		/* get the next available iag number */
248662306a36Sopenharmony_ci		iagno = imap->im_nextiag;
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci		/* make sure that we have not exceeded the maximum inode
248962306a36Sopenharmony_ci		 * number limit.
249062306a36Sopenharmony_ci		 */
249162306a36Sopenharmony_ci		if (iagno > (MAXIAGS - 1)) {
249262306a36Sopenharmony_ci			/* release the inode map lock */
249362306a36Sopenharmony_ci			IWRITE_UNLOCK(ipimap);
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci			rc = -ENOSPC;
249662306a36Sopenharmony_ci			goto out;
249762306a36Sopenharmony_ci		}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci		/*
250062306a36Sopenharmony_ci		 * synchronously append new iag page.
250162306a36Sopenharmony_ci		 */
250262306a36Sopenharmony_ci		/* determine the logical address of iag page to append */
250362306a36Sopenharmony_ci		blkno = IAGTOLBLK(iagno, sbi->l2nbperpage);
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_ci		/* Allocate extent for new iag page */
250662306a36Sopenharmony_ci		xlen = sbi->nbperpage;
250762306a36Sopenharmony_ci		if ((rc = dbAlloc(ipimap, 0, (s64) xlen, &xaddr))) {
250862306a36Sopenharmony_ci			/* release the inode map lock */
250962306a36Sopenharmony_ci			IWRITE_UNLOCK(ipimap);
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci			goto out;
251262306a36Sopenharmony_ci		}
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci		/*
251562306a36Sopenharmony_ci		 * start transaction of update of the inode map
251662306a36Sopenharmony_ci		 * addressing structure pointing to the new iag page;
251762306a36Sopenharmony_ci		 */
251862306a36Sopenharmony_ci		tid = txBegin(sb, COMMIT_FORCE);
251962306a36Sopenharmony_ci		mutex_lock(&JFS_IP(ipimap)->commit_mutex);
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci		/* update the inode map addressing structure to point to it */
252262306a36Sopenharmony_ci		if ((rc =
252362306a36Sopenharmony_ci		     xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
252462306a36Sopenharmony_ci			txEnd(tid);
252562306a36Sopenharmony_ci			mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
252662306a36Sopenharmony_ci			/* Free the blocks allocated for the iag since it was
252762306a36Sopenharmony_ci			 * not successfully added to the inode map
252862306a36Sopenharmony_ci			 */
252962306a36Sopenharmony_ci			dbFree(ipimap, xaddr, (s64) xlen);
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci			/* release the inode map lock */
253262306a36Sopenharmony_ci			IWRITE_UNLOCK(ipimap);
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci			goto out;
253562306a36Sopenharmony_ci		}
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_ci		/* update the inode map's inode to reflect the extension */
253862306a36Sopenharmony_ci		ipimap->i_size += PSIZE;
253962306a36Sopenharmony_ci		inode_add_bytes(ipimap, PSIZE);
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci		/* assign a buffer for the page */
254262306a36Sopenharmony_ci		mp = get_metapage(ipimap, blkno, PSIZE, 0);
254362306a36Sopenharmony_ci		if (!mp) {
254462306a36Sopenharmony_ci			/*
254562306a36Sopenharmony_ci			 * This is very unlikely since we just created the
254662306a36Sopenharmony_ci			 * extent, but let's try to handle it correctly
254762306a36Sopenharmony_ci			 */
254862306a36Sopenharmony_ci			xtTruncate(tid, ipimap, ipimap->i_size - PSIZE,
254962306a36Sopenharmony_ci				   COMMIT_PWMAP);
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci			txAbort(tid, 0);
255262306a36Sopenharmony_ci			txEnd(tid);
255362306a36Sopenharmony_ci			mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci			/* release the inode map lock */
255662306a36Sopenharmony_ci			IWRITE_UNLOCK(ipimap);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci			rc = -EIO;
255962306a36Sopenharmony_ci			goto out;
256062306a36Sopenharmony_ci		}
256162306a36Sopenharmony_ci		iagp = (struct iag *) mp->data;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci		/* init the iag */
256462306a36Sopenharmony_ci		memset(iagp, 0, sizeof(struct iag));
256562306a36Sopenharmony_ci		iagp->iagnum = cpu_to_le32(iagno);
256662306a36Sopenharmony_ci		iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);
256762306a36Sopenharmony_ci		iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);
256862306a36Sopenharmony_ci		iagp->iagfree = cpu_to_le32(-1);
256962306a36Sopenharmony_ci		iagp->nfreeinos = 0;
257062306a36Sopenharmony_ci		iagp->nfreeexts = cpu_to_le32(EXTSPERIAG);
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci		/* initialize the free inode summary map (free extent
257362306a36Sopenharmony_ci		 * summary map initialization handled by bzero).
257462306a36Sopenharmony_ci		 */
257562306a36Sopenharmony_ci		for (i = 0; i < SMAPSZ; i++)
257662306a36Sopenharmony_ci			iagp->inosmap[i] = cpu_to_le32(ONES);
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci		/*
257962306a36Sopenharmony_ci		 * Write and sync the metapage
258062306a36Sopenharmony_ci		 */
258162306a36Sopenharmony_ci		flush_metapage(mp);
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci		/*
258462306a36Sopenharmony_ci		 * txCommit(COMMIT_FORCE) will synchronously write address
258562306a36Sopenharmony_ci		 * index pages and inode after commit in careful update order
258662306a36Sopenharmony_ci		 * of address index pages (right to left, bottom up);
258762306a36Sopenharmony_ci		 */
258862306a36Sopenharmony_ci		iplist[0] = ipimap;
258962306a36Sopenharmony_ci		rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci		txEnd(tid);
259262306a36Sopenharmony_ci		mutex_unlock(&JFS_IP(ipimap)->commit_mutex);
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_ci		duplicateIXtree(sb, blkno, xlen, &xaddr);
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci		/* update the next available iag number */
259762306a36Sopenharmony_ci		imap->im_nextiag += 1;
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_ci		/* Add the iag to the iag free list so we don't lose the iag
260062306a36Sopenharmony_ci		 * if a failure happens now.
260162306a36Sopenharmony_ci		 */
260262306a36Sopenharmony_ci		imap->im_freeiag = iagno;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci		/* Until we have logredo working, we want the imap inode &
260562306a36Sopenharmony_ci		 * control page to be up to date.
260662306a36Sopenharmony_ci		 */
260762306a36Sopenharmony_ci		diSync(ipimap);
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci		/* release the inode map lock */
261062306a36Sopenharmony_ci		IWRITE_UNLOCK(ipimap);
261162306a36Sopenharmony_ci	}
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci	/* obtain read lock on map */
261462306a36Sopenharmony_ci	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
261562306a36Sopenharmony_ci
261662306a36Sopenharmony_ci	/* read the iag */
261762306a36Sopenharmony_ci	if ((rc = diIAGRead(imap, iagno, &mp))) {
261862306a36Sopenharmony_ci		IREAD_UNLOCK(ipimap);
261962306a36Sopenharmony_ci		rc = -EIO;
262062306a36Sopenharmony_ci		goto out;
262162306a36Sopenharmony_ci	}
262262306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	/* remove the iag from the iag free list */
262562306a36Sopenharmony_ci	imap->im_freeiag = le32_to_cpu(iagp->iagfree);
262662306a36Sopenharmony_ci	iagp->iagfree = cpu_to_le32(-1);
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	/* set the return iag number and buffer pointer */
262962306a36Sopenharmony_ci	*iagnop = iagno;
263062306a36Sopenharmony_ci	*mpp = mp;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci      out:
263362306a36Sopenharmony_ci	/* release the iag free lock */
263462306a36Sopenharmony_ci	IAGFREE_UNLOCK(imap);
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci	return (rc);
263762306a36Sopenharmony_ci}
263862306a36Sopenharmony_ci
263962306a36Sopenharmony_ci/*
264062306a36Sopenharmony_ci * NAME:	diIAGRead()
264162306a36Sopenharmony_ci *
264262306a36Sopenharmony_ci * FUNCTION:	get the buffer for the specified iag within a fileset
264362306a36Sopenharmony_ci *		or aggregate inode map.
264462306a36Sopenharmony_ci *
264562306a36Sopenharmony_ci * PARAMETERS:
264662306a36Sopenharmony_ci *	imap	- pointer to inode map control structure.
264762306a36Sopenharmony_ci *	iagno	- iag number.
264862306a36Sopenharmony_ci *	bpp	- point to buffer pointer to be filled in on successful
264962306a36Sopenharmony_ci *		  exit.
265062306a36Sopenharmony_ci *
265162306a36Sopenharmony_ci * SERIALIZATION:
265262306a36Sopenharmony_ci *	must have read lock on imap inode
265362306a36Sopenharmony_ci *	(When called by diExtendFS, the filesystem is quiesced, therefore
265462306a36Sopenharmony_ci *	 the read lock is unnecessary.)
265562306a36Sopenharmony_ci *
265662306a36Sopenharmony_ci * RETURN VALUES:
265762306a36Sopenharmony_ci *	0	- success.
265862306a36Sopenharmony_ci *	-EIO	- i/o error.
265962306a36Sopenharmony_ci */
266062306a36Sopenharmony_cistatic int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
266162306a36Sopenharmony_ci{
266262306a36Sopenharmony_ci	struct inode *ipimap = imap->im_ipimap;
266362306a36Sopenharmony_ci	s64 blkno;
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci	/* compute the logical block number of the iag. */
266662306a36Sopenharmony_ci	blkno = IAGTOLBLK(iagno, JFS_SBI(ipimap->i_sb)->l2nbperpage);
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci	/* read the iag. */
266962306a36Sopenharmony_ci	*mpp = read_metapage(ipimap, blkno, PSIZE, 0);
267062306a36Sopenharmony_ci	if (*mpp == NULL) {
267162306a36Sopenharmony_ci		return -EIO;
267262306a36Sopenharmony_ci	}
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci	return (0);
267562306a36Sopenharmony_ci}
267662306a36Sopenharmony_ci
267762306a36Sopenharmony_ci/*
267862306a36Sopenharmony_ci * NAME:	diFindFree()
267962306a36Sopenharmony_ci *
268062306a36Sopenharmony_ci * FUNCTION:	find the first free bit in a word starting at
268162306a36Sopenharmony_ci *		the specified bit position.
268262306a36Sopenharmony_ci *
268362306a36Sopenharmony_ci * PARAMETERS:
268462306a36Sopenharmony_ci *	word	- word to be examined.
268562306a36Sopenharmony_ci *	start	- starting bit position.
268662306a36Sopenharmony_ci *
268762306a36Sopenharmony_ci * RETURN VALUES:
268862306a36Sopenharmony_ci *	bit position of first free bit in the word or 32 if
268962306a36Sopenharmony_ci *	no free bits were found.
269062306a36Sopenharmony_ci */
269162306a36Sopenharmony_cistatic int diFindFree(u32 word, int start)
269262306a36Sopenharmony_ci{
269362306a36Sopenharmony_ci	int bitno;
269462306a36Sopenharmony_ci	assert(start < 32);
269562306a36Sopenharmony_ci	/* scan the word for the first free bit. */
269662306a36Sopenharmony_ci	for (word <<= start, bitno = start; bitno < 32;
269762306a36Sopenharmony_ci	     bitno++, word <<= 1) {
269862306a36Sopenharmony_ci		if ((word & HIGHORDER) == 0)
269962306a36Sopenharmony_ci			break;
270062306a36Sopenharmony_ci	}
270162306a36Sopenharmony_ci	return (bitno);
270262306a36Sopenharmony_ci}
270362306a36Sopenharmony_ci
270462306a36Sopenharmony_ci/*
270562306a36Sopenharmony_ci * NAME:	diUpdatePMap()
270662306a36Sopenharmony_ci *
270762306a36Sopenharmony_ci * FUNCTION: Update the persistent map in an IAG for the allocation or
270862306a36Sopenharmony_ci *	freeing of the specified inode.
270962306a36Sopenharmony_ci *
271062306a36Sopenharmony_ci * PRE CONDITIONS: Working map has already been updated for allocate.
271162306a36Sopenharmony_ci *
271262306a36Sopenharmony_ci * PARAMETERS:
271362306a36Sopenharmony_ci *	ipimap	- Incore inode map inode
271462306a36Sopenharmony_ci *	inum	- Number of inode to mark in permanent map
271562306a36Sopenharmony_ci *	is_free	- If 'true' indicates inode should be marked freed, otherwise
271662306a36Sopenharmony_ci *		  indicates inode should be marked allocated.
271762306a36Sopenharmony_ci *
271862306a36Sopenharmony_ci * RETURN VALUES:
271962306a36Sopenharmony_ci *		0 for success
272062306a36Sopenharmony_ci */
272162306a36Sopenharmony_ciint
272262306a36Sopenharmony_cidiUpdatePMap(struct inode *ipimap,
272362306a36Sopenharmony_ci	     unsigned long inum, bool is_free, struct tblock * tblk)
272462306a36Sopenharmony_ci{
272562306a36Sopenharmony_ci	int rc;
272662306a36Sopenharmony_ci	struct iag *iagp;
272762306a36Sopenharmony_ci	struct metapage *mp;
272862306a36Sopenharmony_ci	int iagno, ino, extno, bitno;
272962306a36Sopenharmony_ci	struct inomap *imap;
273062306a36Sopenharmony_ci	u32 mask;
273162306a36Sopenharmony_ci	struct jfs_log *log;
273262306a36Sopenharmony_ci	int lsn, difft, diffp;
273362306a36Sopenharmony_ci	unsigned long flags;
273462306a36Sopenharmony_ci
273562306a36Sopenharmony_ci	imap = JFS_IP(ipimap)->i_imap;
273662306a36Sopenharmony_ci	/* get the iag number containing the inode */
273762306a36Sopenharmony_ci	iagno = INOTOIAG(inum);
273862306a36Sopenharmony_ci	/* make sure that the iag is contained within the map */
273962306a36Sopenharmony_ci	if (iagno >= imap->im_nextiag) {
274062306a36Sopenharmony_ci		jfs_error(ipimap->i_sb, "the iag is outside the map\n");
274162306a36Sopenharmony_ci		return -EIO;
274262306a36Sopenharmony_ci	}
274362306a36Sopenharmony_ci	/* read the iag */
274462306a36Sopenharmony_ci	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
274562306a36Sopenharmony_ci	rc = diIAGRead(imap, iagno, &mp);
274662306a36Sopenharmony_ci	IREAD_UNLOCK(ipimap);
274762306a36Sopenharmony_ci	if (rc)
274862306a36Sopenharmony_ci		return (rc);
274962306a36Sopenharmony_ci	metapage_wait_for_io(mp);
275062306a36Sopenharmony_ci	iagp = (struct iag *) mp->data;
275162306a36Sopenharmony_ci	/* get the inode number and extent number of the inode within
275262306a36Sopenharmony_ci	 * the iag and the inode number within the extent.
275362306a36Sopenharmony_ci	 */
275462306a36Sopenharmony_ci	ino = inum & (INOSPERIAG - 1);
275562306a36Sopenharmony_ci	extno = ino >> L2INOSPEREXT;
275662306a36Sopenharmony_ci	bitno = ino & (INOSPEREXT - 1);
275762306a36Sopenharmony_ci	mask = HIGHORDER >> bitno;
275862306a36Sopenharmony_ci	/*
275962306a36Sopenharmony_ci	 * mark the inode free in persistent map:
276062306a36Sopenharmony_ci	 */
276162306a36Sopenharmony_ci	if (is_free) {
276262306a36Sopenharmony_ci		/* The inode should have been allocated both in working
276362306a36Sopenharmony_ci		 * map and in persistent map;
276462306a36Sopenharmony_ci		 * the inode will be freed from working map at the release
276562306a36Sopenharmony_ci		 * of last reference release;
276662306a36Sopenharmony_ci		 */
276762306a36Sopenharmony_ci		if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
276862306a36Sopenharmony_ci			jfs_error(ipimap->i_sb,
276962306a36Sopenharmony_ci				  "inode %ld not marked as allocated in wmap!\n",
277062306a36Sopenharmony_ci				  inum);
277162306a36Sopenharmony_ci		}
277262306a36Sopenharmony_ci		if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) {
277362306a36Sopenharmony_ci			jfs_error(ipimap->i_sb,
277462306a36Sopenharmony_ci				  "inode %ld not marked as allocated in pmap!\n",
277562306a36Sopenharmony_ci				  inum);
277662306a36Sopenharmony_ci		}
277762306a36Sopenharmony_ci		/* update the bitmap for the extent of the freed inode */
277862306a36Sopenharmony_ci		iagp->pmap[extno] &= cpu_to_le32(~mask);
277962306a36Sopenharmony_ci	}
278062306a36Sopenharmony_ci	/*
278162306a36Sopenharmony_ci	 * mark the inode allocated in persistent map:
278262306a36Sopenharmony_ci	 */
278362306a36Sopenharmony_ci	else {
278462306a36Sopenharmony_ci		/* The inode should be already allocated in the working map
278562306a36Sopenharmony_ci		 * and should be free in persistent map;
278662306a36Sopenharmony_ci		 */
278762306a36Sopenharmony_ci		if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
278862306a36Sopenharmony_ci			release_metapage(mp);
278962306a36Sopenharmony_ci			jfs_error(ipimap->i_sb,
279062306a36Sopenharmony_ci				  "the inode is not allocated in the working map\n");
279162306a36Sopenharmony_ci			return -EIO;
279262306a36Sopenharmony_ci		}
279362306a36Sopenharmony_ci		if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) {
279462306a36Sopenharmony_ci			release_metapage(mp);
279562306a36Sopenharmony_ci			jfs_error(ipimap->i_sb,
279662306a36Sopenharmony_ci				  "the inode is not free in the persistent map\n");
279762306a36Sopenharmony_ci			return -EIO;
279862306a36Sopenharmony_ci		}
279962306a36Sopenharmony_ci		/* update the bitmap for the extent of the allocated inode */
280062306a36Sopenharmony_ci		iagp->pmap[extno] |= cpu_to_le32(mask);
280162306a36Sopenharmony_ci	}
280262306a36Sopenharmony_ci	/*
280362306a36Sopenharmony_ci	 * update iag lsn
280462306a36Sopenharmony_ci	 */
280562306a36Sopenharmony_ci	lsn = tblk->lsn;
280662306a36Sopenharmony_ci	log = JFS_SBI(tblk->sb)->log;
280762306a36Sopenharmony_ci	LOGSYNC_LOCK(log, flags);
280862306a36Sopenharmony_ci	if (mp->lsn != 0) {
280962306a36Sopenharmony_ci		/* inherit older/smaller lsn */
281062306a36Sopenharmony_ci		logdiff(difft, lsn, log);
281162306a36Sopenharmony_ci		logdiff(diffp, mp->lsn, log);
281262306a36Sopenharmony_ci		if (difft < diffp) {
281362306a36Sopenharmony_ci			mp->lsn = lsn;
281462306a36Sopenharmony_ci			/* move mp after tblock in logsync list */
281562306a36Sopenharmony_ci			list_move(&mp->synclist, &tblk->synclist);
281662306a36Sopenharmony_ci		}
281762306a36Sopenharmony_ci		/* inherit younger/larger clsn */
281862306a36Sopenharmony_ci		assert(mp->clsn);
281962306a36Sopenharmony_ci		logdiff(difft, tblk->clsn, log);
282062306a36Sopenharmony_ci		logdiff(diffp, mp->clsn, log);
282162306a36Sopenharmony_ci		if (difft > diffp)
282262306a36Sopenharmony_ci			mp->clsn = tblk->clsn;
282362306a36Sopenharmony_ci	} else {
282462306a36Sopenharmony_ci		mp->log = log;
282562306a36Sopenharmony_ci		mp->lsn = lsn;
282662306a36Sopenharmony_ci		/* insert mp after tblock in logsync list */
282762306a36Sopenharmony_ci		log->count++;
282862306a36Sopenharmony_ci		list_add(&mp->synclist, &tblk->synclist);
282962306a36Sopenharmony_ci		mp->clsn = tblk->clsn;
283062306a36Sopenharmony_ci	}
283162306a36Sopenharmony_ci	LOGSYNC_UNLOCK(log, flags);
283262306a36Sopenharmony_ci	write_metapage(mp);
283362306a36Sopenharmony_ci	return (0);
283462306a36Sopenharmony_ci}
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci/*
283762306a36Sopenharmony_ci *	diExtendFS()
283862306a36Sopenharmony_ci *
283962306a36Sopenharmony_ci * function: update imap for extendfs();
284062306a36Sopenharmony_ci *
284162306a36Sopenharmony_ci * note: AG size has been increased s.t. each k old contiguous AGs are
284262306a36Sopenharmony_ci * coalesced into a new AG;
284362306a36Sopenharmony_ci */
284462306a36Sopenharmony_ciint diExtendFS(struct inode *ipimap, struct inode *ipbmap)
284562306a36Sopenharmony_ci{
284662306a36Sopenharmony_ci	int rc, rcx = 0;
284762306a36Sopenharmony_ci	struct inomap *imap = JFS_IP(ipimap)->i_imap;
284862306a36Sopenharmony_ci	struct iag *iagp = NULL, *hiagp = NULL;
284962306a36Sopenharmony_ci	struct bmap *mp = JFS_SBI(ipbmap->i_sb)->bmap;
285062306a36Sopenharmony_ci	struct metapage *bp, *hbp;
285162306a36Sopenharmony_ci	int i, n, head;
285262306a36Sopenharmony_ci	int numinos, xnuminos = 0, xnumfree = 0;
285362306a36Sopenharmony_ci	s64 agstart;
285462306a36Sopenharmony_ci
285562306a36Sopenharmony_ci	jfs_info("diExtendFS: nextiag:%d numinos:%d numfree:%d",
285662306a36Sopenharmony_ci		   imap->im_nextiag, atomic_read(&imap->im_numinos),
285762306a36Sopenharmony_ci		   atomic_read(&imap->im_numfree));
285862306a36Sopenharmony_ci
285962306a36Sopenharmony_ci	/*
286062306a36Sopenharmony_ci	 *	reconstruct imap
286162306a36Sopenharmony_ci	 *
286262306a36Sopenharmony_ci	 * coalesce contiguous k (newAGSize/oldAGSize) AGs;
286362306a36Sopenharmony_ci	 * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
286462306a36Sopenharmony_ci	 * note: new AG size = old AG size * (2**x).
286562306a36Sopenharmony_ci	 */
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	/* init per AG control information im_agctl[] */
286862306a36Sopenharmony_ci	for (i = 0; i < MAXAG; i++) {
286962306a36Sopenharmony_ci		imap->im_agctl[i].inofree = -1;
287062306a36Sopenharmony_ci		imap->im_agctl[i].extfree = -1;
287162306a36Sopenharmony_ci		imap->im_agctl[i].numinos = 0;	/* number of backed inodes */
287262306a36Sopenharmony_ci		imap->im_agctl[i].numfree = 0;	/* number of free backed inodes */
287362306a36Sopenharmony_ci	}
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci	/*
287662306a36Sopenharmony_ci	 *	process each iag page of the map.
287762306a36Sopenharmony_ci	 *
287862306a36Sopenharmony_ci	 * rebuild AG Free Inode List, AG Free Inode Extent List;
287962306a36Sopenharmony_ci	 */
288062306a36Sopenharmony_ci	for (i = 0; i < imap->im_nextiag; i++) {
288162306a36Sopenharmony_ci		if ((rc = diIAGRead(imap, i, &bp))) {
288262306a36Sopenharmony_ci			rcx = rc;
288362306a36Sopenharmony_ci			continue;
288462306a36Sopenharmony_ci		}
288562306a36Sopenharmony_ci		iagp = (struct iag *) bp->data;
288662306a36Sopenharmony_ci		if (le32_to_cpu(iagp->iagnum) != i) {
288762306a36Sopenharmony_ci			release_metapage(bp);
288862306a36Sopenharmony_ci			jfs_error(ipimap->i_sb, "unexpected value of iagnum\n");
288962306a36Sopenharmony_ci			return -EIO;
289062306a36Sopenharmony_ci		}
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci		/* leave free iag in the free iag list */
289362306a36Sopenharmony_ci		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
289462306a36Sopenharmony_ci			release_metapage(bp);
289562306a36Sopenharmony_ci			continue;
289662306a36Sopenharmony_ci		}
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci		agstart = le64_to_cpu(iagp->agstart);
289962306a36Sopenharmony_ci		n = agstart >> mp->db_agl2size;
290062306a36Sopenharmony_ci		iagp->agstart = cpu_to_le64((s64)n << mp->db_agl2size);
290162306a36Sopenharmony_ci
290262306a36Sopenharmony_ci		/* compute backed inodes */
290362306a36Sopenharmony_ci		numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts))
290462306a36Sopenharmony_ci		    << L2INOSPEREXT;
290562306a36Sopenharmony_ci		if (numinos > 0) {
290662306a36Sopenharmony_ci			/* merge AG backed inodes */
290762306a36Sopenharmony_ci			imap->im_agctl[n].numinos += numinos;
290862306a36Sopenharmony_ci			xnuminos += numinos;
290962306a36Sopenharmony_ci		}
291062306a36Sopenharmony_ci
291162306a36Sopenharmony_ci		/* if any backed free inodes, insert at AG free inode list */
291262306a36Sopenharmony_ci		if ((int) le32_to_cpu(iagp->nfreeinos) > 0) {
291362306a36Sopenharmony_ci			if ((head = imap->im_agctl[n].inofree) == -1) {
291462306a36Sopenharmony_ci				iagp->inofreefwd = cpu_to_le32(-1);
291562306a36Sopenharmony_ci				iagp->inofreeback = cpu_to_le32(-1);
291662306a36Sopenharmony_ci			} else {
291762306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, head, &hbp))) {
291862306a36Sopenharmony_ci					rcx = rc;
291962306a36Sopenharmony_ci					goto nextiag;
292062306a36Sopenharmony_ci				}
292162306a36Sopenharmony_ci				hiagp = (struct iag *) hbp->data;
292262306a36Sopenharmony_ci				hiagp->inofreeback = iagp->iagnum;
292362306a36Sopenharmony_ci				iagp->inofreefwd = cpu_to_le32(head);
292462306a36Sopenharmony_ci				iagp->inofreeback = cpu_to_le32(-1);
292562306a36Sopenharmony_ci				write_metapage(hbp);
292662306a36Sopenharmony_ci			}
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci			imap->im_agctl[n].inofree =
292962306a36Sopenharmony_ci			    le32_to_cpu(iagp->iagnum);
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci			/* merge AG backed free inodes */
293262306a36Sopenharmony_ci			imap->im_agctl[n].numfree +=
293362306a36Sopenharmony_ci			    le32_to_cpu(iagp->nfreeinos);
293462306a36Sopenharmony_ci			xnumfree += le32_to_cpu(iagp->nfreeinos);
293562306a36Sopenharmony_ci		}
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci		/* if any free extents, insert at AG free extent list */
293862306a36Sopenharmony_ci		if (le32_to_cpu(iagp->nfreeexts) > 0) {
293962306a36Sopenharmony_ci			if ((head = imap->im_agctl[n].extfree) == -1) {
294062306a36Sopenharmony_ci				iagp->extfreefwd = cpu_to_le32(-1);
294162306a36Sopenharmony_ci				iagp->extfreeback = cpu_to_le32(-1);
294262306a36Sopenharmony_ci			} else {
294362306a36Sopenharmony_ci				if ((rc = diIAGRead(imap, head, &hbp))) {
294462306a36Sopenharmony_ci					rcx = rc;
294562306a36Sopenharmony_ci					goto nextiag;
294662306a36Sopenharmony_ci				}
294762306a36Sopenharmony_ci				hiagp = (struct iag *) hbp->data;
294862306a36Sopenharmony_ci				hiagp->extfreeback = iagp->iagnum;
294962306a36Sopenharmony_ci				iagp->extfreefwd = cpu_to_le32(head);
295062306a36Sopenharmony_ci				iagp->extfreeback = cpu_to_le32(-1);
295162306a36Sopenharmony_ci				write_metapage(hbp);
295262306a36Sopenharmony_ci			}
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci			imap->im_agctl[n].extfree =
295562306a36Sopenharmony_ci			    le32_to_cpu(iagp->iagnum);
295662306a36Sopenharmony_ci		}
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	      nextiag:
295962306a36Sopenharmony_ci		write_metapage(bp);
296062306a36Sopenharmony_ci	}
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	if (xnuminos != atomic_read(&imap->im_numinos) ||
296362306a36Sopenharmony_ci	    xnumfree != atomic_read(&imap->im_numfree)) {
296462306a36Sopenharmony_ci		jfs_error(ipimap->i_sb, "numinos or numfree incorrect\n");
296562306a36Sopenharmony_ci		return -EIO;
296662306a36Sopenharmony_ci	}
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	return rcx;
296962306a36Sopenharmony_ci}
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci/*
297362306a36Sopenharmony_ci *	duplicateIXtree()
297462306a36Sopenharmony_ci *
297562306a36Sopenharmony_ci * serialization: IWRITE_LOCK held on entry/exit
297662306a36Sopenharmony_ci *
297762306a36Sopenharmony_ci * note: shadow page with regular inode (rel.2);
297862306a36Sopenharmony_ci */
297962306a36Sopenharmony_cistatic void duplicateIXtree(struct super_block *sb, s64 blkno,
298062306a36Sopenharmony_ci			    int xlen, s64 *xaddr)
298162306a36Sopenharmony_ci{
298262306a36Sopenharmony_ci	struct jfs_superblock *j_sb;
298362306a36Sopenharmony_ci	struct buffer_head *bh;
298462306a36Sopenharmony_ci	struct inode *ip;
298562306a36Sopenharmony_ci	tid_t tid;
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	/* if AIT2 ipmap2 is bad, do not try to update it */
298862306a36Sopenharmony_ci	if (JFS_SBI(sb)->mntflag & JFS_BAD_SAIT)	/* s_flag */
298962306a36Sopenharmony_ci		return;
299062306a36Sopenharmony_ci	ip = diReadSpecial(sb, FILESYSTEM_I, 1);
299162306a36Sopenharmony_ci	if (ip == NULL) {
299262306a36Sopenharmony_ci		JFS_SBI(sb)->mntflag |= JFS_BAD_SAIT;
299362306a36Sopenharmony_ci		if (readSuper(sb, &bh))
299462306a36Sopenharmony_ci			return;
299562306a36Sopenharmony_ci		j_sb = (struct jfs_superblock *)bh->b_data;
299662306a36Sopenharmony_ci		j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci		mark_buffer_dirty(bh);
299962306a36Sopenharmony_ci		sync_dirty_buffer(bh);
300062306a36Sopenharmony_ci		brelse(bh);
300162306a36Sopenharmony_ci		return;
300262306a36Sopenharmony_ci	}
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	/* start transaction */
300562306a36Sopenharmony_ci	tid = txBegin(sb, COMMIT_FORCE);
300662306a36Sopenharmony_ci	/* update the inode map addressing structure to point to it */
300762306a36Sopenharmony_ci	if (xtInsert(tid, ip, 0, blkno, xlen, xaddr, 0)) {
300862306a36Sopenharmony_ci		JFS_SBI(sb)->mntflag |= JFS_BAD_SAIT;
300962306a36Sopenharmony_ci		txAbort(tid, 1);
301062306a36Sopenharmony_ci		goto cleanup;
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci	}
301362306a36Sopenharmony_ci	/* update the inode map's inode to reflect the extension */
301462306a36Sopenharmony_ci	ip->i_size += PSIZE;
301562306a36Sopenharmony_ci	inode_add_bytes(ip, PSIZE);
301662306a36Sopenharmony_ci	txCommit(tid, 1, &ip, COMMIT_FORCE);
301762306a36Sopenharmony_ci      cleanup:
301862306a36Sopenharmony_ci	txEnd(tid);
301962306a36Sopenharmony_ci	diFreeSpecial(ip);
302062306a36Sopenharmony_ci}
302162306a36Sopenharmony_ci
302262306a36Sopenharmony_ci/*
302362306a36Sopenharmony_ci * NAME:	copy_from_dinode()
302462306a36Sopenharmony_ci *
302562306a36Sopenharmony_ci * FUNCTION:	Copies inode info from disk inode to in-memory inode
302662306a36Sopenharmony_ci *
302762306a36Sopenharmony_ci * RETURN VALUES:
302862306a36Sopenharmony_ci *	0	- success
302962306a36Sopenharmony_ci *	-ENOMEM	- insufficient memory
303062306a36Sopenharmony_ci */
303162306a36Sopenharmony_cistatic int copy_from_dinode(struct dinode * dip, struct inode *ip)
303262306a36Sopenharmony_ci{
303362306a36Sopenharmony_ci	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
303462306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
303762306a36Sopenharmony_ci	jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
303862306a36Sopenharmony_ci	jfs_set_inode_flags(ip);
303962306a36Sopenharmony_ci
304062306a36Sopenharmony_ci	ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
304162306a36Sopenharmony_ci	if (sbi->umask != -1) {
304262306a36Sopenharmony_ci		ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask);
304362306a36Sopenharmony_ci		/* For directories, add x permission if r is allowed by umask */
304462306a36Sopenharmony_ci		if (S_ISDIR(ip->i_mode)) {
304562306a36Sopenharmony_ci			if (ip->i_mode & 0400)
304662306a36Sopenharmony_ci				ip->i_mode |= 0100;
304762306a36Sopenharmony_ci			if (ip->i_mode & 0040)
304862306a36Sopenharmony_ci				ip->i_mode |= 0010;
304962306a36Sopenharmony_ci			if (ip->i_mode & 0004)
305062306a36Sopenharmony_ci				ip->i_mode |= 0001;
305162306a36Sopenharmony_ci		}
305262306a36Sopenharmony_ci	}
305362306a36Sopenharmony_ci	set_nlink(ip, le32_to_cpu(dip->di_nlink));
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci	jfs_ip->saved_uid = make_kuid(&init_user_ns, le32_to_cpu(dip->di_uid));
305662306a36Sopenharmony_ci	if (!uid_valid(sbi->uid))
305762306a36Sopenharmony_ci		ip->i_uid = jfs_ip->saved_uid;
305862306a36Sopenharmony_ci	else {
305962306a36Sopenharmony_ci		ip->i_uid = sbi->uid;
306062306a36Sopenharmony_ci	}
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_ci	jfs_ip->saved_gid = make_kgid(&init_user_ns, le32_to_cpu(dip->di_gid));
306362306a36Sopenharmony_ci	if (!gid_valid(sbi->gid))
306462306a36Sopenharmony_ci		ip->i_gid = jfs_ip->saved_gid;
306562306a36Sopenharmony_ci	else {
306662306a36Sopenharmony_ci		ip->i_gid = sbi->gid;
306762306a36Sopenharmony_ci	}
306862306a36Sopenharmony_ci
306962306a36Sopenharmony_ci	ip->i_size = le64_to_cpu(dip->di_size);
307062306a36Sopenharmony_ci	ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
307162306a36Sopenharmony_ci	ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
307262306a36Sopenharmony_ci	ip->i_mtime.tv_sec = le32_to_cpu(dip->di_mtime.tv_sec);
307362306a36Sopenharmony_ci	ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
307462306a36Sopenharmony_ci	inode_set_ctime(ip, le32_to_cpu(dip->di_ctime.tv_sec),
307562306a36Sopenharmony_ci			le32_to_cpu(dip->di_ctime.tv_nsec));
307662306a36Sopenharmony_ci	ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
307762306a36Sopenharmony_ci	ip->i_generation = le32_to_cpu(dip->di_gen);
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci	jfs_ip->ixpxd = dip->di_ixpxd;	/* in-memory pxd's are little-endian */
308062306a36Sopenharmony_ci	jfs_ip->acl = dip->di_acl;	/* as are dxd's */
308162306a36Sopenharmony_ci	jfs_ip->ea = dip->di_ea;
308262306a36Sopenharmony_ci	jfs_ip->next_index = le32_to_cpu(dip->di_next_index);
308362306a36Sopenharmony_ci	jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec);
308462306a36Sopenharmony_ci	jfs_ip->acltype = le32_to_cpu(dip->di_acltype);
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci	if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) {
308762306a36Sopenharmony_ci		jfs_ip->dev = le32_to_cpu(dip->di_rdev);
308862306a36Sopenharmony_ci		ip->i_rdev = new_decode_dev(jfs_ip->dev);
308962306a36Sopenharmony_ci	}
309062306a36Sopenharmony_ci
309162306a36Sopenharmony_ci	if (S_ISDIR(ip->i_mode)) {
309262306a36Sopenharmony_ci		memcpy(&jfs_ip->u.dir, &dip->u._dir, 384);
309362306a36Sopenharmony_ci	} else if (S_ISREG(ip->i_mode) || S_ISLNK(ip->i_mode)) {
309462306a36Sopenharmony_ci		memcpy(&jfs_ip->i_xtroot, &dip->di_xtroot, 288);
309562306a36Sopenharmony_ci	} else
309662306a36Sopenharmony_ci		memcpy(&jfs_ip->i_inline_ea, &dip->di_inlineea, 128);
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci	/* Zero the in-memory-only stuff */
309962306a36Sopenharmony_ci	jfs_ip->cflag = 0;
310062306a36Sopenharmony_ci	jfs_ip->btindex = 0;
310162306a36Sopenharmony_ci	jfs_ip->btorder = 0;
310262306a36Sopenharmony_ci	jfs_ip->bxflag = 0;
310362306a36Sopenharmony_ci	jfs_ip->blid = 0;
310462306a36Sopenharmony_ci	jfs_ip->atlhead = 0;
310562306a36Sopenharmony_ci	jfs_ip->atltail = 0;
310662306a36Sopenharmony_ci	jfs_ip->xtlid = 0;
310762306a36Sopenharmony_ci	return (0);
310862306a36Sopenharmony_ci}
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci/*
311162306a36Sopenharmony_ci * NAME:	copy_to_dinode()
311262306a36Sopenharmony_ci *
311362306a36Sopenharmony_ci * FUNCTION:	Copies inode info from in-memory inode to disk inode
311462306a36Sopenharmony_ci */
311562306a36Sopenharmony_cistatic void copy_to_dinode(struct dinode * dip, struct inode *ip)
311662306a36Sopenharmony_ci{
311762306a36Sopenharmony_ci	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
311862306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
311962306a36Sopenharmony_ci
312062306a36Sopenharmony_ci	dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
312162306a36Sopenharmony_ci	dip->di_inostamp = cpu_to_le32(sbi->inostamp);
312262306a36Sopenharmony_ci	dip->di_number = cpu_to_le32(ip->i_ino);
312362306a36Sopenharmony_ci	dip->di_gen = cpu_to_le32(ip->i_generation);
312462306a36Sopenharmony_ci	dip->di_size = cpu_to_le64(ip->i_size);
312562306a36Sopenharmony_ci	dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
312662306a36Sopenharmony_ci	dip->di_nlink = cpu_to_le32(ip->i_nlink);
312762306a36Sopenharmony_ci	if (!uid_valid(sbi->uid))
312862306a36Sopenharmony_ci		dip->di_uid = cpu_to_le32(i_uid_read(ip));
312962306a36Sopenharmony_ci	else
313062306a36Sopenharmony_ci		dip->di_uid =cpu_to_le32(from_kuid(&init_user_ns,
313162306a36Sopenharmony_ci						   jfs_ip->saved_uid));
313262306a36Sopenharmony_ci	if (!gid_valid(sbi->gid))
313362306a36Sopenharmony_ci		dip->di_gid = cpu_to_le32(i_gid_read(ip));
313462306a36Sopenharmony_ci	else
313562306a36Sopenharmony_ci		dip->di_gid = cpu_to_le32(from_kgid(&init_user_ns,
313662306a36Sopenharmony_ci						    jfs_ip->saved_gid));
313762306a36Sopenharmony_ci	/*
313862306a36Sopenharmony_ci	 * mode2 is only needed for storing the higher order bits.
313962306a36Sopenharmony_ci	 * Trust i_mode for the lower order ones
314062306a36Sopenharmony_ci	 */
314162306a36Sopenharmony_ci	if (sbi->umask == -1)
314262306a36Sopenharmony_ci		dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) |
314362306a36Sopenharmony_ci					   ip->i_mode);
314462306a36Sopenharmony_ci	else /* Leave the original permissions alone */
314562306a36Sopenharmony_ci		dip->di_mode = cpu_to_le32(jfs_ip->mode2);
314662306a36Sopenharmony_ci
314762306a36Sopenharmony_ci	dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
314862306a36Sopenharmony_ci	dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
314962306a36Sopenharmony_ci	dip->di_ctime.tv_sec = cpu_to_le32(inode_get_ctime(ip).tv_sec);
315062306a36Sopenharmony_ci	dip->di_ctime.tv_nsec = cpu_to_le32(inode_get_ctime(ip).tv_nsec);
315162306a36Sopenharmony_ci	dip->di_mtime.tv_sec = cpu_to_le32(ip->i_mtime.tv_sec);
315262306a36Sopenharmony_ci	dip->di_mtime.tv_nsec = cpu_to_le32(ip->i_mtime.tv_nsec);
315362306a36Sopenharmony_ci	dip->di_ixpxd = jfs_ip->ixpxd;	/* in-memory pxd's are little-endian */
315462306a36Sopenharmony_ci	dip->di_acl = jfs_ip->acl;	/* as are dxd's */
315562306a36Sopenharmony_ci	dip->di_ea = jfs_ip->ea;
315662306a36Sopenharmony_ci	dip->di_next_index = cpu_to_le32(jfs_ip->next_index);
315762306a36Sopenharmony_ci	dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime);
315862306a36Sopenharmony_ci	dip->di_otime.tv_nsec = 0;
315962306a36Sopenharmony_ci	dip->di_acltype = cpu_to_le32(jfs_ip->acltype);
316062306a36Sopenharmony_ci	if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
316162306a36Sopenharmony_ci		dip->di_rdev = cpu_to_le32(jfs_ip->dev);
316262306a36Sopenharmony_ci}
3163