Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54fb996a authored by Evgeniy Dushistov's avatar Evgeniy Dushistov Committed by Linus Torvalds
Browse files

[PATCH] ufs2 write: block allocation update



Patch adds ability to work with 64bit metadata, this made by replacing work
with 32bit pointers by inline functions.

Signed-off-by: default avatarEvgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 3313e292
Loading
Loading
Loading
Loading
+117 −80
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
 * Copyright (C) 1998
 * Daniel Pirkl <daniel.pirkl@email.cz>
 * Charles University, Faculty of Mathematics and Physics
 *
 * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
 */

#include <linux/fs.h>
@@ -21,38 +23,42 @@
#include "swab.h"
#include "util.h"

static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
#define INVBLOCK ((u64)-1L)

static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *);
static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);

/*
 * Free 'count' fragments from fragment number 'fragment'
 */
void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;
	unsigned cgno, bit, end_bit, bbase, blkmap, i;
	u64 blkno;
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
	usb1 = ubh_get_usb_first(uspi);
	
	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
	UFSD("ENTER, fragment %llu, count %u\n",
	     (unsigned long long)fragment, count);
	
	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
		ufs_error (sb, "ufs_free_fragments", "internal error");
	
	lock_super(sb);
	
	cgno = ufs_dtog(fragment);
	bit = ufs_dtogd(fragment);
	cgno = ufs_dtog(uspi, fragment);
	bit = ufs_dtogd(uspi, fragment);
	if (cgno >= uspi->s_ncg) {
		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
		goto failed;
@@ -101,10 +107,14 @@ void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
		uspi->cs_total.cs_nbfree++;
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
		cylno = ufs_cbtocylno (bbase);
		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
		if (uspi->fs_magic != UFS2_MAGIC) {
			unsigned cylno = ufs_cbtocylno (bbase);

			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
						  ufs_cbtorpos(bbase)), 1);
			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
		}
	}
	
	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
@@ -127,24 +137,27 @@ void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
/*
 * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
 */
void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;
	unsigned overflow, cgno, bit, end_bit, i;
	u64 blkno;
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
	usb1 = ubh_get_usb_first(uspi);

	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
	UFSD("ENTER, fragment %llu, count %u\n",
	     (unsigned long long)fragment, count);
	
	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
		ufs_error (sb, "ufs_free_blocks", "internal error, "
			"fragment %u, count %u\n", fragment, count);
			   "fragment %llu, count %u\n",
			   (unsigned long long)fragment, count);
		goto failed;
	}

@@ -152,8 +165,8 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
	
do_more:
	overflow = 0;
	cgno = ufs_dtog (fragment);
	bit = ufs_dtogd (fragment);
	cgno = ufs_dtog(uspi, fragment);
	bit = ufs_dtogd(uspi, fragment);
	if (cgno >= uspi->s_ncg) {
		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
		goto failed_unlock;
@@ -187,10 +200,15 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
		uspi->cs_total.cs_nbfree++;
		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
		cylno = ufs_cbtocylno(i);
		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);

		if (uspi->fs_magic != UFS2_MAGIC) {
			unsigned cylno = ufs_cbtocylno(i);

			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
						  ufs_cbtorpos(i)), 1);
			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
		}
	}

	ubh_mark_buffer_dirty (USPI_UBH(uspi));
	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
@@ -308,15 +326,19 @@ static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
	}
}

unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
			   unsigned goal, unsigned count, int * err, struct page *locked_page)
u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
			   u64 goal, unsigned count, int *err,
			   struct page *locked_page)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	unsigned cgno, oldcount, newcount, tmp, request, result;
	unsigned cgno, oldcount, newcount;
	u64 tmp, request, result;
	
	UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
	     inode->i_ino, (unsigned long long)fragment,
	     (unsigned long long)goal, count);
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
@@ -324,11 +346,12 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
	*err = -ENOSPC;

	lock_super (sb);
	tmp = ufs_data_ptr_to_cpu(sb, p);

	tmp = fs32_to_cpu(sb, *p);
	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
		ufs_warning(sb, "ufs_new_fragments", "internal warning"
			" fragment %u, count %u", fragment, count);
			    " fragment %llu, count %u",
			    (unsigned long long)fragment, count);
		count = uspi->s_fpb - ufs_fragnum(fragment); 
	}
	oldcount = ufs_fragnum (fragment);
@@ -340,9 +363,11 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
	if (oldcount) {
		if (!tmp) {
			ufs_error(sb, "ufs_new_fragments", "internal error, "
				"fragment %u, tmp %u\n", fragment, tmp);
				  "fragment %llu, tmp %llu\n",
				  (unsigned long long)fragment,
				  (unsigned long long)tmp);
			unlock_super(sb);
			return (unsigned)-1;
			return INVBLOCK;
		}
		if (fragment < UFS_I(inode)->i_lastfrag) {
			UFSD("EXIT (ALREADY ALLOCATED)\n");
@@ -372,7 +397,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
	if (goal == 0) 
		cgno = ufs_inotocg (inode->i_ino);
	else
		cgno = ufs_dtog (goal);
		cgno = ufs_dtog(uspi, goal);
	 
	/*
	 * allocate new fragment
@@ -380,14 +405,16 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
	if (oldcount == 0) {
		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
		if (result) {
			*p = cpu_to_fs32(sb, result);
			ufs_cpu_to_data_ptr(sb, p, result);
			*err = 0;
			UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
			ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
					locked_page != NULL);
			UFS_I(inode)->i_lastfrag =
				max_t(u32, UFS_I(inode)->i_lastfrag,
				      fragment + count);
			ufs_clear_frags(inode, result + oldcount,
					newcount - oldcount, locked_page != NULL);
		}
		unlock_super(sb);
		UFSD("EXIT, result %u\n", result);
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
		return result;
	}

@@ -401,7 +428,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
				locked_page != NULL);
		unlock_super(sb);
		UFSD("EXIT, result %u\n", result);
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
		return result;
	}

@@ -433,15 +460,14 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
				locked_page != NULL);
		ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
				   result, locked_page);

		*p = cpu_to_fs32(sb, result);
		ufs_cpu_to_data_ptr(sb, p, result);
		*err = 0;
		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
		unlock_super(sb);
		if (newcount < request)
			ufs_free_fragments (inode, result + newcount, request - newcount);
		ufs_free_fragments (inode, tmp, oldcount);
		UFSD("EXIT, result %u\n", result);
		UFSD("EXIT, result %llu\n", (unsigned long long)result);
		return result;
	}

@@ -450,8 +476,7 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
	return 0;
}		

static unsigned
ufs_add_fragments (struct inode * inode, unsigned fragment,
static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
			     unsigned oldcount, unsigned newcount, int *err)
{
	struct super_block * sb;
@@ -461,14 +486,15 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
	struct ufs_cylinder_group * ucg;
	unsigned cgno, fragno, fragoff, count, fragsize, i;
	
	UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
	     (unsigned long long)fragment, oldcount, newcount);
	
	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
	usb1 = ubh_get_usb_first (uspi);
	count = newcount - oldcount;
	
	cgno = ufs_dtog(fragment);
	cgno = ufs_dtog(uspi, fragment);
	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
		return 0;
	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
@@ -483,7 +509,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
		return 0;
	}

	fragno = ufs_dtogd (fragment);
	fragno = ufs_dtogd(uspi, fragment);
	fragoff = ufs_fragnum (fragno);
	for (i = oldcount; i < newcount; i++)
		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
@@ -521,7 +547,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
	}
	sb->s_dirt = 1;

	UFSD("EXIT, fragment %u\n", fragment);
	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
	
	return fragment;
}
@@ -534,17 +560,19 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
			goto cg_found; 

static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
	unsigned goal, unsigned count, int * err)
static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
			       u64 goal, unsigned count, int *err)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cg_private_info * ucpi;
	struct ufs_cylinder_group * ucg;
	unsigned oldcg, i, j, k, result, allocsize;
	unsigned oldcg, i, j, k, allocsize;
	u64 result;
	
	UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
	     inode->i_ino, cgno, (unsigned long long)goal, count);

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
@@ -593,7 +621,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,

	if (count == uspi->s_fpb) {
		result = ufs_alloccg_block (inode, ucpi, goal, err);
		if (result == (unsigned)-1)
		if (result == INVBLOCK)
			return 0;
		goto succed;
	}
@@ -604,9 +632,9 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
	
	if (allocsize == uspi->s_fpb) {
		result = ufs_alloccg_block (inode, ucpi, goal, err);
		if (result == (unsigned)-1)
		if (result == INVBLOCK)
			return 0;
		goal = ufs_dtogd (result);
		goal = ufs_dtogd(uspi, result);
		for (i = count; i < uspi->s_fpb; i++)
			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
		i = uspi->s_fpb - count;
@@ -620,7 +648,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
	}

	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
	if (result == (unsigned)-1)
	if (result == INVBLOCK)
		return 0;
	if(DQUOT_ALLOC_BLOCK(inode, count)) {
		*err = -EDQUOT;
@@ -647,20 +675,21 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
	sb->s_dirt = 1;

	result += cgno * uspi->s_fpg;
	UFSD("EXIT3, result %u\n", result);
	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
	return result;
}

static unsigned ufs_alloccg_block (struct inode * inode,
	struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
static u64 ufs_alloccg_block(struct inode *inode,
			     struct ufs_cg_private_info *ucpi,
			     u64 goal, int *err)
{
	struct super_block * sb;
	struct ufs_sb_private_info * uspi;
	struct ufs_super_block_first * usb1;
	struct ufs_cylinder_group * ucg;
	unsigned result, cylno, blkno;
	u64 result, blkno;

	UFSD("ENTER, goal %u\n", goal);
	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);

	sb = inode->i_sb;
	uspi = UFS_SB(sb)->s_uspi;
@@ -672,7 +701,7 @@ static unsigned ufs_alloccg_block (struct inode * inode,
		goto norot;
	}
	goal = ufs_blknum (goal);
	goal = ufs_dtogd (goal);
	goal = ufs_dtogd(uspi, goal);
	
	/*
	 * If the requested block is available, use it.
@@ -684,8 +713,8 @@ static unsigned ufs_alloccg_block (struct inode * inode,
	
norot:	
	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
	if (result == (unsigned)-1)
		return (unsigned)-1;
	if (result == INVBLOCK)
		return INVBLOCK;
	ucpi->c_rotor = result;
gotit:
	blkno = ufs_fragstoblks(result);
@@ -694,17 +723,22 @@ static unsigned ufs_alloccg_block (struct inode * inode,
		ufs_clusteracct (sb, ucpi, blkno, -1);
	if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
		*err = -EDQUOT;
		return (unsigned)-1;
		return INVBLOCK;
	}

	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
	uspi->cs_total.cs_nbfree--;
	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
	cylno = ufs_cbtocylno(result);
	fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);

	if (uspi->fs_magic != UFS2_MAGIC) {
		unsigned cylno = ufs_cbtocylno((unsigned)result);

		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
					  ufs_cbtorpos((unsigned)result)), 1);
		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
	}
	
	UFSD("EXIT, result %u\n", result);
	UFSD("EXIT, result %llu\n", (unsigned long long)result);

	return result;
}
@@ -744,9 +778,9 @@ static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
 * @goal: near which block we want find new one
 * @count: specified size
 */
static unsigned ufs_bitmap_search(struct super_block *sb,
static u64 ufs_bitmap_search(struct super_block *sb,
			     struct ufs_cg_private_info *ucpi,
				  unsigned goal, unsigned count)
			     u64 goal, unsigned count)
{
	/*
	 * Bit patterns for identifying fragments in the block map
@@ -761,16 +795,18 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	struct ufs_super_block_first *usb1;
	struct ufs_cylinder_group *ucg;
	unsigned start, length, loc, result;
	unsigned start, length, loc;
	unsigned pos, want, blockmap, mask, end;
	u64 result;

	UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
	     (unsigned long long)goal, count);

	usb1 = ubh_get_usb_first (uspi);
	ucg = ubh_get_ucg(UCPI_UBH(ucpi));

	if (goal)
		start = ufs_dtogd(goal) >> 3;
		start = ufs_dtogd(uspi, goal) >> 3;
	else
		start = ucpi->c_frotor >> 3;
		
@@ -790,7 +826,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
				  " length %u, count %u, freeoff %u\n",
				  ucpi->c_cgx, start, length, count,
				  ucpi->c_freeoff);
			return (unsigned)-1;
			return INVBLOCK;
		}
		start = 0;
	}
@@ -808,7 +844,8 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
		want = want_arr[count];
		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
			if ((blockmap & mask) == want) {
				UFSD("EXIT, result %u\n", result);
				UFSD("EXIT, result %llu\n",
				     (unsigned long long)result);
				return result + pos;
 			}
			mask <<= 1;
@@ -819,7 +856,7 @@ static unsigned ufs_bitmap_search(struct super_block *sb,
	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
		  ucpi->c_cgx);
	UFSD("EXIT (FAILED)\n");
	return (unsigned)-1;
	return INVBLOCK;
}

static void ufs_clusteracct(struct super_block * sb,
+48 −34
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ static u64 ufs_frag_map(struct inode *inode, sector_t frag)
 * @locked_page - for ufs_new_fragments()
 */
static struct buffer_head *
ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
ufs_inode_getfrag(struct inode *inode, u64 fragment,
		  sector_t new_fragment, unsigned int required, int *err,
		  long *phys, int *new, struct page *locked_page)
{
@@ -178,12 +178,12 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	struct buffer_head * result;
	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
	unsigned tmp, goal;
	__fs32 * p, * p2;
	unsigned blockoff, lastblockoff;
	u64 tmp, goal, lastfrag, block, lastblock;
	void *p, *p2;

	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
	     "metadata %d\n", inode->i_ino, fragment,
	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
	     "metadata %d\n", inode->i_ino, (unsigned long long)fragment,
	     (unsigned long long)new_fragment, required, !phys);

        /* TODO : to be done for write support
@@ -193,17 +193,20 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,

	block = ufs_fragstoblks (fragment);
	blockoff = ufs_fragnum (fragment);
	p = ufsi->i_u1.i_data + block;
	p = ufs_get_direct_data_ptr(uspi, ufsi, block);

	goal = 0;

repeat:
	tmp = fs32_to_cpu(sb, *p);
	tmp = ufs_data_ptr_to_cpu(sb, p);

	lastfrag = ufsi->i_lastfrag;
	if (tmp && fragment < lastfrag) {
		if (!phys) {
			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
			if (tmp == fs32_to_cpu(sb, *p)) {
				UFSD("EXIT, result %u\n", tmp + blockoff);
			if (tmp == ufs_data_ptr_to_cpu(sb, p)) {
				UFSD("EXIT, result %llu\n",
				     (unsigned long long)tmp + blockoff);
				return result;
			}
			brelse (result);
@@ -224,9 +227,10 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
		 * We must reallocate last allocated block
		 */
		if (lastblockoff) {
			p2 = ufsi->i_u1.i_data + lastblock;
			p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
			tmp = ufs_new_fragments(inode, p2, lastfrag,
						 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
						ufs_data_ptr_to_cpu(sb, p2),
						uspi->s_fpb - lastblockoff,
						err, locked_page);
			if (!tmp) {
				if (lastfrag != ufsi->i_lastfrag)
@@ -237,27 +241,31 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
			lastfrag = ufsi->i_lastfrag;
			
		}
		tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]);
		tmp = ufs_data_ptr_to_cpu(sb,
					 ufs_get_direct_data_ptr(uspi, ufsi,
								 lastblock));
		if (tmp)
			goal = tmp + uspi->s_fpb;
		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
					 goal, required + blockoff,
					 err,
					 phys != NULL ? locked_page : NULL);
	}
	} else if (lastblock == block) {
	/*
	 * We will extend last allocated block
	 */
	else if (lastblock == block) {
		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
		tmp = ufs_new_fragments(inode, p, fragment -
					(blockoff - lastblockoff),
					ufs_data_ptr_to_cpu(sb, p),
					required +  (blockoff - lastblockoff),
					err, phys != NULL ? locked_page : NULL);
	} else /* (lastblock > block) */ {
	/*
	 * We will allocate new block before last allocated block
	 */
		if (block) {
			tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]);
			tmp = ufs_data_ptr_to_cpu(sb,
						 ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
			if (tmp)
				goal = tmp + uspi->s_fpb;
		}
@@ -266,7 +274,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
					phys != NULL ? locked_page : NULL);
	}
	if (!tmp) {
		if ((!blockoff && *p) || 
		if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) ||
		    (blockoff && lastfrag != ufsi->i_lastfrag))
			goto repeat;
		*err = -ENOSPC;
@@ -286,7 +294,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
	if (IS_SYNC(inode))
		ufs_sync_inode (inode);
	mark_inode_dirty(inode);
	UFSD("EXIT, result %u\n", tmp + blockoff);
	UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff);
	return result;

     /* This part : To be implemented ....
@@ -320,20 +328,22 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
 */
static struct buffer_head *
ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
		  unsigned int fragment, sector_t new_fragment, int *err,
		  u64 fragment, sector_t new_fragment, int *err,
		  long *phys, int *new, struct page *locked_page)
{
	struct super_block *sb = inode->i_sb;
	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
	struct buffer_head * result;
	unsigned tmp, goal, block, blockoff;
	__fs32 * p;
	unsigned blockoff;
	u64 tmp, goal, block;
	void *p;

	block = ufs_fragstoblks (fragment);
	blockoff = ufs_fragnum (fragment);

	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
	     inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n",
	     inode->i_ino, (unsigned long long)fragment,
	     (unsigned long long)new_fragment, !phys);

	result = NULL;
	if (!bh)
@@ -344,14 +354,16 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
		if (!buffer_uptodate(bh))
			goto out;
	}

	if (uspi->fs_magic == UFS2_MAGIC)
		p = (__fs64 *)bh->b_data + block;
	else
		p = (__fs32 *)bh->b_data + block;
repeat:
	tmp = fs32_to_cpu(sb, *p);
	tmp = ufs_data_ptr_to_cpu(sb, p);
	if (tmp) {
		if (!phys) {
			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
			if (tmp == fs32_to_cpu(sb, *p))
			if (tmp == ufs_data_ptr_to_cpu(sb, p))
				goto out;
			brelse (result);
			goto repeat;
@@ -361,14 +373,16 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
		}
	}

	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1])))
	if (block && (uspi->fs_magic == UFS2_MAGIC ?
		      (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) :
		      (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1]))))
		goal = tmp + uspi->s_fpb;
	else
		goal = bh->b_blocknr + uspi->s_fpb;
	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
				uspi->s_fpb, err, locked_page);
	if (!tmp) {
		if (fs32_to_cpu(sb, *p))
		if (ufs_data_ptr_to_cpu(sb, p))
			goto repeat;
		goto out;
	}		
@@ -386,7 +400,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
		sync_dirty_buffer(bh);
	inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);
	UFSD("result %u\n", tmp + blockoff);
	UFSD("result %llu\n", (unsigned long long)tmp + blockoff);
out:
	brelse (bh);
	UFSD("EXIT\n");
+75 −64

File changed.

Preview size limit exceeded, changes collapsed.

+57 −0
Original line number Diff line number Diff line
@@ -305,8 +305,22 @@ static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
	(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
	((begin) & ((uspi->s_fsize>>2) - 1)))

#define ubh_get_addr64(ubh,begin) \
	(((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \
	((begin) & ((uspi->s_fsize>>3) - 1)))

#define ubh_get_addr ubh_get_addr8

static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
				     struct ufs_buffer_head *ubh,
				     u64 blk)
{
	if (uspi->fs_magic == UFS2_MAGIC)
		return ubh_get_addr64(ubh, blk);
	else
		return ubh_get_addr32(ubh, blk);
}

#define ubh_blkmap(ubh,begin,bit) \
	((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))

@@ -507,3 +521,46 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
	if (fragsize > 0 && fragsize < uspi->s_fpb)
		fs32_add(sb, &fraglist[fragsize], cnt);
}

static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi,
					    struct ufs_inode_info *ufsi,
					    unsigned blk)
{
	BUG_ON(blk > UFS_TIND_BLOCK);
	return uspi->fs_magic == UFS2_MAGIC ?
		(void *)&ufsi->i_u1.u2_i_data[blk] :
		(void *)&ufsi->i_u1.i_data[blk];
}

static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p)
{
	return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ?
		fs64_to_cpu(sb, *(__fs64 *)p) :
		fs32_to_cpu(sb, *(__fs32 *)p);
}

static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val)
{
	if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC)
		*(__fs64 *)p = cpu_to_fs64(sb, val);
	else
		*(__fs32 *)p = cpu_to_fs32(sb, val);
}

static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi,
				      void *p)
{
	if (uspi->fs_magic == UFS2_MAGIC)
		*(__fs64 *)p = 0;
	else
		*(__fs32 *)p = 0;
}

static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi,
				       void *p)
{
	if (uspi->fs_magic == UFS2_MAGIC)
		return *(__fs64 *)p == 0;
	else
		return *(__fs32 *)p == 0;
}
+22 −11
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ typedef __u64 __fs64;
typedef __u32 __fs32;
typedef __u16 __fs16;
#else
#include <asm/div64.h>
typedef __u64 __bitwise __fs64;
typedef __u32 __bitwise __fs32;
typedef __u16 __bitwise __fs16;
@@ -266,13 +267,6 @@ typedef __u16 __bitwise __fs16;
#define	ufs_inotofsba(x)	(((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf)
#define	ufs_inotofsbo(x)	((x) % uspi->s_inopf)

/*
 * Give cylinder group number for a file system block.
 * Give cylinder group block number for a file system block.
 */
#define	ufs_dtog(d)	((d) / uspi->s_fpg)
#define	ufs_dtogd(d)	((d) % uspi->s_fpg)

/*
 * Compute the cylinder and rotational position of a cyl block addr.
 */
@@ -723,6 +717,7 @@ struct ufs_cg_private_info {
	__u32	c_nclusterblks;	/* number of clusters this cg */
};	


struct ufs_sb_private_info {
	struct ufs_buffer_head s_ubh; /* buffer containing super block */
	struct ufs_csum_core cs_total;
@@ -952,9 +947,9 @@ struct ufs_super_block_third {
#ifdef __KERNEL__

/* balloc.c */
extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
extern unsigned ufs_new_fragments(struct inode *, __fs32 *, unsigned, unsigned,
extern void ufs_free_fragments (struct inode *, u64, unsigned);
extern void ufs_free_blocks (struct inode *, u64, unsigned);
extern u64 ufs_new_fragments(struct inode *, void *, u64, u64,
			     unsigned, int *, struct page *);

/* cylinder.c */
@@ -1016,6 +1011,22 @@ static inline struct ufs_inode_info *UFS_I(struct inode *inode)
	return container_of(inode, struct ufs_inode_info, vfs_inode);
}

/*
 * Give cylinder group number for a file system block.
 * Give cylinder group block number for a file system block.
 */
/* #define	ufs_dtog(d)	((d) / uspi->s_fpg) */
static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b)
{
	do_div(b, uspi->s_fpg);
	return b;
}
/* #define	ufs_dtogd(d)	((d) % uspi->s_fpg) */
static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
{
	return do_div(b, uspi->s_fpg);
}

#endif	/* __KERNEL__ */

#endif /* __LINUX_UFS_FS_H */
Loading