From 78c388aed2b7184182c08428db1de6c872d815f5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 4 Jan 1999 16:03:48 +0000 Subject: Merge with Linux 2.1.131 and more MIPS goodies. (Did I mention that CVS is buggy ...) --- fs/ufs/balloc.c | 118 ++++--- fs/ufs/cylinder.c | 11 +- fs/ufs/dir.c | 22 +- fs/ufs/ialloc.c | 23 +- fs/ufs/inode.c | 84 +++-- fs/ufs/namei.c | 51 +-- fs/ufs/super.c | 939 ++++++++++++++++++++++++++++++++---------------------- fs/ufs/symlink.c | 4 +- fs/ufs/util.c | 14 +- fs/ufs/util.h | 263 +++++++++++---- 10 files changed, 930 insertions(+), 599 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 6567c515b..ed71ec179 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -20,7 +20,6 @@ #include "util.h" #undef UFS_BALLOC_DEBUG -#undef UFS_BALLOC_DEBUG_MORE #ifdef UFS_BALLOC_DEBUG #define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x; @@ -28,27 +27,12 @@ #define UFSD(x) #endif -#ifdef UFS_BALLOC_DEBUG_MORE -#define UFSDM \ -ufs_print_cylinder_stuff (ucg, swab); \ -printk("inode: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nifree), \ -SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \ -printk("block: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree), \ -SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree), SWAB32(ucg->cg_cs.cs_nbfree)); \ -printk("fragment: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nffree), \ -SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nffree), SWAB32(ucg->cg_cs.cs_nffree)); \ -printk("ndir: total %u, fs %u, cg %u\n\n", SWAB32(usb1->fs_cstotal.cs_ndir), \ -SWAB32(sb->fs_cs(ucpi->c_cgx).cs_ndir), SWAB32(ucg->cg_cs.cs_ndir)); -#else -#define UFSDM -#endif - - unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *); unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *); unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *); unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned); static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; +void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); /* * Free 'count' fragments from fragment number 'fragment' @@ -90,8 +74,6 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count goto failed; } - UFSDM - end_bit = bit + count; bbase = ufs_blknum (bit); blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase); @@ -118,6 +100,8 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count SUB_SWAB32(ucg->cg_cs.cs_nffree, uspi->s_fpb); SUB_SWAB32(usb1->fs_cstotal.cs_nffree, uspi->s_fpb); SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, uspi->s_fpb); + if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD) + ufs_clusteracct (sb, ucpi, blkno, 1); INC_SWAB32(ucg->cg_cs.cs_nbfree); INC_SWAB32(usb1->fs_cstotal.cs_nbfree); INC_SWAB32(sb->fs_cs(cgno).cs_nbfree); @@ -126,8 +110,6 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count INC_SWAB32(ubh_cg_blktot (ucpi, cylno)); } - UFSDM - ubh_mark_buffer_dirty (USPI_UBH, 1); ubh_mark_buffer_dirty (UCPI_UBH, 1); if (sb->s_flags & MS_SYNCHRONOUS) { @@ -166,7 +148,8 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) { UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { - ufs_error (sb, "ufs_free_blocks", "internal error"); + ufs_error (sb, "ufs_free_blocks", "internal error, " + "fragment %u, count %u\n", fragment, count); goto failed; } @@ -196,14 +179,14 @@ do_more: goto failed; } - UFSDM - for (i = bit; i < end_bit; i += uspi->s_fpb) { blkno = ufs_fragstoblks(i); if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) { ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); } ubh_setblock(UCPI_UBH, ucpi->c_freeoff, blkno); + if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD) + ufs_clusteracct (sb, ucpi, blkno, 1); DQUOT_FREE_BLOCK(sb, inode, uspi->s_fpb); INC_SWAB32(ucg->cg_cs.cs_nbfree); INC_SWAB32(usb1->fs_cstotal.cs_nbfree); @@ -213,8 +196,6 @@ do_more: INC_SWAB32(ubh_cg_blktot(ucpi, cylno)); } - UFSDM - ubh_mark_buffer_dirty (USPI_UBH, 1); ubh_mark_buffer_dirty (UCPI_UBH, 1); if (sb->s_flags & MS_SYNCHRONOUS) { @@ -294,7 +275,6 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, } if (fragment < inode->u.ufs_i.i_lastfrag) { UFSD(("EXIT (ALREADY ALLOCATED)\n")) - printk("hlaska 2\n"); unlock_super (sb); return 0; } @@ -302,7 +282,6 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, else { if (tmp) { UFSD(("EXIT (ALREADY ALLOCATED)\n")) - printk("hlaska 3, fragment %u, tmp %u, oldcount %u\n", fragment, tmp, oldcount); unlock_super(sb); return 0; } @@ -442,8 +421,6 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment, return 0; } - UFSDM - fragno = ufs_dtogd (fragment); fragoff = ufs_fragnum (fragno); for (i = oldcount; i < newcount; i++) @@ -472,9 +449,6 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment, SUB_SWAB32(ucg->cg_cs.cs_nffree, count); SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, count); SUB_SWAB32(usb1->fs_cstotal.cs_nffree, count); - usb1->fs_fmod = SWAB32(1); - - UFSDM ubh_mark_buffer_dirty (USPI_UBH, 1); ubh_mark_buffer_dirty (UCPI_UBH, 1); @@ -556,8 +530,6 @@ cg_found: "internal error, bad magic number on cg %u", cgno); ucg->cg_time = SWAB32(CURRENT_TIME); - UFSDM - if (count == uspi->s_fpb) { result = ufs_alloccg_block (inode, ucpi, goal, err); if (result == (unsigned)-1) @@ -602,10 +574,6 @@ cg_found: INC_SWAB32(ucg->cg_frsum[allocsize - count]); succed: - usb1->fs_fmod = SWAB32(1); - - UFSDM - ubh_mark_buffer_dirty (USPI_UBH, 1); ubh_mark_buffer_dirty (UCPI_UBH, 1); if (sb->s_flags & MS_SYNCHRONOUS) { @@ -652,8 +620,6 @@ unsigned ufs_alloccg_block (struct inode * inode, goto gotit; } - /*** This function should be optimized later ***/ - norot: result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); if (result == (unsigned)-1) @@ -661,7 +627,9 @@ norot: ucpi->c_rotor = result; gotit: blkno = ufs_fragstoblks(result); - ubh_clrblock(UCPI_UBH, ucpi->c_freeoff, blkno); + ubh_clrblock (UCPI_UBH, ucpi->c_freeoff, blkno); + if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD) + ufs_clusteracct (sb, ucpi, blkno, -1); if(DQUOT_ALLOC_BLOCK(sb, inode, uspi->s_fpb)) { *err = -EDQUOT; return (unsigned)-1; @@ -672,7 +640,6 @@ gotit: cylno = ufs_cbtocylno(result); DEC_SWAB16(ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result))); DEC_SWAB32(ubh_cg_blktot(ucpi, cylno)); - usb1->fs_fmod = 1; UFSD(("EXIT, result %u\n", result)) @@ -685,7 +652,7 @@ unsigned ufs_bitmap_search (struct super_block * sb, struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_cylinder_group * ucg; - unsigned start, length, length2, location, result; + unsigned start, length, location, result; unsigned possition, fragsize, blockmap, mask; unsigned swab; @@ -706,8 +673,8 @@ unsigned ufs_bitmap_search (struct super_block * sb, (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, 1 << (count - 1 + (uspi->s_fpb & 7))); if (location == 0) { - length2 = start + 1; - location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff, length2, + length = start + 1; + location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff, length, (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, 1 << (count - 1 + (uspi->s_fpb & 7))); if (location == 0) { @@ -717,7 +684,6 @@ unsigned ufs_bitmap_search (struct super_block * sb, return (unsigned)-1; } start = 0; - length = length2; } result = (start + length - location) << 3; ucpi->c_frotor = result; @@ -753,6 +719,64 @@ unsigned ufs_bitmap_search (struct super_block * sb, return (unsigned)-1; } +void ufs_clusteracct(struct super_block * sb, + struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt) +{ + struct ufs_sb_private_info * uspi; + int i, start, end, forw, back; + unsigned swab; + + + uspi = sb->u.ufs_sb.s_uspi; + swab = sb->u.ufs_sb.s_swab; + + if (uspi->s_contigsumsize <= 0) + return; + + if (cnt > 0) + ubh_setbit(UCPI_UBH, ucpi->c_clusteroff, blkno); + else + ubh_clrbit(UCPI_UBH, ucpi->c_clusteroff, blkno); + + /* + * Find the size of the cluster going forward. + */ + start = blkno + 1; + end = start + uspi->s_contigsumsize; + if ( end >= ucpi->c_nclusterblks) + end = ucpi->c_nclusterblks; + i = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_clusteroff, end, start); + if (i > end) + i = end; + forw = i - start; + + /* + * Find the size of the cluster going backward. + */ + start = blkno - 1; + end = start - uspi->s_contigsumsize; + if (end < 0 ) + end = -1; + i = ubh_find_last_zero_bit (UCPI_UBH, ucpi->c_clusteroff, start, end); + if ( i < end) + i = end; + back = start - i; + + /* + * Account for old cluster and the possibly new forward and + * back clusters. + */ + i = back + forw + 1; + if (i > uspi->s_contigsumsize) + i = uspi->s_contigsumsize; + ADD_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2))), cnt); + if (back > 0) + SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2))), cnt); + if (forw > 0) + SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2))), cnt); +} + + static unsigned char ufs_fragtable_8fpb[] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c index a822438b6..295332d17 100644 --- a/fs/ufs/cylinder.c +++ b/fs/ufs/cylinder.c @@ -22,7 +22,6 @@ #include "util.h" #undef UFS_CYLINDER_DEBUG -#undef UFS_CYLINDER_DEBUG_MORE #ifdef UFS_CYLINDER_DEBUG #define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x; @@ -50,10 +49,6 @@ static void ufs_read_cylinder (struct super_block * sb, ucpi = sb->u.ufs_sb.s_ucpi[bitmap_nr]; ucg = (struct ufs_cylinder_group *)sb->u.ufs_sb.s_ucg[cgno]->b_data; -#ifdef UFS_CYLINDER_DEBUG_MORE - ufs_print_cylinder_stuff (ucg, swab); -#endif - UCPI_UBH->fragment = ufs_cgcmin(cgno); UCPI_UBH->count = uspi->s_cgsize >> sb->s_blocksize_bits; /* @@ -77,7 +72,9 @@ static void ufs_read_cylinder (struct super_block * sb, ucpi->c_iusedoff = SWAB32(ucg->cg_iusedoff); ucpi->c_freeoff = SWAB32(ucg->cg_freeoff); ucpi->c_nextfreeoff = SWAB32(ucg->cg_nextfreeoff); - + ucpi->c_clustersumoff = SWAB32(ucg->cg_u.cg_44.cg_clustersumoff); + ucpi->c_clusteroff = SWAB32(ucg->cg_u.cg_44.cg_clusteroff); + ucpi->c_nclusterblks = SWAB32(ucg->cg_u.cg_44.cg_nclusterblks); UFSD(("EXIT\n")) return; @@ -201,10 +198,12 @@ struct ufs_cg_private_info * ufs_load_cylinder ( sb->u.ufs_sb.s_cg_loaded++; else ufs_put_cylinder (sb, UFS_MAX_GROUP_LOADED-1); + ucpi = sb->u.ufs_sb.s_ucpi[sb->u.ufs_sb.s_cg_loaded - 1]; for (j = sb->u.ufs_sb.s_cg_loaded - 1; j > 0; j--) { sb->u.ufs_sb.s_cgno[j] = sb->u.ufs_sb.s_cgno[j-1]; sb->u.ufs_sb.s_ucpi[j] = sb->u.ufs_sb.s_ucpi[j-1]; } + sb->u.ufs_sb.s_ucpi[0] = ucpi; ufs_read_cylinder (sb, cgno, 0); } UFSD(("EXIT\n")) diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 470847dca..6fc224512 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -11,8 +11,6 @@ * 4.4BSD (FreeBSD) support added on February 1st 1998 by * Niels Kristian Bech Jensen partially based * on code by Martin von Loewis . - * - * write support by Daniel Pirkl 1998 */ #include @@ -104,11 +102,11 @@ revalidate: && offset < sb->s_blocksize) { de = (struct ufs_dir_entry *) (bh->b_data + offset); /* XXX - put in a real ufs_check_dir_entry() */ - if ((de->d_reclen == 0) || (ufs_namlen(de) == 0)) { + if ((de->d_reclen == 0) || (ufs_get_de_namlen(de) == 0)) { /* SWAB16() was unneeded -- compare to 0 */ filp->f_pos = (filp->f_pos & - (sb->s_blocksize - 1)) + - sb->s_blocksize; + (sb->s_blocksize - 1)) + + sb->s_blocksize; brelse(bh); return stored; } @@ -119,7 +117,7 @@ revalidate: /* On error, skip the f_pos to the next block. */ filp->f_pos = (filp->f_pos & - (sb->s_blocksize - 1)) + + (sb->s_blocksize - 1)) + sb->s_blocksize; brelse (bh); return stored; @@ -137,8 +135,8 @@ revalidate: unsigned long version = inode->i_version; UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino))) - UFSD(("namlen %u\n", ufs_namlen(de))) - error = filldir(dirent, de->d_name, ufs_namlen(de), + UFSD(("namlen %u\n", ufs_get_de_namlen(de))) + error = filldir(dirent, de->d_name, ufs_get_de_namlen(de), filp->f_pos, SWAB32(de->d_ino)); if (error) break; @@ -172,7 +170,7 @@ int ufs_check_dir_entry (const char * function, struct inode * dir, error_msg = "reclen is smaller than minimal"; else if (SWAB16(de->d_reclen) % 4 != 0) error_msg = "reclen % 4 != 0"; - else if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(ufs_namlen(de))) + else if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(ufs_get_de_namlen(de))) error_msg = "reclen is too small for namlen"; else if (dir && ((char *) de - bh->b_data) + SWAB16(de->d_reclen) > dir->i_sb->s_blocksize) @@ -185,7 +183,7 @@ int ufs_check_dir_entry (const char * function, struct inode * dir, "offset=%lu, inode=%lu, reclen=%d, namlen=%d", dir->i_ino, dir->i_size, error_msg, offset, (unsigned long) SWAB32(de->d_ino), - SWAB16(de->d_reclen), ufs_namlen(de)); + SWAB16(de->d_reclen), ufs_get_de_namlen(de)); return (error_msg == NULL ? 1 : 0); } @@ -222,8 +220,8 @@ struct inode_operations ufs_dir_inode_operations = { NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ - ufs_bmap, /* bmap */ - ufs_truncate, /* truncate */ + NULL, /* bmap */ + NULL, /* truncate */ ufs_permission, /* permission */ NULL, /* smap */ }; diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 6da43f20a..c592009bc 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -34,7 +34,6 @@ #include "util.h" #undef UFS_IALLOC_DEBUG -#undef UFS_IALLOC_DEBUG_MORE #ifdef UFS_IALLOC_DEBUG #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x; @@ -42,18 +41,6 @@ #define UFSD(x) #endif -#ifdef UFS_IALLOC_DEBUG_MORE -#define UFSDM \ -ufs_print_cylinder_stuff (ucg, swab); \ -printk("inode: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nifree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \ -printk("block: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree), SWAB32(ucg->cg_cs.cs_nbfree)); \ -printk("fragment: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nffree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nffree), SWAB32(ucg->cg_cs.cs_nffree)); \ -printk("ndir: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_ndir), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_ndir), SWAB32(ucg->cg_cs.cs_ndir)); -#else -#define UFSDM -#endif - - /* * NOTE! When we get the inode, we're the only people * that have access to it, and as such there are no @@ -120,8 +107,6 @@ void ufs_free_inode (struct inode * inode) if (!ufs_cg_chkmagic(ucg)) ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number"); - UFSDM - ucg->cg_time = SWAB32(CURRENT_TIME); is_directory = S_ISDIR(inode->i_mode); @@ -153,8 +138,6 @@ void ufs_free_inode (struct inode * inode) ubh_wait_on_buffer (UCPI_UBH); } - UFSDM - sb->s_dirt = 1; unlock_super (sb); UFSD(("EXIT\n")) @@ -199,7 +182,7 @@ struct inode * ufs_new_inode (const struct inode * dir, int mode, int * err ) usb1 = ubh_get_usb_first(USPI_UBH); inode->i_sb = sb; - inode->i_flags = sb->s_flags; + inode->i_flags = 0; lock_super (sb); @@ -251,8 +234,6 @@ cg_found: if (!ufs_cg_chkmagic(ucg)) ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); - UFSDM - start = ucpi->c_irotor; bit = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_iusedoff, uspi->s_ipg, start); if (!(bit < uspi->s_ipg)) { @@ -316,8 +297,6 @@ cg_found: insert_inode_hash(inode); mark_inode_dirty(inode); - UFSDM - unlock_super (sb); if(DQUOT_ALLOC_INODE(sb, inode)) { diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index afea7180a..699d4d2c9 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -53,10 +53,11 @@ static void ufs_print_inode(struct inode * inode) { unsigned swab = inode->i_sb->u.ufs_sb.s_swab; - printk("ino %lu mode 0%6.6o nlink %d uid %d gid %d" - " size %lu blocks %lu\n", + printk("ino %lu mode 0%6.6o nlink %d uid %d uid32 %u" + " gid %d gid32 %u size %lu blocks %lu\n", inode->i_ino, inode->i_mode, inode->i_nlink, - inode->i_uid,inode->i_gid, inode->i_size, inode->i_blocks); + inode->i_uid, inode->u.ufs_i.i_uid, inode->i_gid, + inode->u.ufs_i.i_gid, inode->i_size, inode->i_blocks); printk(" db <%u %u %u %u %u %u %u %u %u %u %u %u>\n", SWAB32(inode->u.ufs_i.i_u1.i_data[0]), SWAB32(inode->u.ufs_i.i_u1.i_data[1]), @@ -117,7 +118,7 @@ int ufs_bmap (struct inode * inode, int fragment) * direct fragment */ if (fragment < UFS_NDIR_FRAGMENT) - return ufs_inode_bmap (inode, fragment); + return (uspi->s_sbbase + ufs_inode_bmap (inode, fragment)); /* * indirect fragment @@ -128,8 +129,9 @@ int ufs_bmap (struct inode * inode, int fragment) UFS_IND_FRAGMENT + (fragment >> uspi->s_apbshift)); if (!tmp) return 0; - return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), - fragment & uspi->s_apbmask, uspi, swab); + return (uspi->s_sbbase + + ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), + fragment & uspi->s_apbmask, uspi, swab)); } /* @@ -141,12 +143,13 @@ int ufs_bmap (struct inode * inode, int fragment) UFS_DIND_FRAGMENT + (fragment >> uspi->s_2apbshift)); if (!tmp) return 0; - tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), + tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab); if (!tmp) return 0; - return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), - fragment & uspi->s_apbmask, uspi, swab); + return (uspi->s_sbbase + + ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), + fragment & uspi->s_apbmask, uspi, swab)); } /* @@ -157,16 +160,17 @@ int ufs_bmap (struct inode * inode, int fragment) UFS_TIND_FRAGMENT + (fragment >> uspi->s_3apbshift)); if (!tmp) return 0; - tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), + tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), (fragment >> uspi->s_2apbshift) & uspi->s_apbmask, uspi, swab); if (!tmp) return 0; - tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), + tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab); if (!tmp) return 0; - return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), - fragment & uspi->s_apbmask, uspi, swab); + return (uspi->s_sbbase + + ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize), + fragment & uspi->s_apbmask, uspi, swab)); } static struct buffer_head * ufs_inode_getfrag (struct inode * inode, @@ -197,7 +201,7 @@ repeat: tmp = SWAB32(*p); lastfrag = inode->u.ufs_i.i_lastfrag; if (tmp && fragment < lastfrag) { - result = getblk (sb->s_dev, tmp + blockoff, sb->s_blocksize); + result = getblk (sb->s_dev, uspi->s_sbbase + tmp + blockoff, sb->s_blocksize); if (tmp == SWAB32(*p)) { UFSD(("EXIT, result %u\n", tmp + blockoff)) return result; @@ -308,7 +312,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode * inode, repeat: tmp = SWAB32(*p); if (tmp) { - result = getblk (bh->b_dev, tmp + blockoff, sb->s_blocksize); + result = getblk (bh->b_dev, uspi->s_sbbase + tmp + blockoff, sb->s_blocksize); if (tmp == SWAB32(*p)) { brelse (bh); UFSD(("EXIT, result %u\n", tmp + blockoff)) @@ -329,7 +333,6 @@ repeat: tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err); if (!tmp) { if (SWAB32(*p)) { - printk("REPEAT\n"); goto repeat; } else { @@ -464,7 +467,7 @@ void ufs_read_inode (struct inode * inode) return; } - bh = bread (sb->s_dev, ufs_inotofsba(inode->i_ino), sb->s_blocksize); + bh = bread (sb->s_dev, uspi->s_sbbase + ufs_inotofsba(inode->i_ino), sb->s_blocksize); if (!bh) { ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); return; @@ -483,11 +486,12 @@ void ufs_read_inode (struct inode * inode) * Linux has only 16-bit uid and gid, so we can't support EFT. * Files are dynamically chown()ed to root. */ - inode->i_uid = ufs_uid(ufs_inode); - if (inode->i_uid == UFS_USEEFT) { + inode->i_uid = inode->u.ufs_i.i_uid = ufs_get_inode_uid(ufs_inode); + inode->i_gid = inode->u.ufs_i.i_gid = ufs_get_inode_gid(ufs_inode); + if (inode->u.ufs_i.i_uid >= UFS_USEEFT) { inode->i_uid = 0; } - if (inode->i_gid == UFS_USEEFT) { + if (inode->u.ufs_i.i_gid >= UFS_USEEFT) { inode->i_gid = 0; } @@ -510,8 +514,6 @@ void ufs_read_inode (struct inode * inode) inode->u.ufs_i.i_flags = SWAB32(ufs_inode->ui_flags); inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen); inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow); - inode->u.ufs_i.i_uid = SWAB32(ufs_inode->ui_u3.ui_sun.ui_uid); - inode->u.ufs_i.i_gid = SWAB32(ufs_inode->ui_u3.ui_sun.ui_gid); inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag); inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize); @@ -540,8 +542,6 @@ void ufs_read_inode (struct inode * inode) inode->i_op = &chrdev_inode_operations; else if (S_ISBLK(inode->i_mode)) inode->i_op = &blkdev_inode_operations; - else if (S_ISSOCK(inode->i_mode)) - ; /* nothing */ else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); @@ -558,12 +558,13 @@ static int ufs_update_inode(struct inode * inode, int do_sync) struct buffer_head * bh; struct ufs_inode * ufs_inode; unsigned i; - unsigned swab; + unsigned flags, swab; UFSD(("ENTER, ino %lu\n", inode->i_ino)) sb = inode->i_sb; uspi = sb->u.ufs_sb.s_uspi; + flags = sb->u.ufs_sb.s_flags; swab = sb->u.ufs_sb.s_swab; if (inode->i_ino < UFS_ROOTINO || @@ -582,22 +583,15 @@ static int ufs_update_inode(struct inode * inode, int do_sync) ufs_inode->ui_mode = SWAB16(inode->i_mode); ufs_inode->ui_nlink = SWAB16(inode->i_nlink); - if (inode->i_uid == 0 && inode->u.ufs_i.i_uid >= UFS_USEEFT) { - ufs_inode->ui_u3.ui_sun.ui_uid = SWAB32(inode->u.ufs_i.i_uid); - ufs_inode->ui_u1.oldids.ui_suid = (__u16)ufs_inode->ui_u3.ui_sun.ui_uid; - } - else { - ufs_inode->ui_u1.oldids.ui_suid = SWAB16(inode->i_uid); - ufs_inode->ui_u3.ui_sun.ui_uid = (__u32) ufs_inode->ui_u1.oldids.ui_suid; - } - if (inode->i_gid == 0 && inode->u.ufs_i.i_gid >= UFS_USEEFT) { - ufs_inode->ui_u3.ui_sun.ui_gid = SWAB32(inode->u.ufs_i.i_gid); - ufs_inode->ui_u1.oldids.ui_sgid = (__u16)ufs_inode->ui_u3.ui_sun.ui_gid; - } - else { - ufs_inode->ui_u1.oldids.ui_sgid = SWAB16(inode->i_gid); - ufs_inode->ui_u3.ui_sun.ui_gid = (__u32) ufs_inode->ui_u1.oldids.ui_sgid; - } + if (inode->i_uid == 0 && inode->u.ufs_i.i_uid >= UFS_USEEFT) + ufs_set_inode_uid (ufs_inode, inode->u.ufs_i.i_uid); + else + ufs_set_inode_uid (ufs_inode, inode->i_uid); + + if (inode->i_gid == 0 && inode->u.ufs_i.i_gid >= UFS_USEEFT) + ufs_set_inode_gid (ufs_inode, inode->u.ufs_i.i_gid); + else + ufs_set_inode_gid (ufs_inode, inode->i_gid); ufs_inode->ui_size = SWAB64((u64)inode->i_size); ufs_inode->ui_atime.tv_sec = SWAB32(inode->i_atime); @@ -607,11 +601,13 @@ static int ufs_update_inode(struct inode * inode, int do_sync) ufs_inode->ui_mtime.tv_sec = SWAB32(inode->i_mtime); ufs_inode->ui_mtime.tv_usec = SWAB32(0); ufs_inode->ui_blocks = SWAB32(inode->i_blocks); - ufs_inode->ui_flags = SWAB32(inode->u.ufs_i.i_flags); ufs_inode->ui_gen = SWAB32(inode->u.ufs_i.i_gen); - ufs_inode->ui_u3.ui_sun.ui_shadow = SWAB32(inode->u.ufs_i.i_shadow); - ufs_inode->ui_u3.ui_sun.ui_oeftflag = SWAB32(inode->u.ufs_i.i_oeftflag); + + if ((flags & UFS_UID_MASK) == UFS_UID_EFT) { + ufs_inode->ui_u3.ui_sun.ui_shadow = SWAB32(inode->u.ufs_i.i_shadow); + ufs_inode->ui_u3.ui_sun.ui_oeftflag = SWAB32(inode->u.ufs_i.i_oeftflag); + } if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) ufs_inode->ui_u2.ui_addr.ui_db[0] = SWAB32(kdev_t_to_nr(inode->i_rdev)); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 9542d2770..130d53bb5 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -65,10 +65,10 @@ static int ufs_match (int len, const char * const name, /* * "" means "." ---> so paths like "/usr/lib//libc.a" work */ - if (!len && ufs_namlen(de) == 1 && (de->d_name[0] == '.') && + if (!len && ufs_get_de_namlen(de) == 1 && (de->d_name[0] == '.') && (de->d_name[1] == '\0')) return 1; - if (len != ufs_namlen(de)) + if (len != ufs_get_de_namlen(de)) return 0; return !memcmp(name, de->d_name, len); } @@ -286,7 +286,7 @@ static struct buffer_head * ufs_add_entry (struct inode * dir, de = (struct ufs_dir_entry *) (bh->b_data + fragoff); de->d_ino = SWAB32(0); de->d_reclen = SWAB16(UFS_SECTOR_SIZE); - de->d_u.d_namlen = SWAB16(0); + ufs_set_de_namlen(de,0); dir->i_size = offset + UFS_SECTOR_SIZE; mark_inode_dirty(dir); } else { @@ -304,18 +304,18 @@ static struct buffer_head * ufs_add_entry (struct inode * dir, return NULL; } if ((SWAB32(de->d_ino) == 0 && SWAB16(de->d_reclen) >= rec_len) || - (SWAB16(de->d_reclen) >= UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen)) + rec_len)) { + (SWAB16(de->d_reclen) >= UFS_DIR_REC_LEN(ufs_get_de_namlen(de)) + rec_len)) { offset += SWAB16(de->d_reclen); if (SWAB32(de->d_ino)) { de1 = (struct ufs_dir_entry *) ((char *) de + - UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen))); + UFS_DIR_REC_LEN(ufs_get_de_namlen(de))); de1->d_reclen = SWAB16(SWAB16(de->d_reclen) - - UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen))); - de->d_reclen = SWAB16(UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen))); + UFS_DIR_REC_LEN(ufs_get_de_namlen(de))); + de->d_reclen = SWAB16(UFS_DIR_REC_LEN(ufs_get_de_namlen(de))); de = de1; } de->d_ino = SWAB32(0); - de->d_u.d_namlen = SWAB16(namelen); + ufs_set_de_namlen(de, namelen); memcpy (de->d_name, name, namelen + 1); /* * XXX shouldn't update any times until successful @@ -369,7 +369,7 @@ static int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir, de = (struct ufs_dir_entry *) bh->b_data; UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(de->d_ino), - SWAB16(de->d_reclen), ufs_namlen(de), de->d_name)) + SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name)) while (i < bh->b_size) { if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) @@ -410,11 +410,11 @@ int ufs_create (struct inode * dir, struct dentry * dentry, int mode) struct buffer_head * bh; struct ufs_dir_entry * de; int err = -EIO; - unsigned swab; + unsigned flags, swab; sb = dir->i_sb; swab = sb->u.ufs_sb.s_swab; - + flags = sb->u.ufs_sb.s_flags; /* * N.B. Several error exits in ufs_new_inode don't set err. */ @@ -434,6 +434,7 @@ int ufs_create (struct inode * dir, struct dentry * dentry, int mode) return err; } de->d_ino = SWAB32(inode->i_ino); + ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -455,9 +456,10 @@ int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) struct buffer_head * bh; struct ufs_dir_entry * de; int err = -EIO; - unsigned swab; + unsigned flags, swab; sb = dir->i_sb; + flags = sb->u.ufs_sb.s_flags; swab = sb->u.ufs_sb.s_swab; err = -ENAMETOOLONG; @@ -493,6 +495,7 @@ int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) if (!bh) goto out_no_entry; de->d_ino = SWAB32(inode->i_ino); + ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -519,9 +522,10 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) struct buffer_head * bh, * dir_block; struct ufs_dir_entry * de; int err; - unsigned swab; + unsigned flags, swab; sb = dir->i_sb; + flags = sb->u.ufs_sb.s_flags; swab = sb->u.ufs_sb.s_swab; err = -ENAMETOOLONG; @@ -548,13 +552,15 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE; de = (struct ufs_dir_entry *) dir_block->b_data; de->d_ino = SWAB32(inode->i_ino); - de->d_u.d_namlen = SWAB16(1); + ufs_set_de_type (de, inode->i_mode); + ufs_set_de_namlen(de,1); de->d_reclen = SWAB16(UFS_DIR_REC_LEN(1)); strcpy (de->d_name, "."); de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen)); de->d_ino = SWAB32(dir->i_ino); + ufs_set_de_type (de, dir->i_mode); de->d_reclen = SWAB16(UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1)); - de->d_u.d_namlen = SWAB16(2); + ufs_set_de_namlen(de,2); strcpy (de->d_name, ".."); inode->i_nlink = 2; mark_buffer_dirty(dir_block, 1); @@ -567,6 +573,7 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) if (!bh) goto out_no_entry; de->d_ino = SWAB32(inode->i_ino); + ufs_set_de_type (de, inode->i_mode); dir->i_version = ++event; mark_buffer_dirty(bh, 1); if (IS_SYNC(dir)) { @@ -605,7 +612,7 @@ static int ufs_empty_dir (struct inode * inode) if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) || !(bh = ufs_bread (inode, 0, 0, &err))) { - ufs_warning (inode->i_sb, "empty_dir", + ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no data block", inode->i_ino); return 1; @@ -614,7 +621,7 @@ static int ufs_empty_dir (struct inode * inode) de1 = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen)); if (SWAB32(de->d_ino) != inode->i_ino || !SWAB32(de1->d_ino) || strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) { - ufs_warning (inode->i_sb, "empty_dir", + ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no `.' or `..'", inode->i_ino); return 1; @@ -625,7 +632,7 @@ static int ufs_empty_dir (struct inode * inode) if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err); - if (!bh) { + if (!bh) { ufs_error (sb, "empty_dir", "directory #%lu contains a hole at offset %lu", inode->i_ino, offset); @@ -694,7 +701,6 @@ int ufs_rmdir (struct inode * dir, struct dentry *dentry) if (SWAB32(de->d_ino) != inode->i_ino) goto end_rmdir; - down(&inode->i_sem); /* * Prune any child dentries so that this dentry becomes negative. */ @@ -720,7 +726,6 @@ int ufs_rmdir (struct inode * dir, struct dentry *dentry) retval = ufs_delete_entry (dir, de, bh); dir->i_version = ++event; } - up(&inode->i_sem); if (retval) goto end_rmdir; mark_buffer_dirty(bh, 1); @@ -768,7 +773,7 @@ int ufs_unlink(struct inode * dir, struct dentry *dentry) retval = -ENOENT; bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de); UFSD(("de: ino %u, reclen %u, namelen %u, name %s\n", SWAB32(de->d_ino), - SWAB16(de->d_reclen), ufs_namlen(de), de->d_name)) + SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name)) if (!bh) goto end_unlink; @@ -777,8 +782,6 @@ int ufs_unlink(struct inode * dir, struct dentry *dentry) inode->i_sb->dq_op->initialize (inode, -1); retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) goto end_unlink; if ((dir->i_mode & S_ISVTX) && @@ -984,7 +987,7 @@ static int do_ufs_rename (struct inode * old_dir, struct dentry * old_dentry, UFSD(("name %s, len %u\n", old_dentry->d_name.name, old_dentry->d_name.len)) old_bh = ufs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(old_de->d_ino), - SWAB16(old_de->d_reclen), ufs_namlen(old_de), old_de->d_name)) + SWAB16(old_de->d_reclen), ufs_get_de_namlen(old_de), old_de->d_name)) retval = -ENOENT; if (!old_bh) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index d4426ad5d..dd4815469 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1,4 +1,33 @@ /* + * linux/fs/ufs/super.c + * + * Copyright (C) 1998 + * Daniel Pirkl + * Charles University, Faculty of Mathematics and Physics + */ + +/* Derivated from + * + * linux/fs/ext2/super.c + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/fs/minix/inode.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Big-endian to little-endian byte-swapping/bitmaps by + * David S. Miller (davem@caip.rutgers.edu), 1995 + */ + +/* + * Inspirated by + * * linux/fs/ufs/super.c * * Copyright (C) 1996 @@ -28,20 +57,29 @@ * */ + #include -#include -#include +#include + +#include +#include +#include + +#include #include #include -#include -#include #include +#include +#include +#include +#include +#include +#include #include "swab.h" #include "util.h" - #undef UFS_SUPER_DEBUG #undef UFS_SUPER_DEBUG_MORE @@ -59,39 +97,41 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1, struct ufs_super_block_second * usb2, struct ufs_super_block_third * usb3, unsigned swab) { - printk("\nufs_print_super_stuff\n"); - printk("size of usb: %lu\n", sizeof(struct ufs_super_block)); - printk(" magic: 0x%x\n", SWAB32(usb3->fs_magic)); - printk(" sblkno: %u\n", SWAB32(usb1->fs_sblkno)); - printk(" cblkno: %u\n", SWAB32(usb1->fs_cblkno)); - printk(" iblkno: %u\n", SWAB32(usb1->fs_iblkno)); - printk(" dblkno: %u\n", SWAB32(usb1->fs_dblkno)); - printk(" cgoffset: %u\n", SWAB32(usb1->fs_cgoffset)); - printk(" ~cgmask: 0x%x\n", ~SWAB32(usb1->fs_cgmask)); - printk(" size: %u\n", SWAB32(usb1->fs_size)); - printk(" dsize: %u\n", SWAB32(usb1->fs_dsize)); - printk(" ncg: %u\n", SWAB32(usb1->fs_ncg)); - printk(" bsize: %u\n", SWAB32(usb1->fs_bsize)); - printk(" fsize: %u\n", SWAB32(usb1->fs_fsize)); - printk(" frag: %u\n", SWAB32(usb1->fs_frag)); - printk(" fragshift: %u\n", SWAB32(usb1->fs_fragshift)); - printk(" ~fmask: %u\n", ~SWAB32(usb1->fs_fmask)); - printk(" fshift: %u\n", SWAB32(usb1->fs_fshift)); - printk(" sbsize: %u\n", SWAB32(usb1->fs_sbsize)); - printk(" spc: %u\n", SWAB32(usb1->fs_spc)); - printk(" cpg: %u\n", SWAB32(usb1->fs_cpg)); - printk(" ipg: %u\n", SWAB32(usb1->fs_ipg)); - printk(" fpg: %u\n", SWAB32(usb1->fs_fpg)); - printk(" csaddr: %u\n", SWAB32(usb1->fs_csaddr)); - printk(" cssize: %u\n", SWAB32(usb1->fs_cssize)); - printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize)); - printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb)); - printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat)); - printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos)); - printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir)); - printk(" nifree %u\n", SWAB32(usb1->fs_cstotal.cs_nifree)); - printk(" nbfree %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree)); - printk(" nffree %u\n", SWAB32(usb1->fs_cstotal.cs_nffree)); + printk("ufs_print_super_stuff\n"); + printk("size of usb: %u\n", sizeof(struct ufs_super_block)); + printk(" magic: 0x%x\n", SWAB32(usb3->fs_magic)); + printk(" sblkno: %u\n", SWAB32(usb1->fs_sblkno)); + printk(" cblkno: %u\n", SWAB32(usb1->fs_cblkno)); + printk(" iblkno: %u\n", SWAB32(usb1->fs_iblkno)); + printk(" dblkno: %u\n", SWAB32(usb1->fs_dblkno)); + printk(" cgoffset: %u\n", SWAB32(usb1->fs_cgoffset)); + printk(" ~cgmask: 0x%x\n", ~SWAB32(usb1->fs_cgmask)); + printk(" size: %u\n", SWAB32(usb1->fs_size)); + printk(" dsize: %u\n", SWAB32(usb1->fs_dsize)); + printk(" ncg: %u\n", SWAB32(usb1->fs_ncg)); + printk(" bsize: %u\n", SWAB32(usb1->fs_bsize)); + printk(" fsize: %u\n", SWAB32(usb1->fs_fsize)); + printk(" frag: %u\n", SWAB32(usb1->fs_frag)); + printk(" fragshift: %u\n", SWAB32(usb1->fs_fragshift)); + printk(" ~fmask: %u\n", ~SWAB32(usb1->fs_fmask)); + printk(" fshift: %u\n", SWAB32(usb1->fs_fshift)); + printk(" sbsize: %u\n", SWAB32(usb1->fs_sbsize)); + printk(" spc: %u\n", SWAB32(usb1->fs_spc)); + printk(" cpg: %u\n", SWAB32(usb1->fs_cpg)); + printk(" ipg: %u\n", SWAB32(usb1->fs_ipg)); + printk(" fpg: %u\n", SWAB32(usb1->fs_fpg)); + printk(" csaddr: %u\n", SWAB32(usb1->fs_csaddr)); + printk(" cssize: %u\n", SWAB32(usb1->fs_cssize)); + printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize)); + printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb)); + printk(" contigsumsize: %d\n", SWAB32(usb3->fs_u.fs_44.fs_contigsumsize)); + printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat)); + printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos)); + printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir)); + printk(" nifree %u\n", SWAB32(usb1->fs_cstotal.cs_nifree)); + printk(" nbfree %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree)); + printk(" nffree %u\n", SWAB32(usb1->fs_cstotal.cs_nffree)); + printk("\n"); } @@ -101,107 +141,411 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1, void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab) { printk("\nufs_print_cylinder_stuff\n"); - printk("size of ucg: %lu\n", sizeof(struct ufs_cylinder_group)); - printk(" magic: %x\n", SWAB32(cg->cg_magic)); - printk(" time: %u\n", SWAB32(cg->cg_time)); - printk(" cgx: %u\n", SWAB32(cg->cg_cgx)); - printk(" ncyl: %u\n", SWAB16(cg->cg_ncyl)); - printk(" niblk: %u\n", SWAB16(cg->cg_niblk)); - printk(" ndblk: %u\n", SWAB32(cg->cg_ndblk)); - printk(" cs_ndir: %u\n", SWAB32(cg->cg_cs.cs_ndir)); - printk(" cs_nbfree: %u\n", SWAB32(cg->cg_cs.cs_nbfree)); - printk(" cs_nifree: %u\n", SWAB32(cg->cg_cs.cs_nifree)); - printk(" cs_nffree: %u\n", SWAB32(cg->cg_cs.cs_nffree)); - printk(" rotor: %u\n", SWAB32(cg->cg_rotor)); - printk(" frotor: %u\n", SWAB32(cg->cg_frotor)); - printk(" irotor: %u\n", SWAB32(cg->cg_irotor)); - printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", + printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group)); + printk(" magic: %x\n", SWAB32(cg->cg_magic)); + printk(" time: %u\n", SWAB32(cg->cg_time)); + printk(" cgx: %u\n", SWAB32(cg->cg_cgx)); + printk(" ncyl: %u\n", SWAB16(cg->cg_ncyl)); + printk(" niblk: %u\n", SWAB16(cg->cg_niblk)); + printk(" ndblk: %u\n", SWAB32(cg->cg_ndblk)); + printk(" cs_ndir: %u\n", SWAB32(cg->cg_cs.cs_ndir)); + printk(" cs_nbfree: %u\n", SWAB32(cg->cg_cs.cs_nbfree)); + printk(" cs_nifree: %u\n", SWAB32(cg->cg_cs.cs_nifree)); + printk(" cs_nffree: %u\n", SWAB32(cg->cg_cs.cs_nffree)); + printk(" rotor: %u\n", SWAB32(cg->cg_rotor)); + printk(" frotor: %u\n", SWAB32(cg->cg_frotor)); + printk(" irotor: %u\n", SWAB32(cg->cg_irotor)); + printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", SWAB32(cg->cg_frsum[0]), SWAB32(cg->cg_frsum[1]), SWAB32(cg->cg_frsum[2]), SWAB32(cg->cg_frsum[3]), SWAB32(cg->cg_frsum[4]), SWAB32(cg->cg_frsum[5]), SWAB32(cg->cg_frsum[6]), SWAB32(cg->cg_frsum[7])); - printk(" btotoff: %u\n", SWAB32(cg->cg_btotoff)); - printk(" boff: %u\n", SWAB32(cg->cg_boff)); - printk(" iuseoff: %u\n", SWAB32(cg->cg_iusedoff)); - printk(" freeoff: %u\n", SWAB32(cg->cg_freeoff)); - printk(" nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff)); + printk(" btotoff: %u\n", SWAB32(cg->cg_btotoff)); + printk(" boff: %u\n", SWAB32(cg->cg_boff)); + printk(" iuseoff: %u\n", SWAB32(cg->cg_iusedoff)); + printk(" freeoff: %u\n", SWAB32(cg->cg_freeoff)); + printk(" nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff)); + printk(" clustersumoff %u\n", SWAB32(cg->cg_u.cg_44.cg_clustersumoff)); + printk(" clusteroff %u\n", SWAB32(cg->cg_u.cg_44.cg_clusteroff)); + printk(" nclusterblks %u\n", SWAB32(cg->cg_u.cg_44.cg_nclusterblks)); + printk("\n"); } #endif /* UFS_SUPER_DEBUG_MORE */ +static char error_buf[1024]; + +void ufs_error (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + struct ufs_sb_private_info * uspi; + struct ufs_super_block_first * usb1; + va_list args; + + uspi = sb->u.ufs_sb.s_uspi; + usb1 = ubh_get_usb_first(USPI_UBH); + + if (!(sb->s_flags & MS_RDONLY)) { + usb1->fs_clean = UFS_FSBAD; + ubh_mark_buffer_dirty(USPI_UBH, 1); + sb->s_dirt = 1; + sb->s_flags |= MS_RDONLY; + } + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_ONERROR) { + case UFS_MOUNT_ONERROR_PANIC: + panic ("UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); + + case UFS_MOUNT_ONERROR_LOCK: + case UFS_MOUNT_ONERROR_UMOUNT: + case UFS_MOUNT_ONERROR_REPAIR: + printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); + } +} + +void ufs_panic (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + struct ufs_sb_private_info * uspi; + struct ufs_super_block_first * usb1; + va_list args; + + uspi = sb->u.ufs_sb.s_uspi; + usb1 = ubh_get_usb_first(USPI_UBH); + + if (!(sb->s_flags & MS_RDONLY)) { + usb1->fs_clean = UFS_FSBAD; + ubh_mark_buffer_dirty(USPI_UBH, 1); + sb->s_dirt = 1; + } + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + /* this is to prevent panic from syncing this filesystem */ + if (sb->s_lock) + sb->s_lock = 0; + sb->s_flags |= MS_RDONLY; + printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +/*** + panic ("UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +***/ +} + +void ufs_warning (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + va_list args; + + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +} + +static int ufs_parse_options (char * options, unsigned * mount_options) +{ + char * this_char; + char * value; + + UFSD(("ENTER\n")) + + if (!options) + return 1; + + for (this_char = strtok (options, ","); + this_char != NULL; + this_char = strtok (NULL, ",")) { + + if ((value = strchr (this_char, '=')) != NULL) + *value++ = 0; + if (!strcmp (this_char, "ufstype")) { + ufs_clear_opt (*mount_options, UFSTYPE); + if (!strcmp (value, "old")) + ufs_set_opt (*mount_options, UFSTYPE_OLD); + else if (!strcmp (value, "sun")) + ufs_set_opt (*mount_options, UFSTYPE_SUN); + else if (!strcmp (value, "44bsd")) + ufs_set_opt (*mount_options, UFSTYPE_44BSD); + else if (!strcmp (value, "next")) + ufs_set_opt (*mount_options, UFSTYPE_NEXT); + else { + printk ("UFS-fs: Invalid type option: %s\n", value); + return 0; + } + } + else if (!strcmp (this_char, "onerror")) { + ufs_clear_opt (*mount_options, ONERROR); + if (!strcmp (value, "panic")) + ufs_set_opt (*mount_options, ONERROR_PANIC); + else if (!strcmp (value, "lock")) + ufs_set_opt (*mount_options, ONERROR_LOCK); + else if (!strcmp (value, "umount")) + ufs_set_opt (*mount_options, ONERROR_UMOUNT); + else if (!strcmp (value, "repair")) { + printk("UFS-fs: Unable to do repair on error, " + "will lock lock instead \n"); + ufs_set_opt (*mount_options, ONERROR_REPAIR); + } + else { + printk ("UFS-fs: Invalid action onerror: %s\n", value); + return 0; + } + } + else { + printk("UFS-fs: Invalid option: %s\n", this_char); + return 0; + } + } + return 1; +} + +/* + * Read on-disk structures asscoiated with cylinder groups + */ +int ufs_read_cylinder_structures (struct super_block * sb) { + struct ufs_sb_private_info * uspi; + struct ufs_buffer_head * ubh; + unsigned char * base, * space; + unsigned size, blks, i; + unsigned swab; + + UFSD(("ENTER\n")) + + uspi = sb->u.ufs_sb.s_uspi; + swab = sb->u.ufs_sb.s_swab; + + /* + * Read cs structures from (usually) first data block + * on the device. + */ + size = uspi->s_cssize; + blks = howmany(size, uspi->s_fsize); + base = space = kmalloc(size, GFP_KERNEL); + if (!base) + goto failed; + for (i = 0; i < blks; i += uspi->s_fpb) { + size = uspi->s_bsize; + if (i + uspi->s_fpb > blks) + size = (blks - i) * uspi->s_fsize; + ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size); + if (!ubh) + goto failed; + ubh_ubhcpymem (space, ubh, size); + sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space; + space += size; + ubh_brelse (ubh); + ubh = NULL; + } + + /* + * Read cylinder group (we read only first fragment from block + * at this time) and prepare internal data structures for cg caching. + */ + if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) + goto failed; + for (i = 0; i < uspi->s_ncg; i++) + sb->u.ufs_sb.s_ucg[i] = NULL; + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { + sb->u.ufs_sb.s_ucpi[i] = NULL; + sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; + } + for (i = 0; i < uspi->s_ncg; i++) { + UFSD(("read cg %u\n", i)) + if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize))) + goto failed; + if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data)) + goto failed; +#ifdef UFS_SUPER_DEBUG_MORE + ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab); +#endif + } + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { + if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) + goto failed; + sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; + } + sb->u.ufs_sb.s_cg_loaded = 0; + UFSD(("EXIT\n")) + return 1; + +failed: + if (base) kfree (base); + if (sb->u.ufs_sb.s_ucg) { + for (i = 0; i < uspi->s_ncg; i++) + if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]); + kfree (sb->u.ufs_sb.s_ucg); + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) + if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]); + } + UFSD(("EXIT (FAILED)\n")) + return 0; +} + /* - * Called while file system is mounted, read super block - * and create important internal structures. + * Put on-disk structures associated with cylidner groups and + * write them back to disk */ -struct super_block * ufs_read_super ( - struct super_block * sb, - void * data, +void ufs_put_cylinder_structures (struct super_block * sb) { + struct ufs_sb_private_info * uspi; + struct ufs_buffer_head * ubh; + unsigned char * base, * space; + unsigned blks, size, i; + + UFSD(("ENTER\n")) + + uspi = sb->u.ufs_sb.s_uspi; + + size = uspi->s_cssize; + blks = howmany(size, uspi->s_fsize); + base = space = (char*) sb->u.ufs_sb.s_csp[0]; + for (i = 0; i < blks; i += uspi->s_fpb) { + size = uspi->s_bsize; + if (i + uspi->s_fpb > blks) + size = (blks - i) * uspi->s_fsize; + ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size); + ubh_memcpyubh (ubh, space, size); + space += size; + ubh_mark_buffer_uptodate (ubh, 1); + ubh_mark_buffer_dirty (ubh, 0); + ubh_brelse (ubh); + } + for (i = 0; i < sb->u.ufs_sb.s_cg_loaded; i++) { + ufs_put_cylinder (sb, i); + kfree (sb->u.ufs_sb.s_ucpi[i]); + } + for (; i < UFS_MAX_GROUP_LOADED; i++) + kfree (sb->u.ufs_sb.s_ucpi[i]); + for (i = 0; i < uspi->s_ncg; i++) + brelse (sb->u.ufs_sb.s_ucg[i]); + kfree (sb->u.ufs_sb.s_ucg); + kfree (base); + UFSD(("EXIT\n")) +} + +struct super_block * ufs_read_super (struct super_block * sb, void * data, int silent) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_super_block_second * usb2; struct ufs_super_block_third * usb3; - struct ufs_buffer_head * ubh; - unsigned char * base, * space; - unsigned size, blks, i; + struct ufs_buffer_head * ubh; unsigned block_size, super_block_size; unsigned flags, swab; - s64 tmp; - static unsigned offsets[] = {0, 96, 160}; /* different superblock locations */ - - UFSD(("ENTER\n")) - + uspi = NULL; ubh = NULL; - base = space = NULL; - sb->u.ufs_sb.s_ucg = NULL; flags = 0; + swab = 0; - /* sb->s_dev and sb->s_flags are set by our caller - * data is the mystery argument to sys_mount() - * - * Our caller also sets s_dev, s_covered, s_rd_only, s_dirt, - * and s_type when we return. - */ - + UFSD(("ENTER\n")) + MOD_INC_USE_COUNT; lock_super (sb); - sb->u.ufs_sb.s_uspi = uspi = + /* + * Set default mount options + * Parse mount options + */ + sb->u.ufs_sb.s_mount_opt = 0; + ufs_set_opt (sb->u.ufs_sb.s_mount_opt, ONERROR_LOCK); + if (!ufs_parse_options ((char *) data, &sb->u.ufs_sb.s_mount_opt)) { + printk("wrong mount options\n"); + goto failed; + } + if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) { + printk("You didn't specify type of your ufs file system\n\n" + " mount -t ufs -o ufstype=sun|44bsd|old|next ....\n\n" + "!!! WARNING !!! wrong value may corrupt you file system\n" + "default value is ufstype=old\n"); + ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD); + } + + sb->u.ufs_sb.s_uspi = uspi = kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL); if (!uspi) goto failed; + + switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) { + case UFS_MOUNT_UFSTYPE_44BSD: + UFSD(("44bsd ufstype\n")) + uspi->s_fsize = block_size = 512; + uspi->s_fmask = ~(512 - 1); + uspi->s_fshift = 9; + uspi->s_sbsize = super_block_size = 1536; + uspi->s_sbbase = 0; + flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; + break; + + case UFS_MOUNT_UFSTYPE_SUN: + UFSD(("sun ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN; + break; + + case UFS_MOUNT_UFSTYPE_OLD: + UFSD(("old ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; + if (!(sb->s_flags & MS_RDONLY)) { + printk("old type of ufs is supported read-only\n"); + goto failed; + } + break; - block_size = BLOCK_SIZE; - super_block_size = BLOCK_SIZE * 2; + case UFS_MOUNT_UFSTYPE_NEXT: + UFSD(("next ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; + if (!(sb->s_flags & MS_RDONLY)) { + printk("nextstep type of ufs is supported read-only\n"); + goto failed; + } + break; - uspi->s_fsize = block_size; - uspi->s_fmask = ~(BLOCK_SIZE - 1); - uspi->s_fshift = BLOCK_SIZE_BITS; - uspi->s_sbsize = super_block_size; - i = 0; - uspi->s_sbbase = offsets[i]; -again: + default: + printk("this fs type of ufs is not supported\n"); + goto failed; + } + + if (!(sb->s_flags & MS_RDONLY)) + printk("!!! warning !!! write support of ufs is still in experimental state\n"); + +again: set_blocksize (sb->s_dev, block_size); /* * read ufs super block from device */ - ubh = ubh_bread2 (sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); + ubh = ubh_bread_uspi (uspi, sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); if (!ubh) goto failed; usb1 = ubh_get_usb_first(USPI_UBH); usb2 = ubh_get_usb_second(USPI_UBH); usb3 = ubh_get_usb_third(USPI_UBH); - + /* * Check ufs magic number - * This code uses goto, because it's a lesser evil than unbalanced - * structure in conditional code. Brought to you by Fare' as a minimal - * hack to live with Daniel's (unnecessary, IMNSHO) manual swab - * optimization -- see swab.h. */ #if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */ switch (usb3->fs_magic) { @@ -222,108 +566,68 @@ again: goto magic_found; } #endif - /* - * Magic number not found -- try another super block location - */ - if (++i < sizeof(offsets)/sizeof(unsigned)) { - ubh_brelse2(ubh); + + if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == + UFS_MOUNT_UFSTYPE_NEXT && uspi->s_sbbase < 256) { + ubh_brelse_uspi(uspi); ubh = NULL; - uspi->s_sbbase = offsets[i]; + uspi->s_sbbase += 8; goto again; - } else { - printk("ufs_read_super: " - "super block location not in " - "{ 0, 96, 160} " - "or bad magic number\n"); - goto failed; } - magic_found: + printk("ufs_read_super: bad magic number\n"); + goto failed; +magic_found: /* * Check block and fragment sizes */ uspi->s_bsize = SWAB32(usb1->fs_bsize); uspi->s_fsize = SWAB32(usb1->fs_fsize); uspi->s_sbsize = SWAB32(usb1->fs_sbsize); + uspi->s_fmask = SWAB32(usb1->fs_fmask); + uspi->s_fshift = SWAB32(usb1->fs_fshift); if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192) { - printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", - uspi->s_bsize); + printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize); goto failed; } if (uspi->s_fsize != 512 && uspi->s_fsize != 1024) { - printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", - uspi->s_fsize); + printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", uspi->s_fsize); goto failed; } - - /* - * Block size is not 1024. Free buffers, set block_size and - * super_block_size to superblock-declared values, and try again. - */ if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { - ubh_brelse2(ubh); + ubh_brelse_uspi(uspi); ubh = NULL; - uspi->s_fmask = SWAB32(usb1->fs_fmask); - uspi->s_fshift = SWAB32(usb1->fs_fshift); block_size = uspi->s_fsize; super_block_size = uspi->s_sbsize; + UFSD(("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size)) goto again; } #ifdef UFS_SUPER_DEBUG_MORE ufs_print_super_stuff (usb1, usb2, usb3, swab); #endif - /* - * Check file system flavor - */ - flags |= UFS_VANILLA; - /* XXX more consistency check */ - UFSD(("ufs_read_super: maxsymlinklen 0x%8.8x\n", usb3->fs_u.fs_44.fs_maxsymlinklen)) - if (usb3->fs_u.fs_44.fs_maxsymlinklen >= 0) { - if (usb3->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) { - UFSD(("Flavor: 44BSD\n")) - flags |= UFS_44BSD; - sb->s_flags |= MS_RDONLY; - } else { - UFSD(("Flavor: OLD\n")) - sb->s_flags |= UFS_OLD; /* 4.2BSD */ - } - } else if (uspi->s_sbbase > 0) { - UFSD(("Flavor: NEXT\n")) - flags |= UFS_NEXT; - sb->s_flags |= MS_RDONLY; - } else { - UFSD(("Flavor: SUN\n")) - flags |= UFS_SUN; - } /* - * Check whether file system was correctly unmounted. + * Check, if file system was correctly unmounted. * If not, make it read only. */ if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || ((flags & UFS_ST_MASK) == UFS_ST_OLD) || - ((flags & UFS_ST_MASK) == UFS_ST_NEXT) || - (((flags & UFS_ST_MASK) == UFS_ST_SUN) && - ufs_state(usb3) == UFS_FSOK - usb1->fs_time)) { + (((flags & UFS_ST_MASK) == UFS_ST_SUN) && + (ufs_get_fs_state(usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) { switch(usb1->fs_clean) { - case UFS_FSACTIVE: /* 0x00 */ - printk("ufs_read_super: fs is active\n"); - sb->s_flags |= MS_RDONLY; - break; - case UFS_FSCLEAN: /* 0x01 */ - UFSD(("ufs_read_super: fs is clean\n")) + case UFS_FSCLEAN: + UFSD(("fs is clean\n")) break; case UFS_FSSTABLE: - UFSD(("ufs_read_super: fs is stable\n")) + UFSD(("fs is stable\n")) break; - case UFS_FSOSF1: /* 0x03 */ - /* XXX - is this the correct interpretation under DEC OSF/1? */ - printk("ufs_read_super: " - "fs is clean and stable (OSF/1)\n"); + case UFS_FSACTIVE: + printk("ufs_read_super: fs is active\n"); + sb->s_flags |= MS_RDONLY; break; - case UFS_FSBAD: /* 0xFF */ + case UFS_FSBAD: printk("ufs_read_super: fs is bad\n"); sb->s_flags |= MS_RDONLY; break; @@ -333,19 +637,19 @@ again: sb->s_flags |= MS_RDONLY; break; } - } else { + } + else { printk("ufs_read_super: fs needs fsck\n"); sb->s_flags |= MS_RDONLY; } - sb->s_flags &= ~MS_RDONLY; /* * Read ufs_super_block into internal data structures */ sb->s_blocksize = SWAB32(usb1->fs_fsize); sb->s_blocksize_bits = SWAB32(usb1->fs_fshift); sb->s_op = &ufs_super_ops; - sb->dq_op = 0; /* XXX */ + sb->dq_op = NULL; /***/ sb->s_magic = SWAB32(usb3->fs_magic); uspi->s_sblkno = SWAB32(usb1->fs_sblkno); @@ -385,12 +689,9 @@ again: uspi->s_ipg = SWAB32(usb1->fs_ipg); uspi->s_fpg = SWAB32(usb1->fs_fpg); uspi->s_cpc = SWAB32(usb2->fs_cpc); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1]; - uspi->s_qbmask = SWAB64(tmp); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1]; - uspi->s_qfmask = SWAB64(tmp); + uspi->s_contigsumsize = SWAB32(usb3->fs_u.fs_44.fs_contigsumsize); + uspi->s_qbmask = ufs_get_fs_qbmask(usb3); + uspi->s_qfmask = ufs_get_fs_qfmask(usb3); uspi->s_postblformat = SWAB32(usb3->fs_postblformat); uspi->s_nrpos = SWAB32(usb3->fs_nrpos); uspi->s_postbloff = SWAB32(usb3->fs_postbloff); @@ -410,86 +711,32 @@ again: uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; - - /* we could merge back s_swab and s_flags by having - foo.s_flags = flags | swab; here, and #defining - s_swab to s_flags & UFS_BYTESEX in swab.h */ + uspi->s_bpf = uspi->s_fsize << 3; + uspi->s_bpfshift = uspi->s_fshift + 3; + uspi->s_bpfmask = uspi->s_bpf - 1; + sb->u.ufs_sb.s_flags = flags; sb->u.ufs_sb.s_swab = swab; sb->u.ufs_sb.s_rename_lock = 0; sb->u.ufs_sb.s_rename_wait = NULL; - + sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL); - /* - * Read cs structures from (usually) first data block - * on the device. - */ - size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); - base = space = kmalloc(size, GFP_KERNEL); - if (!base) - goto failed; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size); - if (!ubh) - goto failed; - ubh_ubhcpymem (space, ubh, size); - sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space; - space += size; - ubh_brelse (ubh); - ubh = NULL; - } /* - * Read cylinder group (we read only first fragment from block - * at this time) and prepare internal data structures for cg caching. - * XXX - something here fails on CDROMs from DEC! + * Read cylinder group structures */ - if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) - goto failed; - for (i = 0; i < uspi->s_ncg; i++) - sb->u.ufs_sb.s_ucg[i] = NULL; - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - sb->u.ufs_sb.s_ucpi[i] = NULL; - sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; - } - for (i = 0; i < uspi->s_ncg; i++) { - UFSD(("read cg %u\n", i)) - if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize))) - goto failed; - if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data)) - goto failed; -#ifdef UFS_SUPER_DEBUG_MORE - ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab); -#endif - } - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) + if (!(sb->s_flags & MS_RDONLY)) + if (!ufs_read_cylinder_structures(sb)) goto failed; - sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; - } - sb->u.ufs_sb.s_cg_loaded = 0; unlock_super(sb); UFSD(("EXIT\n")) return(sb); failed: - if (ubh) ubh_brelse2 (ubh); + if (ubh) ubh_brelse_uspi (uspi); if (uspi) kfree (uspi); - if (base) kfree (base); - - if (sb->u.ufs_sb.s_ucg) { - for (i = 0; i < uspi->s_ncg; i++) - if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]); - kfree (sb->u.ufs_sb.s_ucg); - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) - if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]); - } sb->s_dev = 0; unlock_super (sb); MOD_DEC_USE_COUNT; @@ -497,187 +744,132 @@ failed: return(NULL); } -/* - * Put super block, release internal structures - */ -void ufs_put_super (struct super_block * sb) -{ - struct ufs_sb_private_info * uspi; - struct ufs_buffer_head * ubh; - unsigned char * base, * space; - unsigned size, blks, i; - - UFSD(("ENTER\n")) - - uspi = sb->u.ufs_sb.s_uspi; - size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); - base = space = (char*) sb->u.ufs_sb.s_csp[0]; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size); - if (!ubh) - goto go_on; - ubh_memcpyubh (ubh, space, size); - space += size; - ubh_mark_buffer_uptodate (ubh, 1); - ubh_mark_buffer_dirty (ubh, 0); - ubh_brelse (ubh); - } - -go_on: - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - ufs_put_cylinder (sb, i); - kfree (sb->u.ufs_sb.s_ucpi[i]); - } - for (i = 0; i < uspi->s_ncg; i++) - brelse (sb->u.ufs_sb.s_ucg[i]); - kfree (sb->u.ufs_sb.s_ucg); - kfree (base); - ubh_brelse2 (USPI_UBH); - kfree (sb->u.ufs_sb.s_uspi); - sb->s_dev = 0; - MOD_DEC_USE_COUNT; - return; -} - -/* - * Write super block to device - */ void ufs_write_super (struct super_block * sb) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_super_block_third * usb3; - unsigned swab; - + unsigned flags, swab; + UFSD(("ENTER\n")) swab = sb->u.ufs_sb.s_swab; + flags = sb->u.ufs_sb.s_flags; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); usb3 = ubh_get_usb_third(USPI_UBH); - + if (!(sb->s_flags & MS_RDONLY)) { - if (SWAB16(usb3->fs_u.fs_sun.fs_state) & UFS_FSOK) - usb3->fs_u.fs_sun.fs_state = SWAB16(SWAB16(usb3->fs_u.fs_sun.fs_state) & ~UFS_FSOK); usb1->fs_time = SWAB32(CURRENT_TIME); - usb3->fs_u.fs_sun.fs_state = SWAB32(UFS_FSOK - SWAB32(usb1->fs_time)); + if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN) + ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time)); ubh_mark_buffer_dirty (USPI_UBH, 1); } sb->s_dirt = 0; UFSD(("EXIT\n")) } -/* - * Copy some info about file system to user - */ -int ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsiz) +void ufs_put_super (struct super_block * sb) { struct ufs_sb_private_info * uspi; - struct ufs_super_block_first * usb1; - struct statfs tmp; - struct statfs *sp = &tmp; - unsigned long used, avail; unsigned swab; - + UFSD(("ENTER\n")) - - swab = sb->u.ufs_sb.s_swab; - uspi = sb->u.ufs_sb.s_uspi; - usb1 = ubh_get_usb_first (USPI_UBH); - sp->f_type = UFS_MAGIC; - sp->f_bsize = sb->s_blocksize; - sp->f_blocks = uspi->s_dsize; - sp->f_bfree = (SWAB32(usb1->fs_cstotal.cs_nbfree) << uspi->s_fpbshift )+ - SWAB32(usb1->fs_cstotal.cs_nffree); + uspi = sb->u.ufs_sb.s_uspi; + swab = sb->u.ufs_sb.s_swab; - avail = sp->f_blocks - (sp->f_blocks / 100) * uspi->s_minfree; - used = sp->f_blocks - sp->f_bfree; - if (avail > used) - sp->f_bavail = avail - used; - else - sp->f_bavail = 0; - sp->f_files = uspi->s_ncg * uspi->s_ipg; - sp->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); - sp->f_fsid.val[0] = SWAB32(usb1->fs_id[0]); - sp->f_fsid.val[1] = SWAB32(usb1->fs_id[1]); - sp->f_namelen = UFS_MAXNAMLEN; + if (!(sb->s_flags & MS_RDONLY)) + ufs_put_cylinder_structures (sb); - UFSD(("EXIT\n")) - - return copy_to_user(buf, sp, bufsiz) ? -EFAULT : 0; + ubh_brelse_uspi (uspi); + kfree (sb->u.ufs_sb.s_uspi); + sb->s_dev = 0; + MOD_DEC_USE_COUNT; + return; } -static char error_buf[1024]; - -void ufs_warning (struct super_block * sb, const char * function, - const char * fmt, ...) -{ - va_list args; - - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -} - -void ufs_error (struct super_block * sb, const char * function, - const char * fmt, ...) +int ufs_remount (struct super_block * sb, int * mount_flags, char * data) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - va_list args; - + struct ufs_super_block_third * usb3; + unsigned new_mount_opt, ufstype; + unsigned flags, swab; + uspi = sb->u.ufs_sb.s_uspi; + flags = sb->u.ufs_sb.s_flags; + swab = sb->u.ufs_sb.s_swab; usb1 = ubh_get_usb_first(USPI_UBH); + usb3 = ubh_get_usb_third(USPI_UBH); - if (!(sb->s_flags & MS_RDONLY)) { - usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); - sb->s_dirt = 1; + /* + * Allow the "check" option to be passed as a remount option. + * It is not possible to change ufstype option during remount + */ + ufstype = sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE; + new_mount_opt = 0; + ufs_set_opt (new_mount_opt, ONERROR_LOCK); + if (!ufs_parse_options (data, &new_mount_opt)) + return -EINVAL; + if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { + new_mount_opt |= ufstype; + } + else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { + printk("ufstype can't be changed during remount\n"); + return -EINVAL; + } + sb->u.ufs_sb.s_mount_opt = new_mount_opt; + + if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + return 0; + if (*mount_flags & MS_RDONLY) { + ufs_put_cylinder_structures(sb); + usb1->fs_time = SWAB32(CURRENT_TIME); + if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN) + ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time)); + ubh_mark_buffer_dirty (USPI_UBH, 1); + sb->s_dirt = 0; sb->s_flags |= MS_RDONLY; } - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); + else { + if (ufstype != UFS_MOUNT_UFSTYPE_SUN && + ufstype != UFS_MOUNT_UFSTYPE_44BSD) { + printk("this ufstype is read-only supported\n"); + return 0; + } + if (!ufs_read_cylinder_structures (sb)) { + printk("failed during remounting\n"); + return 0; + } + sb->s_flags &= ~MS_RDONLY; + } + return 0; } -void ufs_panic (struct super_block * sb, const char * function, - const char * fmt, ...) +int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - va_list args; - + struct statfs tmp; + unsigned swab; + + swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first (USPI_UBH); - if (!(sb->s_flags & MS_RDONLY)) { - usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); - sb->s_dirt = 1; - } - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - /* this is to prevent panic from syncing this filesystem */ - if (sb->s_lock) - sb->s_lock = 0; - sb->s_flags |= MS_RDONLY; - printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -/* panic ("UFS-fs panic (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -*/ + tmp.f_type = UFS_MAGIC; + tmp.f_bsize = sb->s_blocksize; + tmp.f_blocks = uspi->s_dsize; + tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) + + SWAB32(usb1->fs_cstotal.cs_nffree); + tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree)) + ? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0; + tmp.f_files = uspi->s_ncg * uspi->s_ipg; + tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); + tmp.f_namelen = UFS_MAXNAMLEN; + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } - static struct super_operations ufs_super_ops = { ufs_read_inode, ufs_write_inode, @@ -687,20 +879,19 @@ static struct super_operations ufs_super_ops = { ufs_put_super, ufs_write_super, ufs_statfs, - NULL, /* XXX - ufs_remount() */ + ufs_remount }; static struct file_system_type ufs_fs_type = { - "ufs", + "ufs", FS_REQUIRES_DEV, ufs_read_super, NULL }; - __initfunc(int init_ufs_fs(void)) { - return(register_filesystem(&ufs_fs_type)); + return register_filesystem(&ufs_fs_type); } #ifdef MODULE @@ -715,5 +906,5 @@ void cleanup_module(void) { unregister_filesystem(&ufs_fs_type); } -#endif +#endif diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index f1004733a..bdc38e9fe 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -43,7 +43,7 @@ static struct dentry * ufs_follow_link(struct dentry * dentry, - struct dentry * base) + struct dentry * base, unsigned int follow) { struct inode * inode; struct buffer_head * bh; @@ -67,7 +67,7 @@ static struct dentry * ufs_follow_link(struct dentry * dentry, link = (char *) inode->u.ufs_i.i_u1.i_symlink; } UPDATE_ATIME(inode); - base = lookup_dentry(link, base, 1); + base = lookup_dentry(link, base, follow); if (bh) brelse(bh); UFSD(("EXIT\n")) diff --git a/fs/ufs/util.c b/fs/ufs/util.c index 527ba02aa..23f5052bb 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -49,7 +49,7 @@ failed: return NULL; } -struct ufs_buffer_head * _ubh_bread2_ (struct ufs_sb_private_info * uspi, +struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi, kdev_t dev, unsigned fragment, unsigned size) { unsigned i, j, count; @@ -82,14 +82,14 @@ void ubh_brelse (struct ufs_buffer_head * ubh) kfree (ubh); } -void ubh_brelse2 (struct ufs_buffer_head * ubh) +void ubh_brelse_uspi (struct ufs_sb_private_info * uspi) { unsigned i; - if (!ubh) + if (!USPI_UBH) return; - for ( i = 0; i < ubh->count; i++ ) { - brelse (ubh->bh[i]); - ubh->bh[i] = NULL; + for ( i = 0; i < USPI_UBH->count; i++ ) { + brelse (USPI_UBH->bh[i]); + USPI_UBH->bh[i] = NULL; } } @@ -138,8 +138,6 @@ unsigned ubh_max_bcount (struct ufs_buffer_head * ubh) for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i]->b_count > max ) max = ubh->bh[i]->b_count; - if (max == 0) - printk("Je cosi shnileho v kralovstvi Danskem!\n"); return max; } diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 7443f9fc9..02e6fe98a 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -19,73 +19,166 @@ #define max(x,y) ((x)>(y)?(x):(y)) + /* - * current filesystem state; method depends on flags + * macros used for retyping */ -#define ufs_state(usb3) \ - (((flags & UFS_ST_MASK) == UFS_ST_OLD) \ - ? (usb3)->fs_u.fs_sun.fs_state /* old normal way */ \ - : (usb3)->fs_u.fs_44.fs_state /* 4.4BSD way */) +#define UCPI_UBH ((struct ufs_buffer_head *)ucpi) +#define USPI_UBH ((struct ufs_buffer_head *)uspi) + + /* - * namlen, its format depends of flags + * macros used for accesing structures */ -#define ufs_namlen(de) _ufs_namlen_(de,flags,swab) -static inline __u16 _ufs_namlen_(struct ufs_dir_entry * de, unsigned flags, unsigned swab) { - if ((flags & UFS_DE_MASK) == UFS_DE_OLD) { - return SWAB16(de->d_u.d_namlen); - } else /* UFS_DE_44BSD */ { - return de->d_u.d_44.d_namlen; +#define ufs_get_fs_state(usb3) _ufs_get_fs_state_(usb3,flags,swab) +static inline __s32 _ufs_get_fs_state_(struct ufs_super_block_third * usb3, + unsigned flags, unsigned swab) +{ + if ((flags & UFS_ST_MASK) == UFS_ST_SUN) + return SWAB32((usb3)->fs_u.fs_sun.fs_state); + else + return SWAB32((usb3)->fs_u.fs_44.fs_state); +} + +#define ufs_set_fs_state(usb3,value) _ufs_set_fs_state_(usb3,value,flags,swab) +static inline void _ufs_set_fs_state_(struct ufs_super_block_third * usb3, + __s32 value, unsigned flags, unsigned swab) +{ + if ((flags & UFS_ST_MASK) == UFS_ST_SUN) + (usb3)->fs_u.fs_sun.fs_state = SWAB32(value); + else + (usb3)->fs_u.fs_44.fs_state = SWAB32(value); +} + +#define ufs_get_fs_qbmask(usb3) _ufs_get_fs_qbmask_(usb3,flags,swab) +static inline __u64 _ufs_get_fs_qbmask_(struct ufs_super_block_third * usb3, + unsigned flags, unsigned swab) +{ + __u64 tmp; + if ((flags & UFS_ST_MASK) == UFS_ST_SUN) { + ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1]; + } + else { + ((u32 *)&tmp)[0] = usb3->fs_u.fs_44.fs_qbmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_44.fs_qbmask[1]; } + return SWAB64(tmp); } -/* - * Here is how the uid is computed: - * if the file system is 4.2BSD, get it from oldids. - * if it has sun extension and oldids is USEEFT, get it from ui_sun. - * if it is 4.4 or Hurd, get it from ui_44 (which is the same as from ui_hurd). - */ -#define ufs_uid(inode) _ufs_uid_(inode,flags,swab) -static inline __u32 _ufs_uid_(struct ufs_inode * inode, unsigned flags, unsigned swab) { +#define ufs_get_fs_qfmask(usb3) _ufs_get_fs_qfmask_(usb3,flags,swab) +static inline __u64 _ufs_get_fs_qfmask_(struct ufs_super_block_third * usb3, + unsigned flags, unsigned swab) +{ + __u64 tmp; + if ((flags & UFS_ST_MASK) == UFS_ST_SUN) { + ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1]; + } + else { + ((u32 *)&tmp)[0] = usb3->fs_u.fs_44.fs_qfmask[0]; + ((u32 *)&tmp)[1] = usb3->fs_u.fs_44.fs_qfmask[1]; + } + return SWAB64(tmp); +} + +#define ufs_get_de_namlen(de) \ + (((flags & UFS_DE_MASK) == UFS_DE_OLD) \ + ? SWAB16(de->d_u.d_namlen) \ + : de->d_u.d_44.d_namlen) + +#define ufs_set_de_namlen(de,value) \ + (((flags & UFS_DE_MASK) == UFS_DE_OLD) \ + ? (de->d_u.d_namlen = SWAB16(value)) \ + : (de->d_u.d_44.d_namlen = value)) + +#define ufs_set_de_type(de,mode) _ufs_set_de_type_(de,mode,flags,swab) +static inline void _ufs_set_de_type_(struct ufs_dir_entry * de, int mode, + unsigned flags, unsigned swab) +{ + if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) { + switch (mode & S_IFMT) { + case S_IFSOCK: de->d_u.d_44.d_type = DT_SOCK; break; + case S_IFLNK: de->d_u.d_44.d_type = DT_LNK; break; + case S_IFREG: de->d_u.d_44.d_type = DT_REG; break; + case S_IFBLK: de->d_u.d_44.d_type = DT_BLK; break; + case S_IFDIR: de->d_u.d_44.d_type = DT_DIR; break; + case S_IFCHR: de->d_u.d_44.d_type = DT_CHR; break; + case S_IFIFO: de->d_u.d_44.d_type = DT_FIFO; break; + default: de->d_u.d_44.d_type = DT_UNKNOWN; + } + } +} + +#define ufs_get_inode_uid(inode) _ufs_get_inode_uid_(inode,flags,swab) +static inline __u32 _ufs_get_inode_uid_(struct ufs_inode * inode, + unsigned flags, unsigned swab) +{ switch (flags & UFS_UID_MASK) { case UFS_UID_EFT: return SWAB32(inode->ui_u3.ui_sun.ui_uid); case UFS_UID_44BSD: return SWAB32(inode->ui_u3.ui_44.ui_uid); - case UFS_UID_OLD: default: return SWAB16(inode->ui_u1.oldids.ui_suid); } } -#define ufs_gid(inode) _ufs_gid_(inode,flags,swab) -static inline __u32 _ufs_gid_(struct ufs_inode * inode, unsigned flags, unsigned swab) { +#define ufs_set_inode_uid(inode,value) _ufs_set_inode_uid_(inode,value,flags,swab) +static inline void _ufs_set_inode_uid_(struct ufs_inode * inode, __u32 value, + unsigned flags, unsigned swab) +{ + inode->ui_u1.oldids.ui_suid = SWAB16(value); + switch (flags & UFS_UID_MASK) { + case UFS_UID_EFT: + inode->ui_u3.ui_sun.ui_uid = SWAB32(value); + break; + case UFS_UID_44BSD: + inode->ui_u3.ui_44.ui_uid = SWAB32(value); + break; + } +} + +#define ufs_get_inode_gid(inode) _ufs_get_inode_gid_(inode,flags,swab) +static inline __u32 _ufs_get_inode_gid_(struct ufs_inode * inode, + unsigned flags, unsigned swab) +{ switch (flags & UFS_UID_MASK) { case UFS_UID_EFT: return SWAB32(inode->ui_u3.ui_sun.ui_gid); case UFS_UID_44BSD: return SWAB32(inode->ui_u3.ui_44.ui_gid); - case UFS_UID_OLD: default: return SWAB16(inode->ui_u1.oldids.ui_sgid); } } -/* - * macros used to avoid needless retyping - */ -#define UCPI_UBH ((struct ufs_buffer_head *)ucpi) -#define USPI_UBH ((struct ufs_buffer_head *)uspi) +#define ufs_set_inode_gid(inode,value) _ufs_set_inode_gid_(inode,value,flags,swab) +static inline void _ufs_set_inode_gid_(struct ufs_inode * inode, __u32 value, + unsigned flags, unsigned swab) +{ + inode->ui_u1.oldids.ui_sgid = SWAB16(value); + switch (flags & UFS_UID_MASK) { + case UFS_UID_EFT: + inode->ui_u3.ui_sun.ui_gid = SWAB32(value); + break; + case UFS_UID_44BSD: + inode->ui_u3.ui_44.ui_gid = SWAB32(value); + break; + } +} + + /* * These functions manipulate ufs buffers */ #define ubh_bread(dev,fragment,size) _ubh_bread_(uspi,dev,fragment,size) extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned); -#define ubh_bread2(dev,fragment,size) _ubh_bread2_(uspi,dev,fragment,size) -extern struct ufs_buffer_head * _ubh_bread2_(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned); +extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned); extern void ubh_brelse (struct ufs_buffer_head *); -extern void ubh_brelse2 (struct ufs_buffer_head *); +extern void ubh_brelse_uspi (struct ufs_sb_private_info *); extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *, int); extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int); extern void ubh_ll_rw_block (int, unsigned, struct ufs_buffer_head **); @@ -98,6 +191,8 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); + + /* * macros to get important structures from ufs_buffer_head */ @@ -115,25 +210,29 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head #define ubh_get_ucg(ubh) \ ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) + /* * Extract byte from ufs_buffer_head * Extract the bits for a block from a map inside ufs_buffer_head */ #define ubh_get_addr8(ubh,begin) \ - ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + ((begin) & ~uspi->s_fmask)) + ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + \ + ((begin) & ~uspi->s_fmask)) #define ubh_get_addr16(ubh,begin) \ - (((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + ((begin) & (uspi->fsize>>1) - 1))) + (((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \ + ((begin) & (uspi->fsize>>1) - 1))) #define ubh_get_addr32(ubh,begin) \ - (((u32*)((ubh)->bh[(begin) >> (BLOCK_SIZE_BITS-2)]->b_data)) + \ - ((begin) & ((BLOCK_SIZE>>2) - 1))) + (((u32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \ + ((begin) & ((uspi->s_fsize>>2) - 1))) #define ubh_get_addr ubh_get_addr8 #define ubh_blkmap(ubh,begin,bit) \ ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb))) + /* * Macros for access to superblock array structures */ @@ -188,45 +287,90 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head #define ubh_isclr(ubh,begin,bit) (!ubh_isset(ubh,begin,bit)) -#define ubh_find_first_zero_bit(ubh,begin,size) \ - _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0) -#define ubh_find_next_zero_bit(ubh,begin,size,offset) \ - _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset) +#define ubh_find_first_zero_bit(ubh,begin,size) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0) +#define ubh_find_next_zero_bit(ubh,begin,size,offset) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset) static inline unsigned _ubh_find_next_zero_bit_( struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned size, unsigned offset) { - unsigned base, rest; + unsigned base, count, pos; + size -= offset; begin <<= 3; - size += begin; offset += begin; - base = offset >> (uspi->s_fshift + 3); - offset &= ((uspi->s_fsize << 3) - 1); + base = offset >> uspi->s_bpfshift; + offset &= uspi->s_bpfmask; for (;;) { - rest = min (size, uspi->s_fsize << 3); - size -= rest; - offset = ext2_find_next_zero_bit (ubh->bh[base]->b_data, rest, offset); - if (offset < rest || !size) + count = min (size + offset, uspi->s_bpf); + size -= count - offset; + pos = ext2_find_next_zero_bit (ubh->bh[base]->b_data, count, offset); + if (pos < count || !size) break; base++; offset = 0; } - return (base << (uspi->s_fshift + 3)) + offset - begin; + return (base << uspi->s_bpfshift) + pos - begin; +} + +static inline unsigned find_last_zero_bit (unsigned char * bitmap, + unsigned size, unsigned offset) +{ + unsigned bit, i; + unsigned char * mapp; + unsigned char map; + + mapp = bitmap + (size >> 3); + map = *mapp--; + bit = 1 << (size & 7); + for (i = size; i > offset; i--) { + if ((map & bit) == 0) + break; + if ((i & 7) != 0) { + bit >>= 1; + } else { + map = *mapp--; + bit = 1 << 7; + } + } + return i; +} + +#define ubh_find_last_zero_bit(ubh,begin,size,offset) _ubh_find_last_zero_bit_(uspi,ubh,begin,size,offset) +static inline unsigned _ubh_find_last_zero_bit_( + struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, + unsigned begin, unsigned start, unsigned end) +{ + unsigned base, count, pos, size; + + size = start - end; + begin <<= 3; + start += begin; + base = start >> uspi->s_bpfshift; + start &= uspi->s_bpfmask; + for (;;) { + count = min (size + (uspi->s_bpf - start), uspi->s_bpf) + - (uspi->s_bpf - start); + size -= count; + pos = find_last_zero_bit (ubh->bh[base]->b_data, + start, start - count); + if (pos > start - count || !size) + break; + base--; + start = uspi->s_bpf; + } + return (base << uspi->s_bpfshift) + pos - begin; } -#define ubh_isblockclear(ubh,begin,block) \ - (!_ubh_isblockset_(uspi,ubh,begin,block)) -#define ubh_isblockset(ubh,begin,block) \ - _ubh_isblockset_(uspi,ubh,begin,block) +#define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block)) +#define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block) static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { switch (uspi->s_fpb) { case 8: - return (*ubh_get_addr (ubh, begin + block) == 0xff); + return (*ubh_get_addr (ubh, begin + block) == 0xff); case 4: return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); case 2: @@ -243,8 +387,8 @@ static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi, { switch (uspi->s_fpb) { case 8: - *ubh_get_addr (ubh, begin + block) = 0x00; - return; + *ubh_get_addr (ubh, begin + block) = 0x00; + return; case 4: *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2)); return; @@ -263,8 +407,8 @@ static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi, { switch (uspi->s_fpb) { case 8: - *ubh_get_addr(ubh, begin + block) = 0xff; - return; + *ubh_get_addr(ubh, begin + block) = 0xff; + return; case 4: *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2)); return; @@ -301,8 +445,7 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap, ADD_SWAB32(fraglist[fragsize], cnt); } -#define ubh_scanc(ubh,begin,size,table,mask) \ - _ubh_scanc_(uspi,ubh,begin,size,table,mask) +#define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask) static inline unsigned _ubh_scanc_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned size, unsigned char * table, unsigned char mask) { -- cgit v1.2.3