summaryrefslogtreecommitdiffstats
path: root/fs/ufs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /fs/ufs
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'fs/ufs')
-rw-r--r--fs/ufs/balloc.c118
-rw-r--r--fs/ufs/cylinder.c11
-rw-r--r--fs/ufs/dir.c22
-rw-r--r--fs/ufs/ialloc.c23
-rw-r--r--fs/ufs/inode.c84
-rw-r--r--fs/ufs/namei.c51
-rw-r--r--fs/ufs/super.c939
-rw-r--r--fs/ufs/symlink.c4
-rw-r--r--fs/ufs/util.c14
-rw-r--r--fs/ufs/util.h263
10 files changed, 930 insertions, 599 deletions
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 <nkbj@image.dk> partially based
* on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
- *
- * write support by Daniel Pirkl <daniel.pirkl@email.cz> 1998
*/
#include <linux/fs.h>
@@ -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,6 +1,35 @@
/*
* linux/fs/ufs/super.c
*
+ * Copyright (C) 1998
+ * Daniel Pirkl <daniel.pirkl@email.cz>
+ * 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
* Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
* Laboratory for Computer Science Research Computing Facility
@@ -28,20 +57,29 @@
*
*/
+
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ufs_fs.h>
-#include <linux/locks.h>
-#include <asm/uaccess.h>
#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
#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)
{