summaryrefslogtreecommitdiffstats
path: root/sys/gnu/ext2fs
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2000-01-01 11:05:19 +0000
committerbde <bde@FreeBSD.org>2000-01-01 11:05:19 +0000
commit0fb3f8eb84d36cf3aa47089037856d4171e8b4ab (patch)
treec6a7a63e438dcc9db0dbf41b870abd1b8997672d /sys/gnu/ext2fs
parent86f1bc4514fdcfd255f37f3218fe234bdc3664fc (diff)
downloadFreeBSD-src-0fb3f8eb84d36cf3aa47089037856d4171e8b4ab.zip
FreeBSD-src-0fb3f8eb84d36cf3aa47089037856d4171e8b4ab.tar.gz
Import the Linux ext2fs files that our GPL'ed ext2fs files seem to be
based on. Obtained from: Linux 1.2.2 distribution
Diffstat (limited to 'sys/gnu/ext2fs')
-rw-r--r--sys/gnu/ext2fs/ext2_bitmap.c26
-rw-r--r--sys/gnu/ext2fs/ext2_fs.h285
-rw-r--r--sys/gnu/ext2fs/ext2_fs_i.h86
-rw-r--r--sys/gnu/ext2fs/ext2_fs_sb.h29
-rw-r--r--sys/gnu/ext2fs/ext2_linux_balloc.c401
-rw-r--r--sys/gnu/ext2fs/ext2_linux_ialloc.c431
-rw-r--r--sys/gnu/ext2fs/ext2_super.c780
7 files changed, 1485 insertions, 553 deletions
diff --git a/sys/gnu/ext2fs/ext2_bitmap.c b/sys/gnu/ext2fs/ext2_bitmap.c
new file mode 100644
index 0000000..8b9b5d2
--- /dev/null
+++ b/sys/gnu/ext2fs/ext2_bitmap.c
@@ -0,0 +1,26 @@
+/*
+ * linux/fs/ext2/bitmap.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)
+ */
+
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+
+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+
+unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
+{
+ unsigned int i;
+ unsigned long sum = 0;
+
+ if (!map)
+ return (0);
+ for (i = 0; i < numchars; i++)
+ sum += nibblemap[map->b_data[i] & 0xf] +
+ nibblemap[(map->b_data[i] >> 4) & 0xf];
+ return (sum);
+}
diff --git a/sys/gnu/ext2fs/ext2_fs.h b/sys/gnu/ext2fs/ext2_fs.h
index 56a8575..1129d1c 100644
--- a/sys/gnu/ext2fs/ext2_fs.h
+++ b/sys/gnu/ext2fs/ext2_fs.h
@@ -1,10 +1,4 @@
/*
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993, 1994, 1995
@@ -18,45 +12,11 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
+
#ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H
-#include <sys/types.h>
-
-#ifdef i386
-#if defined(__FreeBSD__)
-#include <machine/types.h>
-#else
-#include <i386/types.h>
-#endif
-#else
-#error need processor specific types
-#endif
-
-#define __u32 u_int32_t
-#define u32 u_int32_t
-#define __u16 u_int16_t
-#define __u8 u_int8_t
-
-#define __s32 int32_t
-#define __s16 int16_t
-#define __s8 int8_t
-
-#define umode_t mode_t
-#define loff_t off_t
-
-/* the Linux implementation of EXT2 stores some information about
- * an inode in a ext2_inode_info structure which is part of the incore
- * inode in Linux
- * I decided to use the i_spare[11] fields instead - we'll see how this
- * works out
- */
-
-#define i_block_group i_spare[0]
-#define i_next_alloc_block i_spare[1]
-#define i_next_alloc_goal i_spare[2]
-#define i_prealloc_block i_spare[3]
-#define i_prealloc_count i_spare[4]
+#include <linux/types.h>
/*
* The second extended filesystem constants/structures
@@ -96,11 +56,11 @@
/*
* Debug code
*/
-#ifdef EXT2FS_DEBUG
+#ifdef EXT2FS_DEBUG
# define ext2_debug(f, a...) { \
- printf ("EXT2-fs DEBUG (%s, %d): %s:", \
+ printk ("EXT2-fs DEBUG (%s, %d): %s:", \
__FILE__, __LINE__, __FUNCTION__); \
- printf (f, ## a); \
+ printk (f, ## a); \
}
#else
# define ext2_debug(f, a...) /**/
@@ -134,16 +94,19 @@
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
-
-#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
-#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / \
- sizeof (struct ext2_acl_entry))
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
+#else
+# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#endif
+#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
-#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
-
-#define EXT2_INODE_SIZE 128
- /* ought to be sizeof (struct ext2_inode)) */
-#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block)
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->u.ext2_sb.s_es->s_log_block_size + 10)
+#else
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+#endif
+#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_inode))
/*
* Macro-instructions used to manage fragments
@@ -151,8 +114,13 @@
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
-#define EXT2_FRAG_SIZE(s) ((s)->s_frag_size)
-#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+#ifdef __KERNEL__
+# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
+#else
+# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+#endif
/*
* ACL structures
@@ -203,9 +171,15 @@ struct ext2_group_desc
/*
* Macro-instructions used to manage group descriptors
*/
-#define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
-#define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+#ifdef __KERNEL__
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
+# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
+#else
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
+#endif
/*
* Constants relative to the data blocks
@@ -215,7 +189,6 @@ struct ext2_group_desc
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
-#define EXT2_MAXSYMLINKLEN (EXT2_N_BLOCKS * sizeof (__u32))
/*
* Inode flags
@@ -237,6 +210,84 @@ struct ext2_group_desc
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+ __u16 i_mode; /* File mode */
+ __u16 i_uid; /* Owner Uid */
+ __u32 i_size; /* Size in bytes */
+ __u32 i_atime; /* Access time */
+ __u32 i_ctime; /* Creation time */
+ __u32 i_mtime; /* Modification time */
+ __u32 i_dtime; /* Deletion Time */
+ __u16 i_gid; /* Group Id */
+ __u16 i_links_count; /* Links count */
+ __u32 i_blocks; /* Blocks count */
+ __u32 i_flags; /* File flags */
+ union {
+ struct {
+ __u32 l_i_reserved1;
+ } linux1;
+ struct {
+ __u32 h_i_translator;
+ } hurd1;
+ struct {
+ __u32 m_i_reserved1;
+ } masix1;
+ } osd1; /* OS dependent 1 */
+ __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+ __u32 i_version; /* File version (for NFS) */
+ __u32 i_file_acl; /* File ACL */
+ __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_faddr; /* Fragment address */
+ union {
+ struct {
+ __u8 l_i_frag; /* Fragment number */
+ __u8 l_i_fsize; /* Fragment size */
+ __u16 i_pad1;
+ __u32 l_i_reserved2[2];
+ } linux2;
+ struct {
+ __u8 h_i_frag; /* Fragment number */
+ __u8 h_i_fsize; /* Fragment size */
+ __u16 h_i_mode_high;
+ __u16 h_i_uid_high;
+ __u16 h_i_gid_high;
+ __u32 h_i_author;
+ } hurd2;
+ struct {
+ __u8 m_i_frag; /* Fragment number */
+ __u8 m_i_fsize; /* Fragment size */
+ __u16 m_pad1;
+ __u32 m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
+};
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1 osd1.linux1.l_i_reserved1
+#define i_frag osd2.linux2.l_i_frag
+#define i_fsize osd2.linux2.l_i_fsize
+#define i_reserved2 osd2.linux2.l_i_reserved2
+#endif
+
+#ifdef __hurd__
+#define i_translator osd1.hurd1.h_i_translator
+#define i_frag osd2.hurd2.h_i_frag;
+#define i_fsize osd2.hurd2.h_i_fsize;
+#define i_uid_high osd2.hurd2.h_i_uid_high
+#define i_gid_high osd2.hurd2.h_i_gid_high
+#define i_author osd2.hurd2.h_i_author
+#endif
+
+#ifdef __masix__
+#define i_reserved1 osd1.masix1.m_i_reserved1
+#define i_frag osd2.masix2.m_i_frag
+#define i_fsize osd2.masix2.m_i_fsize
+#define i_reserved2 osd2.masix2.m_i_reserved2
+#endif
+
+/*
* File system states
*/
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
@@ -337,4 +388,118 @@ struct ext2_dir_entry {
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
+#ifdef __KERNEL__
+/*
+ * Function prototypes
+ */
+
+/*
+ * Ok, these declarations are also in <linux/kernel.h> but none of the
+ * ext2 source programs needs to include it so they are duplicated here.
+ */
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+# define NORET_TYPE __volatile__
+# define ATTRIB_NORET /**/
+# define NORET_AND /**/
+#else
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
+#endif
+
+/* acl.c */
+extern int ext2_permission (struct inode *, int);
+
+/* balloc.c */
+extern int ext2_new_block (struct super_block *, unsigned long,
+ __u32 *, __u32 *);
+extern void ext2_free_blocks (struct super_block *, unsigned long,
+ unsigned long);
+extern unsigned long ext2_count_free_blocks (struct super_block *);
+extern void ext2_check_blocks_bitmap (struct super_block *);
+
+/* bitmap.c */
+extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
+
+/* dir.c */
+extern int ext2_check_dir_entry (char *, struct inode *,
+ struct ext2_dir_entry *, struct buffer_head *,
+ unsigned long);
+
+/* file.c */
+extern int ext2_read (struct inode *, struct file *, char *, int);
+extern int ext2_write (struct inode *, struct file *, char *, int);
+
+/* fsync.c */
+extern int ext2_sync_file (struct inode *, struct file *);
+
+/* ialloc.c */
+extern struct inode * ext2_new_inode (const struct inode *, int);
+extern void ext2_free_inode (struct inode *);
+extern unsigned long ext2_count_free_inodes (struct super_block *);
+extern void ext2_check_inodes_bitmap (struct super_block *);
+
+/* inode.c */
+extern int ext2_bmap (struct inode *, int);
+
+extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
+extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
+
+extern int ext2_getcluster (struct inode * inode, long block);
+extern void ext2_read_inode (struct inode *);
+extern void ext2_write_inode (struct inode *);
+extern void ext2_put_inode (struct inode *);
+extern int ext2_sync_inode (struct inode *);
+extern void ext2_discard_prealloc (struct inode *);
+
+/* ioctl.c */
+extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+/* namei.c */
+extern void ext2_release (struct inode *, struct file *);
+extern int ext2_lookup (struct inode *,const char *, int, struct inode **);
+extern int ext2_create (struct inode *,const char *, int, int,
+ struct inode **);
+extern int ext2_mkdir (struct inode *, const char *, int, int);
+extern int ext2_rmdir (struct inode *, const char *, int);
+extern int ext2_unlink (struct inode *, const char *, int);
+extern int ext2_symlink (struct inode *, const char *, int, const char *);
+extern int ext2_link (struct inode *, struct inode *, const char *, int);
+extern int ext2_mknod (struct inode *, const char *, int, int, int);
+extern int ext2_rename (struct inode *, const char *, int,
+ struct inode *, const char *, int);
+
+/* super.c */
+extern void ext2_error (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
+ const char *, ...)
+ __attribute__ ((NORET_AND format (printf, 3, 4)));
+extern void ext2_warning (struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern void ext2_put_super (struct super_block *);
+extern void ext2_write_super (struct super_block *);
+extern int ext2_remount (struct super_block *, int *, char *);
+extern struct super_block * ext2_read_super (struct super_block *,void *,int);
+extern void ext2_statfs (struct super_block *, struct statfs *);
+
+/* truncate.c */
+extern void ext2_truncate (struct inode *);
+
+/*
+ * Inodes and files operations
+ */
+
+/* dir.c */
+extern struct inode_operations ext2_dir_inode_operations;
+
+/* file.c */
+extern struct inode_operations ext2_file_inode_operations;
+
+/* symlink.c */
+extern struct inode_operations ext2_symlink_inode_operations;
+
+#endif /* __KERNEL__ */
+
#endif /* _LINUX_EXT2_FS_H */
diff --git a/sys/gnu/ext2fs/ext2_fs_i.h b/sys/gnu/ext2fs/ext2_fs_i.h
index 800b2d4..f3eca44 100644
--- a/sys/gnu/ext2fs/ext2_fs_i.h
+++ b/sys/gnu/ext2fs/ext2_fs_i.h
@@ -1,16 +1,4 @@
/*
- * added for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- *
- * Note that this started out to be ext2_fs_i.h. In reality it
- * doesn't have anything to do with. I put the declaration of
- * the on disk ext2 format here from ext2_fs.h because this is
- * something that would name clash with other stuff.
- * This is used only in ext2_inode_cnv.c
- */
-/*
* linux/include/linux/ext2_fs_i.h
*
* Copyright (C) 1992, 1993, 1994, 1995
@@ -25,62 +13,28 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
-#ifndef _EXT2_FS_I
-#define _EXT2_FS_I
+#ifndef _LINUX_EXT2_FS_I
+#define _LINUX_EXT2_FS_I
/*
- * Structure of an inode on the disk
+ * second extended file system inode data in memory
*/
-struct ext2_inode {
- __u16 i_mode; /* File mode */
- __u16 i_uid; /* Owner Uid */
- __u32 i_size; /* Size in bytes */
- __u32 i_atime; /* Access time */
- __u32 i_ctime; /* Creation time */
- __u32 i_mtime; /* Modification time */
- __u32 i_dtime; /* Deletion Time */
- __u16 i_gid; /* Group Id */
- __u16 i_links_count; /* Links count */
- __u32 i_blocks; /* Blocks count */
- __u32 i_flags; /* File flags */
- union {
- struct {
- __u32 l_i_reserved1;
- } linux1;
- struct {
- __u32 h_i_translator;
- } hurd1;
- struct {
- __u32 m_i_reserved1;
- } masix1;
- } osd1; /* OS dependent 1 */
- __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
- __u32 i_version; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
- __u32 i_faddr; /* Fragment address */
- union {
- struct {
- __u8 l_i_frag; /* Fragment number */
- __u8 l_i_fsize; /* Fragment size */
- __u16 i_pad1;
- __u32 l_i_reserved2[2];
- } linux2;
- struct {
- __u8 h_i_frag; /* Fragment number */
- __u8 h_i_fsize; /* Fragment size */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
- __u32 h_i_author;
- } hurd2;
- struct {
- __u8 m_i_frag; /* Fragment number */
- __u8 m_i_fsize; /* Fragment size */
- __u16 m_pad1;
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
+struct ext2_inode_info {
+ __u32 i_data[15];
+ __u32 i_flags;
+ __u32 i_faddr;
+ __u8 i_frag_no;
+ __u8 i_frag_size;
+ __u16 i_osync;
+ __u32 i_file_acl;
+ __u32 i_dir_acl;
+ __u32 i_dtime;
+ __u32 i_version;
+ __u32 i_block_group;
+ __u32 i_next_alloc_block;
+ __u32 i_next_alloc_goal;
+ __u32 i_prealloc_block;
+ __u32 i_prealloc_count;
};
-#endif /* _EXT2_FS_I */
+#endif /* _LINUX_EXT2_FS_I */
diff --git a/sys/gnu/ext2fs/ext2_fs_sb.h b/sys/gnu/ext2fs/ext2_fs_sb.h
index f475ce2..685efeb 100644
--- a/sys/gnu/ext2fs/ext2_fs_sb.h
+++ b/sys/gnu/ext2fs/ext2_fs_sb.h
@@ -1,10 +1,4 @@
/*
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*
* linux/include/linux/ext2_fs_sb.h
*
* Copyright (C) 1992, 1993, 1994, 1995
@@ -30,11 +24,6 @@
#define EXT2_MAX_GROUP_LOADED 8
-#if defined(LITES) || defined(__FreeBSD__)
-#define buffer_head buf
-#define MAXMNTLEN 512
-#endif
-
/*
* second extended-fs super-block data in memory
*/
@@ -59,29 +48,11 @@ struct ext2_sb_info {
unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED];
struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
int s_rename_lock;
-#if !defined(LITES) && !defined(__FreeBSD__)
struct wait_queue * s_rename_wait;
-#endif
unsigned long s_mount_opt;
unsigned short s_resuid;
unsigned short s_resgid;
unsigned short s_mount_state;
-#if defined(LITES) || defined(__FreeBSD__)
- /*
- stuff that FFS keeps in its super block or that linux
- has in its non-ext2 specific super block and which is
- generally considered useful
- */
- unsigned long s_blocksize;
- unsigned long s_blocksize_bits;
- unsigned int s_bshift; /* = log2(s_blocksize) */
- quad_t s_qbmask; /* = s_blocksize - 1 */
- unsigned int s_fsbtodb; /* shift to get disk block */
- char s_rd_only; /* read-only */
- char s_dirt; /* fs modified flag */
-
- char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
-#endif
};
#endif /* _LINUX_EXT2_FS_SB */
diff --git a/sys/gnu/ext2fs/ext2_linux_balloc.c b/sys/gnu/ext2fs/ext2_linux_balloc.c
index 25b9891..c476fa2 100644
--- a/sys/gnu/ext2fs/ext2_linux_balloc.c
+++ b/sys/gnu/ext2fs/ext2_linux_balloc.c
@@ -1,10 +1,4 @@
/*
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*
* linux/fs/ext2/balloc.c
*
* Copyright (C) 1992, 1993, 1994, 1995
@@ -16,6 +10,10 @@
*/
/*
+ * balloc.c contains the blocks allocation and deallocation routines
+ */
+
+/*
* The free blocks are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
@@ -26,53 +24,61 @@
* when a file system is mounted (see ext2_read_super).
*/
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/ufsmount.h>
-#include <gnu/ext2fs/ext2_extern.h>
-#include <gnu/ext2fs/ext2_fs.h>
-#include <gnu/ext2fs/ext2_fs_sb.h>
-#include <gnu/ext2fs/fs.h>
-#include <sys/stat.h>
-
-#ifdef i386
-#include <gnu/ext2fs/i386-bitops.h>
-#else
-#error Provide an bitops.h file, please !
-#endif
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/locks.h>
-unsigned long ext2_count_free __P((struct buffer_head *, unsigned int));
+#include <asm/bitops.h>
#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
-/* got rid of get_group_desc since it can already be found in
- * ext2_linux_ialloc.c
- */
+static struct ext2_group_desc * get_group_desc (struct super_block * sb,
+ unsigned int block_group,
+ struct buffer_head ** bh)
+{
+ unsigned long group_desc;
+ unsigned long desc;
+ struct ext2_group_desc * gdp;
+
+ if (block_group >= sb->u.ext2_sb.s_groups_count)
+ ext2_panic (sb, "get_group_desc",
+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %lu",
+ block_group, sb->u.ext2_sb.s_groups_count);
+
+ group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
+ desc = block_group % EXT2_DESC_PER_BLOCK(sb);
+ if (!sb->u.ext2_sb.s_group_desc[group_desc])
+ ext2_panic (sb, "get_group_desc",
+ "Group descriptor not loaded - "
+ "block_group = %d, group_desc = %lu, desc = %lu",
+ block_group, group_desc, desc);
+ gdp = (struct ext2_group_desc *)
+ sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
+ if (bh)
+ *bh = sb->u.ext2_sb.s_group_desc[group_desc];
+ return gdp + desc;
+}
-static void read_block_bitmap (struct mount * mp,
+static void read_block_bitmap (struct super_block * sb,
unsigned int block_group,
unsigned long bitmap_nr)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
- int error;
- gdp = get_group_desc (mp, block_group, NULL);
- if(error = bread (VFSTOUFS(mp)->um_devvp,
- fsbtodb(sb, gdp->bg_block_bitmap),sb->s_blocksize, NOCRED, &bh))
- panic ( "read_block_bitmap: "
+ gdp = get_group_desc (sb, block_group, NULL);
+ bh = bread (sb->s_dev, gdp->bg_block_bitmap, sb->s_blocksize);
+ if (!bh)
+ ext2_panic (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %lu",
block_group, (unsigned long) gdp->bg_block_bitmap);
- sb->s_block_bitmap_number[bitmap_nr] = block_group;
- sb->s_block_bitmap[bitmap_nr] = bh;
+ sb->u.ext2_sb.s_block_bitmap_number[bitmap_nr] = block_group;
+ sb->u.ext2_sb.s_block_bitmap[bitmap_nr] = bh;
}
/*
@@ -86,86 +92,82 @@ static void read_block_bitmap (struct mount * mp,
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*/
-static int load__block_bitmap (struct mount * mp,
+static int load__block_bitmap (struct super_block * sb,
unsigned int block_group)
{
int i, j;
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
unsigned long block_bitmap_number;
struct buffer_head * block_bitmap;
- int error;
- if (block_group >= sb->s_groups_count)
- panic ( "load_block_bitmap: "
+ if (block_group >= sb->u.ext2_sb.s_groups_count)
+ ext2_panic (sb, "load_block_bitmap",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, sb->s_groups_count);
+ block_group, sb->u.ext2_sb.s_groups_count);
- if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
- if (sb->s_block_bitmap[block_group]) {
- if (sb->s_block_bitmap_number[block_group] !=
+ if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
+ if (sb->u.ext2_sb.s_block_bitmap[block_group]) {
+ if (sb->u.ext2_sb.s_block_bitmap_number[block_group] !=
block_group)
- panic ( "load_block_bitmap: "
+ ext2_panic (sb, "load_block_bitmap",
"block_group != block_bitmap_number");
else
return block_group;
} else {
- read_block_bitmap (mp, block_group, block_group);
+ read_block_bitmap (sb, block_group, block_group);
return block_group;
}
}
- for (i = 0; i < sb->s_loaded_block_bitmaps &&
- sb->s_block_bitmap_number[i] != block_group; i++)
+ for (i = 0; i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
+ sb->u.ext2_sb.s_block_bitmap_number[i] != block_group; i++)
;
- if (i < sb->s_loaded_block_bitmaps &&
- sb->s_block_bitmap_number[i] == block_group) {
- block_bitmap_number = sb->s_block_bitmap_number[i];
- block_bitmap = sb->s_block_bitmap[i];
+ if (i < sb->u.ext2_sb.s_loaded_block_bitmaps &&
+ sb->u.ext2_sb.s_block_bitmap_number[i] == block_group) {
+ block_bitmap_number = sb->u.ext2_sb.s_block_bitmap_number[i];
+ block_bitmap = sb->u.ext2_sb.s_block_bitmap[i];
for (j = i; j > 0; j--) {
- sb->s_block_bitmap_number[j] =
- sb->s_block_bitmap_number[j - 1];
- sb->s_block_bitmap[j] =
- sb->s_block_bitmap[j - 1];
+ sb->u.ext2_sb.s_block_bitmap_number[j] =
+ sb->u.ext2_sb.s_block_bitmap_number[j - 1];
+ sb->u.ext2_sb.s_block_bitmap[j] =
+ sb->u.ext2_sb.s_block_bitmap[j - 1];
}
- sb->s_block_bitmap_number[0] = block_bitmap_number;
- sb->s_block_bitmap[0] = block_bitmap;
+ sb->u.ext2_sb.s_block_bitmap_number[0] = block_bitmap_number;
+ sb->u.ext2_sb.s_block_bitmap[0] = block_bitmap;
} else {
- if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
- sb->s_loaded_block_bitmaps++;
+ if (sb->u.ext2_sb.s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
+ sb->u.ext2_sb.s_loaded_block_bitmaps++;
else
- brelse (sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
- for (j = sb->s_loaded_block_bitmaps - 1; j > 0; j--) {
- sb->s_block_bitmap_number[j] =
- sb->s_block_bitmap_number[j - 1];
- sb->s_block_bitmap[j] =
- sb->s_block_bitmap[j - 1];
+ brelse (sb->u.ext2_sb.s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
+ for (j = sb->u.ext2_sb.s_loaded_block_bitmaps - 1; j > 0; j--) {
+ sb->u.ext2_sb.s_block_bitmap_number[j] =
+ sb->u.ext2_sb.s_block_bitmap_number[j - 1];
+ sb->u.ext2_sb.s_block_bitmap[j] =
+ sb->u.ext2_sb.s_block_bitmap[j - 1];
}
- read_block_bitmap (mp, block_group, 0);
+ read_block_bitmap (sb, block_group, 0);
}
return 0;
}
-static inline int load_block_bitmap (struct mount * mp,
+static inline int load_block_bitmap (struct super_block * sb,
unsigned int block_group)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
- if (sb->s_loaded_block_bitmaps > 0 &&
- sb->s_block_bitmap_number[0] == block_group)
+ if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
+ sb->u.ext2_sb.s_block_bitmap_number[0] == block_group)
return 0;
- if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED &&
- sb->s_block_bitmap_number[block_group] == block_group &&
- sb->s_block_bitmap[block_group])
+ if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED &&
+ sb->u.ext2_sb.s_block_bitmap_number[block_group] == block_group &&
+ sb->u.ext2_sb.s_block_bitmap[block_group])
return block_group;
- return load__block_bitmap (mp, block_group);
+ return load__block_bitmap (sb, block_group);
}
-void ext2_free_blocks (struct mount * mp, unsigned long block,
+void ext2_free_blocks (struct super_block * sb, unsigned long block,
unsigned long count)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
unsigned long block_group;
@@ -173,51 +175,52 @@ void ext2_free_blocks (struct mount * mp, unsigned long block,
unsigned long i;
int bitmap_nr;
struct ext2_group_desc * gdp;
- struct ext2_super_block * es = sb->s_es;
+ struct ext2_super_block * es;
if (!sb) {
- printf ("ext2_free_blocks: nonexistent device");
+ printk ("ext2_free_blocks: nonexistent device");
return;
}
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
if (block < es->s_first_data_block ||
(block + count) > es->s_blocks_count) {
- printf ( "ext2_free_blocks: "
+ ext2_error (sb, "ext2_free_blocks",
"Freeing blocks not in datazone - "
"block = %lu, count = %lu", block, count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
return;
}
- ext2_debug ("freeing blocks %lu to %lu\n", block, block+count-1);
+ ext2_debug ("freeing block %lu\n", block);
block_group = (block - es->s_first_data_block) /
EXT2_BLOCKS_PER_GROUP(sb);
bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
- panic ( "ext2_free_blocks: "
+ ext2_panic (sb, "ext2_free_blocks",
"Freeing blocks across group boundary - "
"Block = %lu, count = %lu",
block, count);
- bitmap_nr = load_block_bitmap (mp, block_group);
- bh = sb->s_block_bitmap[bitmap_nr];
- gdp = get_group_desc (mp, block_group, &bh2);
+ bitmap_nr = load_block_bitmap (sb, block_group);
+ bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
+ gdp = get_group_desc (sb, block_group, &bh2);
- if (/* test_opt (sb, CHECK_STRICT) && assume always strict ! */
+ if (test_opt (sb, CHECK_STRICT) &&
(in_range (gdp->bg_block_bitmap, block, count) ||
in_range (gdp->bg_inode_bitmap, block, count) ||
in_range (block, gdp->bg_inode_table,
- sb->s_itb_per_group) ||
+ sb->u.ext2_sb.s_itb_per_group) ||
in_range (block + count - 1, gdp->bg_inode_table,
- sb->s_itb_per_group)))
- panic ( "ext2_free_blocks: "
+ sb->u.ext2_sb.s_itb_per_group)))
+ ext2_panic (sb, "ext2_free_blocks",
"Freeing blocks in system zones - "
"Block = %lu, count = %lu",
block, count);
for (i = 0; i < count; i++) {
if (!clear_bit (bit + i, bh->b_data))
- printf ("ext2_free_blocks: "
+ ext2_warning (sb, "ext2_free_blocks",
"bit already cleared for block %lu",
block);
else {
@@ -225,17 +228,17 @@ void ext2_free_blocks (struct mount * mp, unsigned long block,
es->s_free_blocks_count++;
}
}
+
+ mark_buffer_dirty(bh2, 1);
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
- mark_buffer_dirty(bh2);
mark_buffer_dirty(bh, 1);
-/****
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
-****/
sb->s_dirt = 1;
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
return;
}
@@ -246,29 +249,37 @@ void ext2_free_blocks (struct mount * mp, unsigned long block,
* each block group the search first looks for an entire free byte in the block
* bitmap, and then for any free bit if that fails.
*/
-int ext2_new_block (struct mount * mp, unsigned long goal,
- long * prealloc_count,
- long * prealloc_block)
+int ext2_new_block (struct super_block * sb, unsigned long goal,
+ u32 * prealloc_count,
+ u32 * prealloc_block)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
char * p, * r;
int i, j, k, tmp;
+ unsigned long lmap;
int bitmap_nr;
struct ext2_group_desc * gdp;
- struct ext2_super_block * es = sb->s_es;
+ struct ext2_super_block * es;
#ifdef EXT2FS_DEBUG
static int goal_hits = 0, goal_attempts = 0;
#endif
if (!sb) {
- printf ("ext2_new_block: nonexistent device");
+ printk ("ext2_new_block: nonexistent device");
+ return 0;
+ }
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
+ if (es->s_free_blocks_count <= es->s_r_blocks_count &&
+ (!fsuser() && (sb->u.ext2_sb.s_resuid != current->fsuid) &&
+ (sb->u.ext2_sb.s_resgid == 0 ||
+ !in_group_p (sb->u.ext2_sb.s_resgid)))) {
+ unlock_super (sb);
return 0;
}
- lock_super (VFSTOUFS(mp)->um_devvp);
- ext2_debug ("goal=%lu.\n", goal);
+ ext2_debug ("goal=%lu.\n", goal);
repeat:
/*
@@ -277,17 +288,17 @@ repeat:
if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
goal = es->s_first_data_block;
i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
- gdp = get_group_desc (mp, i, &bh2);
+ gdp = get_group_desc (sb, i, &bh2);
if (gdp->bg_free_blocks_count > 0) {
j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
#ifdef EXT2FS_DEBUG
if (j)
goal_attempts++;
#endif
- bitmap_nr = load_block_bitmap (mp, i);
- bh = sb->s_block_bitmap[bitmap_nr];
+ bitmap_nr = load_block_bitmap (sb, i);
+ bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
- ext2_debug ("goal is at %d:%d.\n", i, j);
+ ext2_debug ("goal is at %d:%d.\n", i, j);
if (!test_bit(j, bh->b_data)) {
#ifdef EXT2FS_DEBUG
@@ -299,16 +310,22 @@ repeat:
if (j) {
/*
* The goal was occupied; search forward for a free
- * block within the next XX blocks.
- *
- * end_goal is more or less random, but it has to be
- * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
- * next 64-bit boundary is simple..
+ * block within the next 32 blocks
*/
- int end_goal = (j + 63) & ~63;
- j = find_next_zero_bit(bh->b_data, end_goal, j);
- if (j < end_goal)
- goto got_block;
+ lmap = ((((unsigned long *) bh->b_data)[j >> 5]) >>
+ ((j & 31) + 1));
+ if (j < EXT2_BLOCKS_PER_GROUP(sb) - 32)
+ lmap |= (((unsigned long *) bh->b_data)[(j >> 5) + 1]) <<
+ (31 - (j & 31));
+ else
+ lmap |= 0xffffffff << (31 - (j & 31));
+ if (lmap != 0xffffffffl) {
+ k = ffz(lmap) + 1;
+ if ((j + k) < EXT2_BLOCKS_PER_GROUP(sb)) {
+ j += k;
+ goto got_block;
+ }
+ }
}
ext2_debug ("Bit not found near goal\n");
@@ -338,38 +355,37 @@ repeat:
}
}
- ext2_debug ("Bit not found in block group %d.\n", i);
+ ext2_debug ("Bit not found in block group %d.\n", i);
/*
* Now search the rest of the groups. We assume that
* i and gdp correctly point to the last group visited.
*/
- for (k = 0; k < sb->s_groups_count; k++) {
+ for (k = 0; k < sb->u.ext2_sb.s_groups_count; k++) {
i++;
- if (i >= sb->s_groups_count)
+ if (i >= sb->u.ext2_sb.s_groups_count)
i = 0;
- gdp = get_group_desc (mp, i, &bh2);
+ gdp = get_group_desc (sb, i, &bh2);
if (gdp->bg_free_blocks_count > 0)
break;
}
- if (k >= sb->s_groups_count) {
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ if (k >= sb->u.ext2_sb.s_groups_count) {
+ unlock_super (sb);
return 0;
}
- bitmap_nr = load_block_bitmap (mp, i);
- bh = sb->s_block_bitmap[bitmap_nr];
+ bitmap_nr = load_block_bitmap (sb, i);
+ bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
j = (r - bh->b_data) << 3;
-
if (j < EXT2_BLOCKS_PER_GROUP(sb))
goto search_back;
else
j = find_first_zero_bit ((unsigned long *) bh->b_data,
EXT2_BLOCKS_PER_GROUP(sb));
if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
- printf ( "ext2_new_block: "
- "Free blocks count corrupted for block group %d", i);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ ext2_error (sb, "ext2_new_block",
+ "Free blocks count corrupted for block group %d", i);
+ unlock_super (sb);
return 0;
}
@@ -387,17 +403,17 @@ got_block:
tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + es->s_first_data_block;
- if (/* test_opt (sb, CHECK_STRICT) && we are always strict. */
+ if (test_opt (sb, CHECK_STRICT) &&
(tmp == gdp->bg_block_bitmap ||
tmp == gdp->bg_inode_bitmap ||
- in_range (tmp, gdp->bg_inode_table, sb->s_itb_per_group)))
- panic ( "ext2_new_block: "
+ in_range (tmp, gdp->bg_inode_table, sb->u.ext2_sb.s_itb_per_group)))
+ ext2_panic (sb, "ext2_new_block",
"Allocating block in system zone - "
- "%dth block = %u in group %u", j, tmp, i);
+ "block = %u", tmp);
if (set_bit (j, bh->b_data)) {
- printf ( "ext2_new_block: "
- "bit already set for block %d", j);
+ ext2_warning (sb, "ext2_new_block",
+ "bit already set for block %d", j);
goto repeat;
}
@@ -419,26 +435,34 @@ got_block:
gdp->bg_free_blocks_count -= *prealloc_count;
es->s_free_blocks_count -= *prealloc_count;
ext2_debug ("Preallocated a further %lu bits.\n",
- *prealloc_count);
+ *prealloc_count);
}
#endif
j = tmp;
- mark_buffer_dirty(bh);
-/****
+ mark_buffer_dirty(bh, 1);
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
-****/
+
if (j >= es->s_blocks_count) {
- printf ( "ext2_new_block: "
+ ext2_error (sb, "ext2_new_block",
"block >= blocks count - "
"block_group = %d, block=%d", i, j);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
+ return 0;
+ }
+ if (!(bh = getblk (sb->s_dev, j, sb->s_blocksize))) {
+ ext2_error (sb, "ext2_new_block", "cannot get block %d", j);
+ unlock_super (sb);
return 0;
}
+ memset(bh->b_data, 0, sb->s_blocksize);
+ bh->b_uptodate = 1;
+ mark_buffer_dirty(bh, 1);
+ brelse (bh);
ext2_debug ("allocating block %d. "
"Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
@@ -446,14 +470,14 @@ got_block:
gdp->bg_free_blocks_count--;
mark_buffer_dirty(bh2, 1);
es->s_free_blocks_count--;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
return j;
}
-unsigned long ext2_count_free_blocks (struct mount * mp)
+unsigned long ext2_count_free_blocks (struct super_block * sb)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
#ifdef EXT2FS_DEBUG
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
@@ -461,42 +485,40 @@ unsigned long ext2_count_free_blocks (struct mount * mp)
struct ext2_group_desc * gdp;
int i;
- lock_super (VFSTOUFS(mp)->um_devvp);
- es = sb->s_es;
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
- for (i = 0; i < sb->s_groups_count; i++) {
- gdp = get_group_desc (mp, i, NULL);
+ for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
+ gdp = get_group_desc (sb, i, NULL);
desc_count += gdp->bg_free_blocks_count;
- bitmap_nr = load_block_bitmap (mp, i);
- x = ext2_count_free (sb->s_block_bitmap[bitmap_nr],
+ bitmap_nr = load_block_bitmap (sb, i);
+ x = ext2_count_free (sb->u.ext2_sb.s_block_bitmap[bitmap_nr],
sb->s_blocksize);
- ext2_debug ("group %d: stored = %d, counted = %lu\n",
+ printk ("group %d: stored = %d, counted = %lu\n",
i, gdp->bg_free_blocks_count, x);
bitmap_count += x;
}
- ext2_debug( "stored = %lu, computed = %lu, %lu\n",
+ printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
es->s_free_blocks_count, desc_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
return bitmap_count;
#else
- return sb->s_es->s_free_blocks_count;
+ return sb->u.ext2_sb.s_es->s_free_blocks_count;
#endif
}
-
static inline int block_in_use (unsigned long block,
- struct ext2_sb_info * sb,
+ struct super_block * sb,
unsigned char * map)
{
- return test_bit ((block - sb->s_es->s_first_data_block) %
+ return test_bit ((block - sb->u.ext2_sb.s_es->s_first_data_block) %
EXT2_BLOCKS_PER_GROUP(sb), map);
}
-void ext2_check_blocks_bitmap (struct mount * mp)
+void ext2_check_blocks_bitmap (struct super_block * sb)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct buffer_head * bh;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
@@ -505,78 +527,57 @@ void ext2_check_blocks_bitmap (struct mount * mp)
struct ext2_group_desc * gdp;
int i, j;
- lock_super (VFSTOUFS(mp)->um_devvp);
- es = sb->s_es;
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
- desc_blocks = (sb->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
+ desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
- for (i = 0; i < sb->s_groups_count; i++) {
- gdp = get_group_desc (mp, i, NULL);
+ for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
+ gdp = get_group_desc (sb, i, NULL);
desc_count += gdp->bg_free_blocks_count;
- bitmap_nr = load_block_bitmap (mp, i);
- bh = sb->s_block_bitmap[bitmap_nr];
+ bitmap_nr = load_block_bitmap (sb, i);
+ bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
if (!test_bit (0, bh->b_data))
- printf ( "ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Superblock in group %d is marked free", i);
for (j = 0; j < desc_blocks; j++)
if (!test_bit (j + 1, bh->b_data))
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Descriptor block #%d in group "
"%d is marked free", j, i);
if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Block bitmap for group %d is marked free",
i);
if (!block_in_use (gdp->bg_inode_bitmap, sb, bh->b_data))
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Inode bitmap for group %d is marked free",
i);
- for (j = 0; j < sb->s_itb_per_group; j++)
+ for (j = 0; j < sb->u.ext2_sb.s_itb_per_group; j++)
if (!block_in_use (gdp->bg_inode_table + j, sb, bh->b_data))
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Block #%d of the inode table in "
"group %d is marked free", j, i);
x = ext2_count_free (bh, sb->s_blocksize);
if (gdp->bg_free_blocks_count != x)
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Wrong free blocks count for group %d, "
"stored = %d, counted = %lu", i,
gdp->bg_free_blocks_count, x);
bitmap_count += x;
}
if (es->s_free_blocks_count != bitmap_count)
- printf ("ext2_check_blocks_bitmap: "
+ ext2_error (sb, "ext2_check_blocks_bitmap",
"Wrong free blocks count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) es->s_free_blocks_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
}
-
-/*
- * this function is taken from
- * linux/fs/ext2/bitmap.c
- */
-
-static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
-
-unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
-{
- unsigned int i;
- unsigned long sum = 0;
-
- if (!map)
- return (0);
- for (i = 0; i < numchars; i++)
- sum += nibblemap[map->b_data[i] & 0xf] +
- nibblemap[(map->b_data[i] >> 4) & 0xf];
- return (sum);
-}
-
diff --git a/sys/gnu/ext2fs/ext2_linux_ialloc.c b/sys/gnu/ext2fs/ext2_linux_ialloc.c
index 62e7938..9102d02 100644
--- a/sys/gnu/ext2fs/ext2_linux_ialloc.c
+++ b/sys/gnu/ext2fs/ext2_linux_ialloc.c
@@ -1,10 +1,4 @@
/*
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*
* linux/fs/ext2/ialloc.c
*
* Copyright (C) 1992, 1993, 1994, 1995
@@ -17,6 +11,10 @@
*/
/*
+ * ialloc.c contains the inodes allocation and deallocation routines
+ */
+
+/*
* The free inodes are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
@@ -27,99 +25,59 @@
* when a file system is mounted (see ext2_read_super).
*/
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/ufsmount.h>
-#include <gnu/ext2fs/ext2_fs.h>
-#include <gnu/ext2fs/ext2_fs_sb.h>
-#include <gnu/ext2fs/fs.h>
-#include <sys/stat.h>
-
-#if (i386)
-#include <gnu/ext2fs/i386-bitops.h>
-#else
-#error please provide bit operation functions
-#endif
-
-/* this is supposed to mark a buffer dirty on ready for delayed writing
- */
-void mark_buffer_dirty(struct buf *bh)
-{
- bh->b_flags |= B_DELWRI;
- bh->b_flags &= ~(B_READ | B_ERROR);
-}
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
-/*
- this should write a buffer immediately w/o releasing it
- */
-int ll_w_block(struct buf * bp, int waitfor)
-{
- bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
- bp->b_flags |= B_WRITEINPROG;
- bp->b_vp->v_numoutput++;
-#if defined(__FreeBSD__)
- vfs_busy_pages(bp, 1);
-#endif
- VOP_STRATEGY(bp);
- return waitfor ? biowait(bp) : 0;
-}
+#include <asm/bitops.h>
-struct ext2_group_desc * get_group_desc (struct mount * mp,
+static struct ext2_group_desc * get_group_desc (struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
unsigned long group_desc;
unsigned long desc;
struct ext2_group_desc * gdp;
- if (block_group >= sb->s_groups_count)
- panic ("get_group_desc: "
+ if (block_group >= sb->u.ext2_sb.s_groups_count)
+ ext2_panic (sb, "get_group_desc",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, sb->s_groups_count);
+ block_group, sb->u.ext2_sb.s_groups_count);
group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
desc = block_group % EXT2_DESC_PER_BLOCK(sb);
- if (!sb->s_group_desc[group_desc])
- panic ( "get_group_desc:"
+ if (!sb->u.ext2_sb.s_group_desc[group_desc])
+ ext2_panic (sb, "get_group_desc",
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
block_group, group_desc, desc);
gdp = (struct ext2_group_desc *)
- sb->s_group_desc[group_desc]->b_data;
+ sb->u.ext2_sb.s_group_desc[group_desc]->b_data;
if (bh)
- *bh = sb->s_group_desc[group_desc];
+ *bh = sb->u.ext2_sb.s_group_desc[group_desc];
return gdp + desc;
}
-static void read_inode_bitmap (struct mount * mp,
+static void read_inode_bitmap (struct super_block * sb,
unsigned long block_group,
unsigned int bitmap_nr)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
- int error;
- gdp = get_group_desc (mp, block_group, NULL);
- if (error = bread (VFSTOUFS(mp)->um_devvp,
- fsbtodb(sb, gdp->bg_inode_bitmap),
- sb->s_blocksize,
- NOCRED, &bh))
- panic ( "read_inode_bitmap:"
+ gdp = get_group_desc (sb, block_group, NULL);
+ bh = bread (sb->s_dev, gdp->bg_inode_bitmap, sb->s_blocksize);
+ if (!bh)
+ ext2_panic (sb, "read_inode_bitmap",
"Cannot read inode bitmap - "
"block_group = %lu, inode_bitmap = %lu",
block_group, (unsigned long) gdp->bg_inode_bitmap);
- sb->s_inode_bitmap_number[bitmap_nr] = block_group;
- sb->s_inode_bitmap[bitmap_nr] = bh;
+ sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
+ sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
}
/*
@@ -133,72 +91,104 @@ static void read_inode_bitmap (struct mount * mp,
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*/
-static int load_inode_bitmap (struct mount * mp,
+static int load_inode_bitmap (struct super_block * sb,
unsigned int block_group)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
int i, j;
unsigned long inode_bitmap_number;
struct buffer_head * inode_bitmap;
- if (block_group >= sb->s_groups_count)
- panic ("load_inode_bitmap:"
+ if (block_group >= sb->u.ext2_sb.s_groups_count)
+ ext2_panic (sb, "load_inode_bitmap",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, sb->s_groups_count);
- if (sb->s_loaded_inode_bitmaps > 0 &&
- sb->s_inode_bitmap_number[0] == block_group)
+ block_group, sb->u.ext2_sb.s_groups_count);
+ if (sb->u.ext2_sb.s_loaded_inode_bitmaps > 0 &&
+ sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group)
return 0;
- if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
- if (sb->s_inode_bitmap[block_group]) {
- if (sb->s_inode_bitmap_number[block_group] !=
- block_group)
- panic ( "load_inode_bitmap:"
- "block_group != inode_bitmap_number");
+ if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
+ if (sb->u.ext2_sb.s_inode_bitmap[block_group]) {
+ if (sb->u.ext2_sb.s_inode_bitmap_number[block_group] != block_group)
+ ext2_panic (sb, "load_inode_bitmap",
+ "block_group != inode_bitmap_number");
else
return block_group;
} else {
- read_inode_bitmap (mp, block_group, block_group);
+ read_inode_bitmap (sb, block_group, block_group);
return block_group;
}
}
- for (i = 0; i < sb->s_loaded_inode_bitmaps &&
- sb->s_inode_bitmap_number[i] != block_group;
+ for (i = 0; i < sb->u.ext2_sb.s_loaded_inode_bitmaps &&
+ sb->u.ext2_sb.s_inode_bitmap_number[i] != block_group;
i++)
;
- if (i < sb->s_loaded_inode_bitmaps &&
- sb->s_inode_bitmap_number[i] == block_group) {
- inode_bitmap_number = sb->s_inode_bitmap_number[i];
- inode_bitmap = sb->s_inode_bitmap[i];
+ if (i < sb->u.ext2_sb.s_loaded_inode_bitmaps &&
+ sb->u.ext2_sb.s_inode_bitmap_number[i] == block_group) {
+ inode_bitmap_number = sb->u.ext2_sb.s_inode_bitmap_number[i];
+ inode_bitmap = sb->u.ext2_sb.s_inode_bitmap[i];
for (j = i; j > 0; j--) {
- sb->s_inode_bitmap_number[j] =
- sb->s_inode_bitmap_number[j - 1];
- sb->s_inode_bitmap[j] =
- sb->s_inode_bitmap[j - 1];
+ sb->u.ext2_sb.s_inode_bitmap_number[j] =
+ sb->u.ext2_sb.s_inode_bitmap_number[j - 1];
+ sb->u.ext2_sb.s_inode_bitmap[j] =
+ sb->u.ext2_sb.s_inode_bitmap[j - 1];
}
- sb->s_inode_bitmap_number[0] = inode_bitmap_number;
- sb->s_inode_bitmap[0] = inode_bitmap;
+ sb->u.ext2_sb.s_inode_bitmap_number[0] = inode_bitmap_number;
+ sb->u.ext2_sb.s_inode_bitmap[0] = inode_bitmap;
} else {
- if (sb->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
- sb->s_loaded_inode_bitmaps++;
+ if (sb->u.ext2_sb.s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
+ sb->u.ext2_sb.s_loaded_inode_bitmaps++;
else
- brelse (sb->s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
- for (j = sb->s_loaded_inode_bitmaps - 1; j > 0; j--) {
- sb->s_inode_bitmap_number[j] =
- sb->s_inode_bitmap_number[j - 1];
- sb->s_inode_bitmap[j] =
- sb->s_inode_bitmap[j - 1];
+ brelse (sb->u.ext2_sb.s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
+ for (j = sb->u.ext2_sb.s_loaded_inode_bitmaps - 1; j > 0; j--) {
+ sb->u.ext2_sb.s_inode_bitmap_number[j] =
+ sb->u.ext2_sb.s_inode_bitmap_number[j - 1];
+ sb->u.ext2_sb.s_inode_bitmap[j] =
+ sb->u.ext2_sb.s_inode_bitmap[j - 1];
}
- read_inode_bitmap (mp, block_group, 0);
+ read_inode_bitmap (sb, block_group, 0);
}
return 0;
}
+/*
+ * This function sets the deletion time for the inode
+ *
+ * This may be used one day by an 'undelete' program
+ */
+static void set_inode_dtime (struct inode * inode,
+ struct ext2_group_desc * gdp)
+{
+ unsigned long inode_block;
+ struct buffer_head * bh;
+ struct ext2_inode * raw_inode;
+
+ inode_block = gdp->bg_inode_table + (((inode->i_ino - 1) %
+ EXT2_INODES_PER_GROUP(inode->i_sb)) /
+ EXT2_INODES_PER_BLOCK(inode->i_sb));
+ bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize);
+ if (!bh)
+ ext2_panic (inode->i_sb, "set_inode_dtime",
+ "Cannot load inode table block - "
+ "inode=%lu, inode_block=%lu",
+ inode->i_ino, inode_block);
+ raw_inode = ((struct ext2_inode *) bh->b_data) +
+ (((inode->i_ino - 1) %
+ EXT2_INODES_PER_GROUP(inode->i_sb)) %
+ EXT2_INODES_PER_BLOCK(inode->i_sb));
+ raw_inode->i_links_count = 0;
+ raw_inode->i_dtime = CURRENT_TIME;
+ mark_buffer_dirty(bh, 1);
+ if (IS_SYNC(inode)) {
+ ll_rw_block (WRITE, 1, &bh);
+ wait_on_buffer (bh);
+ }
+ brelse (bh);
+}
void ext2_free_inode (struct inode * inode)
{
- struct ext2_sb_info * sb;
+ struct super_block * sb;
struct buffer_head * bh;
struct buffer_head * bh2;
unsigned long block_group;
@@ -209,51 +199,65 @@ void ext2_free_inode (struct inode * inode)
if (!inode)
return;
-
+ if (!inode->i_dev) {
+ printk ("ext2_free_inode: inode has no device\n");
+ return;
+ }
+ if (inode->i_count > 1) {
+ printk ("ext2_free_inode: inode has count=%d\n",
+ inode->i_count);
+ return;
+ }
if (inode->i_nlink) {
- printf ("ext2_free_inode: inode has nlink=%d\n",
+ printk ("ext2_free_inode: inode has nlink=%d\n",
inode->i_nlink);
return;
}
+ if (!inode->i_sb) {
+ printk("ext2_free_inode: inode on nonexistent device\n");
+ return;
+ }
- ext2_debug ("freeing inode %lu\n", inode->i_number);
+ ext2_debug ("freeing inode %lu\n", inode->i_ino);
- sb = inode->i_e2fs;
- lock_super (DEVVP(inode));
- if (inode->i_number < EXT2_FIRST_INO ||
- inode->i_number > sb->s_es->s_inodes_count) {
- printf ("free_inode reserved inode or nonexistent inode");
- unlock_super (DEVVP(inode));
+ sb = inode->i_sb;
+ lock_super (sb);
+ if (inode->i_ino < EXT2_FIRST_INO ||
+ inode->i_ino > sb->u.ext2_sb.s_es->s_inodes_count) {
+ ext2_error (sb, "free_inode",
+ "reserved inode or nonexistent inode");
+ unlock_super (sb);
return;
}
- es = sb->s_es;
- block_group = (inode->i_number - 1) / EXT2_INODES_PER_GROUP(sb);
- bit = (inode->i_number - 1) % EXT2_INODES_PER_GROUP(sb);
- bitmap_nr = load_inode_bitmap (ITOV(inode)->v_mount, block_group);
- bh = sb->s_inode_bitmap[bitmap_nr];
- if (!clear_bit (bit, bh->b_data))
- printf ( "ext2_free_inode:"
- "bit already cleared for inode %lu", inode->i_number);
+ es = sb->u.ext2_sb.s_es;
+ block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(sb);
+ bit = (inode->i_ino - 1) % EXT2_INODES_PER_GROUP(sb);
+ bitmap_nr = load_inode_bitmap (sb, block_group);
+ bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
+ if (!clear_bit (bit, bh->b_data))
+ ext2_warning (sb, "ext2_free_inode",
+ "bit already cleared for inode %lu", inode->i_ino);
else {
- gdp = get_group_desc (ITOV(inode)->v_mount, block_group, &bh2);
+ gdp = get_group_desc (sb, block_group, &bh2);
gdp->bg_free_inodes_count++;
- if (S_ISDIR(inode->i_mode))
+ if (S_ISDIR(inode->i_mode))
gdp->bg_used_dirs_count--;
- mark_buffer_dirty(bh2);
+ mark_buffer_dirty(bh2, 1);
es->s_free_inodes_count++;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ set_inode_dtime (inode, gdp);
}
- mark_buffer_dirty(bh);
-/*** XXX
+ mark_buffer_dirty(bh, 1);
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
-***/
+
sb->s_dirt = 1;
- unlock_super (DEVVP(inode));
+ clear_inode (inode);
+ unlock_super (sb);
}
-#if linux
/*
* This function increments the inode version number
*
@@ -267,19 +271,20 @@ static void inc_inode_version (struct inode * inode,
struct buffer_head * bh;
struct ext2_inode * raw_inode;
- inode_block = gdp->bg_inode_table + (((inode->i_number - 1) %
+ inode_block = gdp->bg_inode_table + (((inode->i_ino - 1) %
EXT2_INODES_PER_GROUP(inode->i_sb)) /
EXT2_INODES_PER_BLOCK(inode->i_sb));
bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize);
if (!bh) {
- printf ("inc_inode_version Cannot load inode table block - "
+ ext2_error (inode->i_sb, "inc_inode_version",
+ "Cannot load inode table block - "
"inode=%lu, inode_block=%lu\n",
- inode->i_number, inode_block);
+ inode->i_ino, inode_block);
inode->u.ext2_i.i_version = 1;
return;
}
raw_inode = ((struct ext2_inode *) bh->b_data) +
- (((inode->i_number - 1) %
+ (((inode->i_ino - 1) %
EXT2_INODES_PER_GROUP(inode->i_sb)) %
EXT2_INODES_PER_BLOCK(inode->i_sb));
raw_inode->i_version++;
@@ -288,8 +293,6 @@ static void inc_inode_version (struct inode * inode,
brelse (bh);
}
-#endif /* linux */
-
/*
* There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both
@@ -300,32 +303,31 @@ static void inc_inode_version (struct inode * inode,
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
-/*
- * this functino has been reduced to the actual 'find the inode number' part
- */
-ino_t ext2_new_inode (const struct inode * dir, int mode)
+struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
- struct ext2_sb_info * sb;
+ struct super_block * sb;
struct buffer_head * bh;
struct buffer_head * bh2;
int i, j, avefreei;
+ struct inode * inode;
int bitmap_nr;
struct ext2_group_desc * gdp;
struct ext2_group_desc * tmp;
struct ext2_super_block * es;
- if (!dir)
- return 0;
- sb = dir->i_e2fs;
-
- lock_super (DEVVP(dir));
- es = sb->s_es;
+ if (!dir || !(inode = get_empty_inode ()))
+ return NULL;
+ sb = dir->i_sb;
+ inode->i_sb = sb;
+ inode->i_flags = sb->s_flags;
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
repeat:
- gdp = NULL; i=0;
-
- if (S_ISDIR(mode)) {
+ gdp = NULL; i=0;
+
+ if (S_ISDIR(mode)) {
avefreei = es->s_free_inodes_count /
- sb->s_groups_count;
+ sb->u.ext2_sb.s_groups_count;
/* I am not yet convinced that this next bit is necessary.
i = dir->u.ext2_i.i_block_group;
for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
@@ -340,8 +342,8 @@ repeat:
}
*/
if (!gdp) {
- for (j = 0; j < sb->s_groups_count; j++) {
- tmp = get_group_desc(ITOV(dir)->v_mount,j,&bh2);
+ for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
+ tmp = get_group_desc (sb, j, &bh2);
if (tmp->bg_free_inodes_count &&
tmp->bg_free_inodes_count >= avefreei) {
if (!gdp ||
@@ -359,8 +361,8 @@ repeat:
/*
* Try to place the inode in its parent directory
*/
- i = dir->i_block_group;
- tmp = get_group_desc (ITOV(dir)->v_mount, i, &bh2);
+ i = dir->u.ext2_i.i_block_group;
+ tmp = get_group_desc (sb, i, &bh2);
if (tmp->bg_free_inodes_count)
gdp = tmp;
else
@@ -369,11 +371,11 @@ repeat:
* Use a quadratic hash to find a group with a
* free inode
*/
- for (j = 1; j < sb->s_groups_count; j <<= 1) {
+ for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) {
i += j;
- if (i >= sb->s_groups_count)
- i -= sb->s_groups_count;
- tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
+ if (i >= sb->u.ext2_sb.s_groups_count)
+ i -= sb->u.ext2_sb.s_groups_count;
+ tmp = get_group_desc (sb, i, &bh2);
if (tmp->bg_free_inodes_count) {
gdp = tmp;
break;
@@ -384,11 +386,11 @@ repeat:
/*
* That failed: try linear search for a free inode
*/
- i = dir->i_block_group + 1;
- for (j = 2; j < sb->s_groups_count; j++) {
- if (++i >= sb->s_groups_count)
+ i = dir->u.ext2_i.i_block_group + 1;
+ for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
+ if (++i >= sb->u.ext2_sb.s_groups_count)
i = 0;
- tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
+ tmp = get_group_desc (sb, i, &bh2);
if (tmp->bg_free_inodes_count) {
gdp = tmp;
break;
@@ -398,92 +400,127 @@ repeat:
}
if (!gdp) {
- unlock_super (DEVVP(dir));
- return 0;
+ unlock_super (sb);
+ iput(inode);
+ return NULL;
}
- bitmap_nr = load_inode_bitmap (ITOV(dir)->v_mount, i);
- bh = sb->s_inode_bitmap[bitmap_nr];
+ bitmap_nr = load_inode_bitmap (sb, i);
+ bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
EXT2_INODES_PER_GROUP(sb))) <
EXT2_INODES_PER_GROUP(sb)) {
if (set_bit (j, bh->b_data)) {
- printf ( "ext2_new_inode:"
+ ext2_warning (sb, "ext2_new_inode",
"bit already set for inode %d", j);
goto repeat;
}
-/* Linux now does the following:
mark_buffer_dirty(bh, 1);
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
-*/
- mark_buffer_dirty(bh);
} else {
if (gdp->bg_free_inodes_count != 0) {
- printf ( "ext2_new_inode:"
+ ext2_error (sb, "ext2_new_inode",
"Free inodes count corrupted in group %d",
i);
- unlock_super (DEVVP(dir));
- return 0;
+ unlock_super (sb);
+ iput (inode);
+ return NULL;
}
goto repeat;
}
j += i * EXT2_INODES_PER_GROUP(sb) + 1;
if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
- printf ( "ext2_new_inode:"
+ ext2_error (sb, "ext2_new_inode",
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%d", i, j);
- unlock_super (DEVVP(dir));
- return 0;
+ unlock_super (sb);
+ iput (inode);
+ return NULL;
}
gdp->bg_free_inodes_count--;
if (S_ISDIR(mode))
gdp->bg_used_dirs_count++;
- mark_buffer_dirty(bh2);
+ mark_buffer_dirty(bh2, 1);
es->s_free_inodes_count--;
- /* mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); */
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;
- unlock_super (DEVVP(dir));
- return j;
+ inode->i_mode = mode;
+ inode->i_sb = sb;
+ inode->i_count = 1;
+ inode->i_nlink = 1;
+ inode->i_dev = sb->s_dev;
+ inode->i_uid = current->fsuid;
+ if (test_opt (sb, GRPID))
+ inode->i_gid = dir->i_gid;
+ else if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+ } else
+ inode->i_gid = current->fsgid;
+ inode->i_dirt = 1;
+ inode->i_ino = j;
+ inode->i_blksize = sb->s_blocksize;
+ inode->i_blocks = 0;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
+ if (S_ISLNK(mode))
+ inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
+ inode->u.ext2_i.i_faddr = 0;
+ inode->u.ext2_i.i_frag_no = 0;
+ inode->u.ext2_i.i_frag_size = 0;
+ inode->u.ext2_i.i_file_acl = 0;
+ inode->u.ext2_i.i_dir_acl = 0;
+ inode->u.ext2_i.i_dtime = 0;
+ inode->u.ext2_i.i_block_group = i;
+ inode->i_op = NULL;
+ if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
+ inode->i_flags |= MS_SYNCHRONOUS;
+ insert_inode_hash(inode);
+ inc_inode_version (inode, gdp, mode);
+
+ ext2_debug ("allocating inode %lu\n", inode->i_ino);
+
+ unlock_super (sb);
+ return inode;
}
-unsigned long ext2_count_free_inodes (struct mount * mp)
+unsigned long ext2_count_free_inodes (struct super_block * sb)
{
#ifdef EXT2FS_DEBUG
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
- lock_super (VFSTOUFS(mp)->um_devvp);
- es = sb->s_es;
+ lock_super (sb);
+ es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
- for (i = 0; i < sb->s_groups_count; i++) {
- gdp = get_group_desc (mp, i, NULL);
+ for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
+ gdp = get_group_desc (sb, i, NULL);
desc_count += gdp->bg_free_inodes_count;
- bitmap_nr = load_inode_bitmap (mp, i);
- x = ext2_count_free (sb->s_inode_bitmap[bitmap_nr],
+ bitmap_nr = load_inode_bitmap (sb, i);
+ x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
EXT2_INODES_PER_GROUP(sb) / 8);
- ext2_debug ("group %d: stored = %d, counted = %lu\n",
+ printk ("group %d: stored = %d, counted = %lu\n",
i, gdp->bg_free_inodes_count, x);
bitmap_count += x;
}
- ext2_debug("stored = %lu, computed = %lu, %lu\n",
+ printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
es->s_free_inodes_count, desc_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (sb);
return desc_count;
#else
- return VFSTOUFS(mp)->um_e2fsb->s_free_inodes_count;
+ return sb->u.ext2_sb.s_es->s_free_inodes_count;
#endif
}
-#ifdef LATER
-void ext2_check_inodes_bitmap (struct mount * mp)
+void ext2_check_inodes_bitmap (struct super_block * sb)
{
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
@@ -503,18 +540,16 @@ void ext2_check_inodes_bitmap (struct mount * mp)
x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
EXT2_INODES_PER_GROUP(sb) / 8);
if (gdp->bg_free_inodes_count != x)
- printf ( "ext2_check_inodes_bitmap:"
+ ext2_error (sb, "ext2_check_inodes_bitmap",
"Wrong free inodes count in group %d, "
"stored = %d, counted = %lu", i,
gdp->bg_free_inodes_count, x);
bitmap_count += x;
}
if (es->s_free_inodes_count != bitmap_count)
- printf ( "ext2_check_inodes_bitmap:"
+ ext2_error (sb, "ext2_check_inodes_bitmap",
"Wrong free inodes count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) es->s_free_inodes_count, bitmap_count);
unlock_super (sb);
}
-#endif
-
diff --git a/sys/gnu/ext2fs/ext2_super.c b/sys/gnu/ext2fs/ext2_super.c
new file mode 100644
index 0000000..b73cc52
--- /dev/null
+++ b/sys/gnu/ext2fs/ext2_super.c
@@ -0,0 +1,780 @@
+/*
+ * 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
+ */
+
+#include <stdarg.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+
+static char error_buf[1024];
+
+void ext2_error (struct super_block * sb, const char * function,
+ const char * fmt, ...)
+{
+ va_list args;
+
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
+ sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ sb->s_dirt = 1;
+ }
+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+ if (test_opt (sb, ERRORS_PANIC) ||
+ (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_PANIC &&
+ !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
+ panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
+ printk (KERN_CRIT "EXT2-fs error (device %d/%d): %s: %s\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
+ if (test_opt (sb, ERRORS_RO) ||
+ (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_RO &&
+ !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
+ printk ("Remounting filesystem read-only\n");
+ sb->s_flags |= MS_RDONLY;
+ }
+}
+
+NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
+ const char * fmt, ...)
+{
+ va_list args;
+
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
+ sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ sb->s_dirt = 1;
+ }
+ va_start (args, fmt);
+ vsprintf (error_buf, fmt, args);
+ va_end (args);
+ panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
+}
+
+void ext2_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 "EXT2-fs warning (device %d/%d): %s: %s\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), function, error_buf);
+}
+
+void ext2_put_super (struct super_block * sb)
+{
+ int db_count;
+ int i;
+
+ lock_super (sb);
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ }
+ sb->s_dev = 0;
+ db_count = sb->u.ext2_sb.s_db_per_group;
+ for (i = 0; i < db_count; i++)
+ if (sb->u.ext2_sb.s_group_desc[i])
+ brelse (sb->u.ext2_sb.s_group_desc[i]);
+ kfree_s (sb->u.ext2_sb.s_group_desc,
+ db_count * sizeof (struct buffer_head *));
+ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
+ if (sb->u.ext2_sb.s_inode_bitmap[i])
+ brelse (sb->u.ext2_sb.s_inode_bitmap[i]);
+ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
+ if (sb->u.ext2_sb.s_block_bitmap[i])
+ brelse (sb->u.ext2_sb.s_block_bitmap[i]);
+ brelse (sb->u.ext2_sb.s_sbh);
+ unlock_super (sb);
+ return;
+}
+
+static struct super_operations ext2_sops = {
+ ext2_read_inode,
+ NULL,
+ ext2_write_inode,
+ ext2_put_inode,
+ ext2_put_super,
+ ext2_write_super,
+ ext2_statfs,
+ ext2_remount
+};
+
+#ifdef EXT2FS_PRE_02B_COMPAT
+
+static int convert_pre_02b_fs (struct super_block * sb,
+ struct buffer_head * bh)
+{
+ struct ext2_super_block * es;
+ struct ext2_old_group_desc old_group_desc [BLOCK_SIZE / sizeof (struct ext2_old_group_desc)];
+ struct ext2_group_desc * gdp;
+ struct buffer_head * bh2;
+ int groups_count;
+ int i;
+
+ es = (struct ext2_super_block *) bh->b_data;
+ bh2 = bread (sb->s_dev, 2, BLOCK_SIZE);
+ if (!bh2) {
+ printk ("Cannot read descriptor blocks while converting !\n");
+ return 0;
+ }
+ memcpy (old_group_desc, bh2->b_data, BLOCK_SIZE);
+ groups_count = (sb->u.ext2_sb.s_blocks_count -
+ sb->u.ext2_sb.s_first_data_block +
+ (EXT2_BLOCK_SIZE(sb) * 8) - 1) /
+ (EXT2_BLOCK_SIZE(sb) * 8);
+ memset (bh2->b_data, 0, BLOCK_SIZE);
+ gdp = (struct ext2_group_desc *) bh2->b_data;
+ for (i = 0; i < groups_count; i++) {
+ gdp[i].bg_block_bitmap = old_group_desc[i].bg_block_bitmap;
+ gdp[i].bg_inode_bitmap = old_group_desc[i].bg_inode_bitmap;
+ gdp[i].bg_inode_table = old_group_desc[i].bg_inode_table;
+ gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
+ gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
+ }
+ mark_buffer_dirty(bh2, 1);
+ brelse (bh2);
+ es->s_magic = EXT2_SUPER_MAGIC;
+ mark_buffer_dirty(bh, 1);
+ sb->s_magic = EXT2_SUPER_MAGIC;
+ return 1;
+}
+
+#endif
+
+/*
+ * This function has been shamelessly adapted from the msdos fs
+ */
+static int parse_options (char * options, unsigned long * sb_block,
+ unsigned short *resuid, unsigned short * resgid,
+ unsigned long * mount_options)
+{
+ char * this_char;
+ char * value;
+
+ 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, "bsddf"))
+ clear_opt (*mount_options, MINIX_DF);
+ else if (!strcmp (this_char, "check")) {
+ if (!value || !*value)
+ set_opt (*mount_options, CHECK_NORMAL);
+ else if (!strcmp (value, "none")) {
+ clear_opt (*mount_options, CHECK_NORMAL);
+ clear_opt (*mount_options, CHECK_STRICT);
+ }
+ else if (strcmp (value, "normal"))
+ set_opt (*mount_options, CHECK_NORMAL);
+ else if (strcmp (value, "strict")) {
+ set_opt (*mount_options, CHECK_NORMAL);
+ set_opt (*mount_options, CHECK_STRICT);
+ }
+ else {
+ printk ("EXT2-fs: Invalid check option: %s\n",
+ value);
+ return 0;
+ }
+ }
+ else if (!strcmp (this_char, "debug"))
+ set_opt (*mount_options, DEBUG);
+ else if (!strcmp (this_char, "errors")) {
+ if (!value || !*value) {
+ printk ("EXT2-fs: the errors option requires "
+ "an argument");
+ return 0;
+ }
+ if (!strcmp (value, "continue")) {
+ clear_opt (*mount_options, ERRORS_RO);
+ clear_opt (*mount_options, ERRORS_PANIC);
+ set_opt (*mount_options, ERRORS_CONT);
+ }
+ else if (!strcmp (value, "remount-ro")) {
+ clear_opt (*mount_options, ERRORS_CONT);
+ clear_opt (*mount_options, ERRORS_PANIC);
+ set_opt (*mount_options, ERRORS_RO);
+ }
+ else if (!strcmp (value, "panic")) {
+ clear_opt (*mount_options, ERRORS_CONT);
+ clear_opt (*mount_options, ERRORS_RO);
+ set_opt (*mount_options, ERRORS_PANIC);
+ }
+ else {
+ printk ("EXT2-fs: Invalid errors option: %s\n",
+ value);
+ return 0;
+ }
+ }
+ else if (!strcmp (this_char, "grpid") ||
+ !strcmp (this_char, "bsdgroups"))
+ set_opt (*mount_options, GRPID);
+ else if (!strcmp (this_char, "minixdf"))
+ set_opt (*mount_options, MINIX_DF);
+ else if (!strcmp (this_char, "nocheck")) {
+ clear_opt (*mount_options, CHECK_NORMAL);
+ clear_opt (*mount_options, CHECK_STRICT);
+ }
+ else if (!strcmp (this_char, "nogrpid") ||
+ !strcmp (this_char, "sysvgroups"))
+ clear_opt (*mount_options, GRPID);
+ else if (!strcmp (this_char, "resgid")) {
+ if (!value || !*value) {
+ printk ("EXT2-fs: the resgid option requires "
+ "an argument");
+ return 0;
+ }
+ *resgid = simple_strtoul (value, &value, 0);
+ if (*value) {
+ printk ("EXT2-fs: Invalid resgid option: %s\n",
+ value);
+ return 0;
+ }
+ }
+ else if (!strcmp (this_char, "resuid")) {
+ if (!value || !*value) {
+ printk ("EXT2-fs: the resuid option requires "
+ "an argument");
+ return 0;
+ }
+ *resuid = simple_strtoul (value, &value, 0);
+ if (*value) {
+ printk ("EXT2-fs: Invalid resuid option: %s\n",
+ value);
+ return 0;
+ }
+ }
+ else if (!strcmp (this_char, "sb")) {
+ if (!value || !*value) {
+ printk ("EXT2-fs: the sb option requires "
+ "an argument");
+ return 0;
+ }
+ *sb_block = simple_strtoul (value, &value, 0);
+ if (*value) {
+ printk ("EXT2-fs: Invalid sb option: %s\n",
+ value);
+ return 0;
+ }
+ }
+ else {
+ printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void ext2_setup_super (struct super_block * sb,
+ struct ext2_super_block * es)
+{
+ if (es->s_rev_level > EXT2_CURRENT_REV) {
+ printk ("EXT2-fs warning: revision level too high, "
+ "forcing read/only mode\n");
+ sb->s_flags |= MS_RDONLY;
+ }
+ if (!(sb->s_flags & MS_RDONLY)) {
+ if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
+ printk ("EXT2-fs warning: mounting unchecked fs, "
+ "running e2fsck is recommended\n");
+ else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS))
+ printk ("EXT2-fs warning: mounting fs with errors, "
+ "running e2fsck is recommended\n");
+ else if (es->s_max_mnt_count >= 0 &&
+ es->s_mnt_count >= (unsigned short) es->s_max_mnt_count)
+ printk ("EXT2-fs warning: maximal mount count reached, "
+ "running e2fsck is recommended\n");
+ else if (es->s_checkinterval &&
+ (es->s_lastcheck + es->s_checkinterval <= CURRENT_TIME))
+ printk ("EXT2-fs warning: checktime reached, "
+ "running e2fsck is recommended\n");
+ es->s_state &= ~EXT2_VALID_FS;
+ if (!es->s_max_mnt_count)
+ es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
+ es->s_mnt_count++;
+ es->s_mtime = CURRENT_TIME;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ sb->s_dirt = 1;
+ if (test_opt (sb, DEBUG))
+ printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
+ "bpg=%lu, ipg=%lu, mo=%04lx]\n",
+ EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
+ sb->u.ext2_sb.s_frag_size,
+ sb->u.ext2_sb.s_groups_count,
+ EXT2_BLOCKS_PER_GROUP(sb),
+ EXT2_INODES_PER_GROUP(sb),
+ sb->u.ext2_sb.s_mount_opt);
+ if (test_opt (sb, CHECK)) {
+ ext2_check_blocks_bitmap (sb);
+ ext2_check_inodes_bitmap (sb);
+ }
+ }
+}
+
+static int ext2_check_descriptors (struct super_block * sb)
+{
+ int i;
+ int desc_block = 0;
+ unsigned long block = sb->u.ext2_sb.s_es->s_first_data_block;
+ struct ext2_group_desc * gdp = NULL;
+
+ ext2_debug ("Checking group descriptors");
+
+ for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++)
+ {
+ if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
+ gdp = (struct ext2_group_desc *) sb->u.ext2_sb.s_group_desc[desc_block++]->b_data;
+ if (gdp->bg_block_bitmap < block ||
+ gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
+ {
+ ext2_error (sb, "ext2_check_descriptors",
+ "Block bitmap for group %d"
+ " not in group (block %lu)!",
+ i, (unsigned long) gdp->bg_block_bitmap);
+ return 0;
+ }
+ if (gdp->bg_inode_bitmap < block ||
+ gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
+ {
+ ext2_error (sb, "ext2_check_descriptors",
+ "Inode bitmap for group %d"
+ " not in group (block %lu)!",
+ i, (unsigned long) gdp->bg_inode_bitmap);
+ return 0;
+ }
+ if (gdp->bg_inode_table < block ||
+ gdp->bg_inode_table + sb->u.ext2_sb.s_itb_per_group >=
+ block + EXT2_BLOCKS_PER_GROUP(sb))
+ {
+ ext2_error (sb, "ext2_check_descriptors",
+ "Inode table for group %d"
+ " not in group (block %lu)!",
+ i, (unsigned long) gdp->bg_inode_table);
+ return 0;
+ }
+ block += EXT2_BLOCKS_PER_GROUP(sb);
+ gdp++;
+ }
+ return 1;
+}
+
+struct super_block * ext2_read_super (struct super_block * sb, void * data,
+ int silent)
+{
+ struct buffer_head * bh;
+ struct ext2_super_block * es;
+ unsigned long sb_block = 1;
+ unsigned short resuid = EXT2_DEF_RESUID;
+ unsigned short resgid = EXT2_DEF_RESGID;
+ unsigned long logic_sb_block = 1;
+ int dev = sb->s_dev;
+ int db_count;
+ int i, j;
+#ifdef EXT2FS_PRE_02B_COMPAT
+ int fs_converted = 0;
+#endif
+
+ set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
+ if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
+ &sb->u.ext2_sb.s_mount_opt)) {
+ sb->s_dev = 0;
+ return NULL;
+ }
+
+ lock_super (sb);
+ set_blocksize (dev, BLOCK_SIZE);
+ if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ printk ("EXT2-fs: unable to read superblock\n");
+ return NULL;
+ }
+ /*
+ * Note: s_es must be initialized s_es as soon as possible because
+ * some ext2 macro-instructions depend on its value
+ */
+ es = (struct ext2_super_block *) bh->b_data;
+ sb->u.ext2_sb.s_es = es;
+ sb->s_magic = es->s_magic;
+ if (sb->s_magic != EXT2_SUPER_MAGIC
+#ifdef EXT2FS_PRE_02B_COMPAT
+ && sb->s_magic != EXT2_PRE_02B_MAGIC
+#endif
+ ) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ if (!silent)
+ printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
+ MAJOR(dev), MINOR(dev));
+ return NULL;
+ }
+ sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
+ sb->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(sb);
+ if (sb->s_blocksize != BLOCK_SIZE &&
+ (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
+ sb->s_blocksize == 4096)) {
+ unsigned long offset;
+
+ brelse (bh);
+ set_blocksize (dev, sb->s_blocksize);
+ logic_sb_block = (sb_block*BLOCK_SIZE) / sb->s_blocksize;
+ offset = (sb_block*BLOCK_SIZE) % sb->s_blocksize;
+ bh = bread (dev, logic_sb_block, sb->s_blocksize);
+ if(!bh)
+ return NULL;
+ es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
+ sb->u.ext2_sb.s_es = es;
+ if (es->s_magic != EXT2_SUPER_MAGIC) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: Magic mismatch, very weird !\n");
+ return NULL;
+ }
+ }
+ sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
+ es->s_log_frag_size;
+ if (sb->u.ext2_sb.s_frag_size)
+ sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
+ sb->u.ext2_sb.s_frag_size;
+ else
+ sb->s_magic = 0;
+ sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
+ sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
+ sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
+ sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
+ sizeof (struct ext2_inode);
+ sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
+ sb->u.ext2_sb.s_inodes_per_block;
+ sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
+ sizeof (struct ext2_group_desc);
+ sb->u.ext2_sb.s_sbh = bh;
+ sb->u.ext2_sb.s_es = es;
+ if (resuid != EXT2_DEF_RESUID)
+ sb->u.ext2_sb.s_resuid = resuid;
+ else
+ sb->u.ext2_sb.s_resuid = es->s_def_resuid;
+ if (resgid != EXT2_DEF_RESGID)
+ sb->u.ext2_sb.s_resgid = resgid;
+ else
+ sb->u.ext2_sb.s_resgid = es->s_def_resgid;
+ sb->u.ext2_sb.s_mount_state = es->s_state;
+ sb->u.ext2_sb.s_rename_lock = 0;
+ sb->u.ext2_sb.s_rename_wait = NULL;
+#ifdef EXT2FS_PRE_02B_COMPAT
+ if (sb->s_magic == EXT2_PRE_02B_MAGIC) {
+ if (es->s_blocks_count > 262144) {
+ /*
+ * fs > 256 MB can't be converted
+ */
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: trying to mount a pre-0.2b file"
+ "system which cannot be converted\n");
+ return NULL;
+ }
+ printk ("EXT2-fs: mounting a pre 0.2b file system, "
+ "will try to convert the structure\n");
+ if (!(sb->s_flags & MS_RDONLY)) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: cannot convert a read-only fs\n");
+ return NULL;
+ }
+ if (!convert_pre_02b_fs (sb, bh)) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: conversion failed !!!\n");
+ return NULL;
+ }
+ printk ("EXT2-fs: conversion succeeded !!!\n");
+ fs_converted = 1;
+ }
+#endif
+ if (sb->s_magic != EXT2_SUPER_MAGIC) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ if (!silent)
+ printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
+ MAJOR(dev), MINOR(dev));
+ return NULL;
+ }
+ if (sb->s_blocksize != bh->b_size) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ if (!silent)
+ printk ("VFS: Unsupported blocksize on dev 0x%04x.\n",
+ dev);
+ return NULL;
+ }
+
+ if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
+ sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
+ return NULL;
+ }
+
+ if (sb->u.ext2_sb.s_blocks_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #blocks per group too big: %lu\n",
+ sb->u.ext2_sb.s_blocks_per_group);
+ return NULL;
+ }
+ if (sb->u.ext2_sb.s_frags_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #fragments per group too big: %lu\n",
+ sb->u.ext2_sb.s_frags_per_group);
+ return NULL;
+ }
+ if (sb->u.ext2_sb.s_inodes_per_group > sb->s_blocksize * 8) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: #inodes per group too big: %lu\n",
+ sb->u.ext2_sb.s_inodes_per_group);
+ return NULL;
+ }
+
+ sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
+ es->s_first_data_block +
+ EXT2_BLOCKS_PER_GROUP(sb) - 1) /
+ EXT2_BLOCKS_PER_GROUP(sb);
+ db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
+ EXT2_DESC_PER_BLOCK(sb);
+ sb->u.ext2_sb.s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
+ if (sb->u.ext2_sb.s_group_desc == NULL) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ brelse (bh);
+ printk ("EXT2-fs: not enough memory\n");
+ return NULL;
+ }
+ for (i = 0; i < db_count; i++) {
+ sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
+ sb->s_blocksize);
+ if (!sb->u.ext2_sb.s_group_desc[i]) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ for (j = 0; j < i; j++)
+ brelse (sb->u.ext2_sb.s_group_desc[j]);
+ kfree_s (sb->u.ext2_sb.s_group_desc,
+ db_count * sizeof (struct buffer_head *));
+ brelse (bh);
+ printk ("EXT2-fs: unable to read group descriptors\n");
+ return NULL;
+ }
+ }
+ if (!ext2_check_descriptors (sb)) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ for (j = 0; j < db_count; j++)
+ brelse (sb->u.ext2_sb.s_group_desc[j]);
+ kfree_s (sb->u.ext2_sb.s_group_desc,
+ db_count * sizeof (struct buffer_head *));
+ brelse (bh);
+ printk ("EXT2-fs: group descriptors corrupted !\n");
+ return NULL;
+ }
+ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
+ sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
+ sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
+ sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
+ sb->u.ext2_sb.s_block_bitmap[i] = NULL;
+ }
+ sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
+ sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
+ sb->u.ext2_sb.s_db_per_group = db_count;
+ unlock_super (sb);
+ /*
+ * set up enough so that it can read an inode
+ */
+ sb->s_dev = dev;
+ sb->s_op = &ext2_sops;
+ if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
+ sb->s_dev = 0;
+ for (i = 0; i < db_count; i++)
+ if (sb->u.ext2_sb.s_group_desc[i])
+ brelse (sb->u.ext2_sb.s_group_desc[i]);
+ kfree_s (sb->u.ext2_sb.s_group_desc,
+ db_count * sizeof (struct buffer_head *));
+ brelse (bh);
+ printk ("EXT2-fs: get root inode failed\n");
+ return NULL;
+ }
+#ifdef EXT2FS_PRE_02B_COMPAT
+ if (fs_converted) {
+ for (i = 0; i < db_count; i++)
+ mark_buffer_dirty(sb->u.ext2_sb.s_group_desc[i], 1);
+ sb->s_dirt = 1;
+ }
+#endif
+ ext2_setup_super (sb, es);
+ return sb;
+}
+
+static void ext2_commit_super (struct super_block * sb,
+ struct ext2_super_block * es)
+{
+ es->s_wtime = CURRENT_TIME;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ sb->s_dirt = 0;
+}
+
+/*
+ * In the second extended file system, it is not necessary to
+ * write the super block since we use a mapping of the
+ * disk super block in a buffer.
+ *
+ * However, this function is still used to set the fs valid
+ * flags to 0. We need to set this flag to 0 since the fs
+ * may have been checked while mounted and e2fsck may have
+ * set s_state to EXT2_VALID_FS after some corrections.
+ */
+
+void ext2_write_super (struct super_block * sb)
+{
+ struct ext2_super_block * es;
+
+ if (!(sb->s_flags & MS_RDONLY)) {
+ es = sb->u.ext2_sb.s_es;
+
+ ext2_debug ("setting valid to 0\n");
+
+ if (es->s_state & EXT2_VALID_FS) {
+ es->s_state &= ~EXT2_VALID_FS;
+ es->s_mtime = CURRENT_TIME;
+ }
+ ext2_commit_super (sb, es);
+ }
+ sb->s_dirt = 0;
+}
+
+int ext2_remount (struct super_block * sb, int * flags, char * data)
+{
+ struct ext2_super_block * es;
+ unsigned short resuid = sb->u.ext2_sb.s_resuid;
+ unsigned short resgid = sb->u.ext2_sb.s_resgid;
+ unsigned long new_mount_opt;
+ unsigned long tmp;
+
+ /*
+ * Allow the "check" option to be passed as a remount option.
+ */
+ set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
+ if (!parse_options (data, &tmp, &resuid, &resgid,
+ &new_mount_opt))
+ return -EINVAL;
+
+ sb->u.ext2_sb.s_mount_opt = new_mount_opt;
+ sb->u.ext2_sb.s_resuid = resuid;
+ sb->u.ext2_sb.s_resgid = resgid;
+ es = sb->u.ext2_sb.s_es;
+ if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+ return 0;
+ if (*flags & MS_RDONLY) {
+ if (es->s_state & EXT2_VALID_FS ||
+ !(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
+ return 0;
+ /*
+ * OK, we are remounting a valid rw partition rdonly, so set
+ * the rdonly flag and then mark the partition as valid again.
+ */
+ es->s_state = sb->u.ext2_sb.s_mount_state;
+ es->s_mtime = CURRENT_TIME;
+ mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+ sb->s_dirt = 1;
+ ext2_commit_super (sb, es);
+ }
+ else {
+ /*
+ * Mounting a RDONLY partition read-write, so reread and
+ * store the current valid flag. (It may have been changed
+ * by e2fsck since we originally mounted the partition.)
+ */
+ sb->u.ext2_sb.s_mount_state = es->s_state;
+ sb->s_flags &= ~MS_RDONLY;
+ ext2_setup_super (sb, es);
+ }
+ return 0;
+}
+
+void ext2_statfs (struct super_block * sb, struct statfs * buf)
+{
+ long tmp;
+ unsigned long overhead;
+ unsigned long overhead_per_group;
+
+ if (test_opt (sb, MINIX_DF))
+ overhead = 0;
+ else {
+ /*
+ * Compute the overhead (FS structures)
+ */
+ overhead_per_group = 1 /* super block */ +
+ sb->u.ext2_sb.s_db_per_group /* descriptors */ +
+ 1 /* block bitmap */ +
+ 1 /* inode bitmap */ +
+ sb->u.ext2_sb.s_itb_per_group /* inode table */;
+ overhead = sb->u.ext2_sb.s_es->s_first_data_block +
+ sb->u.ext2_sb.s_groups_count * overhead_per_group;
+ }
+
+ put_fs_long (EXT2_SUPER_MAGIC, &buf->f_type);
+ put_fs_long (sb->s_blocksize, &buf->f_bsize);
+ put_fs_long (sb->u.ext2_sb.s_es->s_blocks_count - overhead,
+ &buf->f_blocks);
+ tmp = ext2_count_free_blocks (sb);
+ put_fs_long (tmp, &buf->f_bfree);
+ if (tmp >= sb->u.ext2_sb.s_es->s_r_blocks_count)
+ put_fs_long (tmp - sb->u.ext2_sb.s_es->s_r_blocks_count,
+ &buf->f_bavail);
+ else
+ put_fs_long (0, &buf->f_bavail);
+ put_fs_long (sb->u.ext2_sb.s_es->s_inodes_count, &buf->f_files);
+ put_fs_long (ext2_count_free_inodes (sb), &buf->f_ffree);
+ put_fs_long (EXT2_NAME_LEN, &buf->f_namelen);
+ /* Don't know what value to put in buf->f_fsid */
+}
OpenPOWER on IntegriCloud