ufs2 write: block allocation update
RFC PATCH 3/3 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 Evgeniy Dushistov <[email protected]>
---
fs/ufs/balloc.c +117 -80
@@ -4,6 +4,8 @@* Copyright (C) 1998 * Daniel Pirkl <[email protected]> * Charles University, Faculty of Mathematics and Physics +* +* UFS2 write support Evgeniy Dushistov <[email protected]>, 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,9 +107,13 @@ void ufs_free_fragments(struct inode *infs32_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 ); -fs32_add (sb, &ubh_cg_blktot (ucpi, cylno),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));
@@ -127,24 +137,27 @@ failed:/* * 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 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,9 +200,14 @@ do_more: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 ); -fs32_add (sb, &ubh_cg_blktot (ucpi, cylno),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));
@@ -308,15 +326,19 @@ static void ufs_clear_frags(struct inode } } -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 *err = -ENOSPC ;lock_super (sb); - - tmp =fs32_to_cpu (sb, *p); + tmp =ufs_data_ptr_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); +ufs_warning (sb,"ufs_new_fragments" ,"internal warning" +" fragment %llu, count %u" , + (unsigned long long )fragment, count); count = uspi->s_fpb -ufs_fragnum (fragment); } oldcount =ufs_fragnum (fragment);
@@ -339,10 +362,12 @@ unsigned ufs_new_fragments(struct inode*/ if (oldcount) {if (!tmp) { -ufs_error (sb,"ufs_new_fragments" ,"internal error, " -"fragment %u, tmp %u\n" , fragment, tmp); -unlock_super (sb); -return (unsigned )-1 ; +ufs_error (sb,"ufs_new_fragments" ,"internal error, " +"fragment %llu, tmp %llu\n" , + (unsigned long long )fragment, + (unsigned long long )tmp); +unlock_super (sb); +return INVBLOCK ; }if (fragment <UFS_I (inode)->i_lastfrag) {UFSD ("EXIT (ALREADY ALLOCATED)\n" );
@@ -372,7 +397,7 @@ unsigned ufs_new_fragments(struct inodeif (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 inodeif (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 inodeufs_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 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,9 +476,8 @@ unsigned ufs_new_fragments(struct inodereturn 0 ; } -static unsigned -ufs_add_fragments (struct inode * inode,unsigned fragment, -unsigned oldcount,unsigned newcount,int * err) +static u64 ufs_add_fragments (struct inode *inode,u64 fragment, +unsigned oldcount,unsigned newcount,int *err) {struct super_block * sb;struct ufs_sb_private_info * uspi;
@@ -461,14 +486,15 @@ ufs_add_fragments (struct inode * inode,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,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, } 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,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 @@ cg_found: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 @@ cg_found: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 @@ cg_found: } 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 @@ succed: 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 (struc 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 (struc 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 @@ gotit: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 ); -fs32_sub (sb, &ubh_cg_blktot (ucpi, cylno),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_* @goal: near which block we want find new one * @count: specified size */ -static unsigned ufs_bitmap_search (struct super_block *sb, -struct ufs_cg_private_info *ucpi, -unsigned goal,unsigned count) +static u64 ufs_bitmap_search (struct super_block *sb, +struct ufs_cg_private_info *ucpi, +u64 goal,unsigned count) {/* * Bit patterns for identifying fragments in the block map
@@ -761,16 +795,18 @@ static unsigned ufs_bitmap_search(structstruct 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" 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 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(structufs_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,
fs/ufs/inode.c +48 -34
190 lines not on this page · raw message
fs/ufs/truncate.c +75 -64
312 lines not on this page · raw message
include/linux/ufs_fs.h +22 -11
@@ -34,6 +34,7 @@#include <linux/kernel.h> #include <linux/stat.h> #include <linux/fs.h> +#include <asm/div64.h> #ifndef __KERNEL__typedef __u64 __fs64 ;
@@ -265,13 +266,6 @@ typedef __u16 __bitwise __fs16;#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. */ #define ufs_cbtocylno (bno) \
@@ -721,6 +715,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;
@@ -949,10 +944,10 @@ 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 , -unsigned ,int *,struct page *); +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 */ extern struct ufs_cg_private_info *ufs_load_cylinder (struct super_block *,unsigned );
@@ -1013,6 +1008,22 @@ static inline struct ufs_inode_info *UFS 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 */
include/linux/ufs_fs_i.h +1 -1
@@ -25,7 +25,7 @@ struct ufs_inode_info {__u32 i_unused2;__u32 i_oeftflag;__u16 i_osync; -__u32 i_lastfrag; +__u64 i_lastfrag;__u32 i_dir_start_lookup;struct inode vfs_inode; };
fs/ufs/util.h +57 -0
68 lines not on this page · raw message
Signature · 1 line
/Evgeniy