lkml.org 
[lkml]   [1997]   [Apr]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectExt2 patches
Linus,

Enclosed please find some patches to the ext2 filesystem layer, plus a
few changes to the VFS layer. I'd appreciate it if they could be
applied to the 2.1 development tree. Thanks!!

- Ted

The changes do the following:

* Add support for per-file no-atime support. (Currently
settable only on regular files using the ext2-specific
ioctls, via the chattr program, but see below.)

* The beginnings of VFS level support for setting per-file
attributes, using the BSD getflags() and setflags()
interface. The idea here is to have a generic way of
setting flags like the MS-DOS read-only flag, the ext2
append-only flag, etc.

* Update ext2 include file to contain new superblock fields,
including the UUID, volume name, and last_mounted
fields. (The e2fsprogs programs have supported these
fields for a while now, I just haven't gotten them into
the kernel include files).

* Fixed a bug (or rather, unwarranted assumption) in the ext2
block freeing routines that you can never free an extent
which crosses a block group boundary. This was true
when every single block group began with an (allocated)
superblock, but with the advent of the e2fsprogs 1.09's
"sparse superblock" option, which reduces the overhead
for extremely large filesystems, this assumption was no
longer true. IT IS NOT SAFE TO USE THE SPARE SUPERBLOCK
OPTION IN E2FSPROGS UNTIL YOU APPLY THIS KERNEL PATCH.


Patch generated: on Sat Apr 26 10:36:11 EDT 1997 by tytso@rsts-11
against Linux version 2.1.36

===================================================================
RCS file: include/linux/RCS/ext2_fs.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/ext2_fs.h
--- include/linux/ext2_fs.h 1997/04/25 02:55:00 1.1
+++ include/linux/ext2_fs.h 1997/04/25 02:55:07
@@ -189,6 +189,7 @@
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
+#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */

/*
@@ -363,7 +364,10 @@
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
- __u32 s_reserved[230]; /* Padding to the end of the block */
+ __u8 s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ __u32 s_reserved[206]; /* Padding to the end of the block */
};

/*
@@ -387,6 +391,16 @@
#define EXT2_GOOD_OLD_INODE_SIZE 128

/*
+ * Feature set definitions
+ */
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+
+#define EXT2_FEATURE_COMPAT_SUPP 0
+#define EXT2_FEATURE_INCOMPAT_SUPP 0
+#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+
+/*
* Default values for user and/or group using reserved blocks
*/
#define EXT2_DEF_RESUID 0
@@ -413,13 +427,6 @@
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
-
-/*
- * Feature set definitions --- none are defined as of now
- */
-#define EXT2_FEATURE_COMPAT_SUPP 0
-#define EXT2_FEATURE_INCOMPAT_SUPP 0
-#define EXT2_FEATURE_RO_COMPAT_SUPP 0

#ifdef __KERNEL__
/*
===================================================================
RCS file: include/linux/RCS/ext2_fs_sb.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/ext2_fs_sb.h
--- include/linux/ext2_fs_sb.h 1997/04/25 02:55:00 1.1
+++ include/linux/ext2_fs_sb.h 1997/04/25 02:55:07
@@ -60,6 +60,9 @@
int s_desc_per_block_bits;
int s_inode_size;
int s_first_ino;
+ int s_feature_compat;
+ int s_feature_incompat;
+ int s_feature_ro_compat;
};

#endif /* _LINUX_EXT2_FS_SB */
===================================================================
RCS file: include/linux/RCS/fs.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/fs.h
--- include/linux/fs.h 1997/04/25 02:55:00 1.1
+++ include/linux/fs.h 1997/04/25 02:59:45
@@ -95,7 +95,6 @@
* Exception: MS_RDONLY is always applied to the entire file system.
*/
#define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY))
-#define DO_UPDATE_ATIME(inode) (!((inode)->i_flags & MS_NOATIME) && !IS_RDONLY(inode))
#define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID)
#define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
#define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
@@ -105,6 +104,8 @@
#define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE)
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
+#define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME)
+#define DO_UPDATE_ATIME(inode) (!IS_NOATIME(inode) && !IS_RDONLY(inode))

/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
@@ -246,6 +247,7 @@
#define ATTR_ATIME_SET 128
#define ATTR_MTIME_SET 256
#define ATTR_FORCE 512 /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG 1024

/*
* This is the Inode Attributes structure, used for notify_change(). It
@@ -265,8 +267,17 @@
time_t ia_atime;
time_t ia_mtime;
time_t ia_ctime;
+ unsigned int ia_attr_flags;
};

+/*
+ * This is the inode attributes flag definitions
+ */
+#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */
+#define ATTR_FLAG_NOATIME 2 /* Don't update atime */
+#define ATTR_FLAG_APPEND 4 /* Append-only file */
+#define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */
+
#include <linux/quota.h>

struct inode {
@@ -308,6 +319,7 @@
unsigned char i_seek;
unsigned char i_update;
unsigned short i_writecount;
+ unsigned int i_attr_flags;
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
===================================================================
RCS file: fs/RCS/pipe.c,v
retrieving revision 1.1
diff -u -r1.1 fs/pipe.c
--- fs/pipe.c 1997/04/25 02:55:00 1.1
+++ fs/pipe.c 1997/04/25 02:55:07
@@ -74,7 +74,10 @@
PIPE_LOCK(*inode)--;
wake_up_interruptible(&PIPE_WAIT(*inode));
if (read) {
- inode->i_atime = CURRENT_TIME;
+ if (DO_UPDATE_ATIME(inode)) {
+ inode->i_atime = CURRENT_TIME;
+ inode->i_dirt = 1;
+ }
return read;
}
if (PIPE_WRITERS(*inode))
@@ -128,6 +131,7 @@
free = 1;
}
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ inode->i_dirt = 1;
return written;
}

===================================================================
RCS file: fs/RCS/inode.c,v
retrieving revision 1.1
diff -u -r1.1 fs/inode.c
--- fs/inode.c 1997/04/25 02:55:01 1.1
+++ fs/inode.c 1997/04/25 02:57:15
@@ -288,7 +288,7 @@

((attr->ia_valid & ATTR_GID) &&
(!in_group_p(attr->ia_gid) &&
- (attr->ia_gid != inode->i_gid))) ||
+ (attr->ia_gid != inode->i_gid && not_fsuser))) ||

((attr->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)) &&
(fsuid != iuid) && not_fsuser))
@@ -325,6 +325,8 @@
if (!fsuser() && !in_group_p(inode->i_gid))
inode->i_mode &= ~S_ISGID;
}
+ if (attr->ia_valid & ATTR_ATTR_FLAG)
+ inode->i_attr_flags = attr->ia_attr_flags;
inode->i_dirt = 1;
}

===================================================================
RCS file: fs/ext2/RCS/inode.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/inode.c
--- fs/ext2/inode.c 1997/04/25 02:55:01 1.1
+++ fs/ext2/inode.c 1997/04/25 02:55:07
@@ -503,12 +503,23 @@
inode->i_op = &blkdev_inode_operations;
else if (S_ISFIFO(inode->i_mode))
init_fifo(inode);
- if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
+ inode->i_attr_flags = 0;
+ if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;
inode->i_flags |= MS_SYNCHRONOUS;
- if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL)
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_APPEND;
inode->i_flags |= S_APPEND;
- if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;
inode->i_flags |= S_IMMUTABLE;
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_NOATIME;
+ inode->i_flags |= MS_NOATIME;
+ }
}

static int ext2_update_inode(struct inode * inode, int do_sync)
@@ -597,11 +608,71 @@

void ext2_write_inode (struct inode * inode)
{
+#if 0
+ printk("ext2_write(%04x:%06d)...", inode->i_dev, inode->i_ino);
+#endif
ext2_update_inode (inode, 0);
}

int ext2_sync_inode (struct inode *inode)
{
+#if 0
+ printk("ext2_sync(%04x:%06d)...", inode->i_dev, inode->i_ino);
+#endif
return ext2_update_inode (inode, 1);
+}
+
+int ext2_notify_change(struct inode *inode, struct iattr *iattr)
+{
+ int retval;
+ unsigned int flags;
+
+ if ((iattr->ia_attr_flags &
+ (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
+ (inode->u.ext2_i.i_flags &
+ (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
+ if (!fsuser() || securelevel > 0)
+ return -EPERM;
+ } else
+ if ((current->fsuid != inode->i_uid) && !fsuser())
+ return -EPERM;
+
+ if ((retval = inode_change_ok(inode, iattr)) != 0)
+ return retval;
+
+ inode_setattr(inode, iattr);
+
+ flags = iattr->ia_attr_flags;
+ if (flags & ATTR_FLAG_SYNCRONOUS) {
+ inode->i_flags |= MS_SYNCHRONOUS;
+ inode->u.ext2_i.i_flags = EXT2_SYNC_FL;
+ } else {
+ inode->i_flags &= ~MS_SYNCHRONOUS;
+ inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;
+ }
+ if (flags & ATTR_FLAG_NOATIME) {
+ inode->i_flags |= MS_NOATIME;
+ inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;
+ } else {
+ inode->i_flags &= ~MS_NOATIME;
+ inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;
+ }
+ if (flags & ATTR_FLAG_APPEND) {
+ inode->i_flags |= S_APPEND;
+ inode->u.ext2_i.i_flags = EXT2_APPEND_FL;
+ } else {
+ inode->i_flags &= ~S_APPEND;
+ inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;
+ }
+ if (flags & ATTR_FLAG_IMMUTABLE) {
+ inode->i_flags |= S_IMMUTABLE;
+ inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;
+ } else {
+ inode->i_flags &= ~S_IMMUTABLE;
+ inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
+ }
+ inode->i_dirt = 1;
+
+ return 0;
}

===================================================================
RCS file: fs/ext2/RCS/ioctl.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/ioctl.c
--- fs/ext2/ioctl.c 1997/04/25 02:55:01 1.1
+++ fs/ext2/ioctl.c 1997/04/25 02:55:07
@@ -45,6 +45,10 @@
if (IS_RDONLY(inode))
return -EROFS;
inode->u.ext2_i.i_flags = flags;
+ if (flags & EXT2_SYNC_FL)
+ inode->i_flags |= MS_SYNCHRONOUS;
+ else
+ inode->i_flags &= ~MS_SYNCHRONOUS;
if (flags & EXT2_APPEND_FL)
inode->i_flags |= S_APPEND;
else
@@ -53,6 +57,10 @@
inode->i_flags |= S_IMMUTABLE;
else
inode->i_flags &= ~S_IMMUTABLE;
+ if (flags & EXT2_NOATIME_FL)
+ inode->i_flags |= MS_NOATIME;
+ else
+ inode->i_flags &= ~MS_NOATIME;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
return 0;
===================================================================
RCS file: fs/ext2/RCS/balloc.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/balloc.c
--- fs/ext2/balloc.c 1997/04/25 02:55:01 1.1
+++ fs/ext2/balloc.c 1997/04/25 02:55:07
@@ -177,6 +177,7 @@
unsigned long bit;
unsigned long i;
int bitmap_nr;
+ unsigned long overflow;
struct super_block * sb;
struct ext2_group_desc * gdp;
struct ext2_super_block * es;
@@ -199,14 +200,20 @@

ext2_debug ("freeing block %lu\n", block);

+do_more:
+ overflow = 0;
block_group = (block - le32_to_cpu(es->s_first_data_block)) /
EXT2_BLOCKS_PER_GROUP(sb);
- bit = (block - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb);
- if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
- ext2_panic (sb, "ext2_free_blocks",
- "Freeing blocks across group boundary - "
- "Block = %lu, count = %lu",
- block, count);
+ bit = (block - le32_to_cpu(es->s_first_data_block)) %
+ EXT2_BLOCKS_PER_GROUP(sb);
+ /*
+ * Check to see if we are freeing blocks across a group
+ * boundary.
+ */
+ if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) {
+ overflow = bit + count - EXT2_BLOCKS_PER_GROUP(sb);
+ count -= overflow;
+ }
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);
@@ -246,6 +253,11 @@
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
+ if (overflow) {
+ block += count;
+ count = overflow;
+ goto do_more;
+ }
sb->s_dirt = 1;
unlock_super (sb);
return;
@@ -546,6 +558,19 @@
EXT2_BLOCKS_PER_GROUP(sb), map);
}

+static int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
void ext2_check_blocks_bitmap (struct super_block * sb)
{
struct buffer_head * bh;
@@ -569,15 +594,21 @@
bitmap_nr = load_block_bitmap (sb, i);
bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];

- if (!ext2_test_bit (0, bh->b_data))
- ext2_error (sb, "ext2_check_blocks_bitmap",
- "Superblock in group %d is marked free", i);
-
- for (j = 0; j < desc_blocks; j++)
- if (!ext2_test_bit (j + 1, bh->b_data))
+ if (!(sb->u.ext2_sb.s_feature_ro_compat &
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+ (test_root(i, 3) || test_root(i, 5) || test_root(i, 7))) {
+ if (!ext2_test_bit (0, bh->b_data))
ext2_error (sb, "ext2_check_blocks_bitmap",
+ "Superblock in group %d "
+ "is marked free", i);
+
+ for (j = 0; j < desc_blocks; j++)
+ if (!ext2_test_bit (j + 1, bh->b_data))
+ ext2_error (sb,
+ "ext2_check_blocks_bitmap",
"Descriptor block #%d in group "
"%d is marked free", j, i);
+ }

if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
ext2_error (sb, "ext2_check_blocks_bitmap",
===================================================================
RCS file: fs/ext2/RCS/super.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/super.c
--- fs/ext2/super.c 1997/04/25 02:55:01 1.1
+++ fs/ext2/super.c 1997/04/25 02:55:07
@@ -508,6 +508,9 @@
goto failed_mount;
}
}
+ sb->u.ext2_sb.s_feature_compat = es->s_feature_compat;
+ sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat;
+ sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat;
sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
(__s32) le32_to_cpu(es->s_log_frag_size);
if (sb->u.ext2_sb.s_frag_size)
\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.104 / U:0.032 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site