diff -uNr linux-2.4.18.o1/fs/reiserfs/dir.c linux-2.4.18.o/fs/reiserfs/dir.c
--- linux-2.4.18.o1/fs/reiserfs/dir.c Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/fs/reiserfs/dir.c Thu Feb 28 19:25:22 2002
@@ -20,6 +20,7 @@
read: generic_read_dir,
readdir: reiserfs_readdir,
fsync: reiserfs_dir_fsync,
+ ioctl: reiserfs_ioctl,
};
int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, int datasync) {
diff -uNr linux-2.4.18.o1/fs/reiserfs/inode.c linux-2.4.18.o/fs/reiserfs/inode.c
--- linux-2.4.18.o1/fs/reiserfs/inode.c Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/fs/reiserfs/inode.c Thu Feb 28 19:25:22 2002
@@ -929,6 +929,9 @@
rdev = sd_v1_rdev(sd);
inode->u.reiserfs_i.i_first_direct_byte = sd_v1_first_direct_byte(sd);
+ /* nopack is initially zero for v1 objects. For v2 objects,
+ nopack is initialised from sd_attrs */
+ inode->u.reiserfs_i.i_flags &= ~i_nopack_mask;
} else {
// new stat data found, but object may have old items
// (directories and symlinks)
@@ -955,10 +958,12 @@
set_inode_item_key_version (inode, KEY_FORMAT_3_6);
set_inode_sd_version (inode, STAT_DATA_V2);
+ /* read persistent inode attributes from sd and initalise
+ generic inode flags from them */
+ inode -> u.reiserfs_i.i_attrs = sd_v2_attrs( sd );
+ sd_attrs_to_i_attrs( sd_v2_attrs( sd ), inode );
}
- /* nopack = 0, by default */
- inode->u.reiserfs_i.i_flags &= ~i_nopack_mask;
pathrelse (path);
if (S_ISREG (inode->i_mode)) {
@@ -982,6 +987,7 @@
static void inode2sd (void * sd, struct inode * inode)
{
struct stat_data * sd_v2 = (struct stat_data *)sd;
+ __u16 flags;
set_sd_v2_mode(sd_v2, inode->i_mode );
set_sd_v2_nlink(sd_v2, inode->i_nlink );
@@ -992,13 +998,13 @@
set_sd_v2_atime(sd_v2, inode->i_atime );
set_sd_v2_ctime(sd_v2, inode->i_ctime );
set_sd_v2_blocks(sd_v2, inode->i_blocks );
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
set_sd_v2_rdev(sd_v2, inode->i_rdev );
-}
else
- {
set_sd_v2_generation(sd_v2, inode->i_generation);
- }
+ flags = inode -> u.reiserfs_i.i_attrs;
+ i_attrs_to_sd_attrs( inode, &flags );
+ set_sd_v2_attrs( sd_v2, flags );
}
@@ -1496,7 +1502,9 @@
}
sb = dir->i_sb;
- inode->i_flags = 0;//inode->i_sb->s_flags;
+ inode -> u.reiserfs_i.i_attrs =
+ dir -> u.reiserfs_i.i_attrs & REISERFS_INHERIT_MASK;
+ sd_attrs_to_i_attrs( inode -> u.reiserfs_i.i_attrs, inode );
/* item head of new item */
ih.ih_key.k_dir_id = INODE_PKEY (dir)->k_objectid;
@@ -1555,6 +1563,10 @@
} else
inode->i_gid = current->fsgid;
+ /* symlink cannot be immutable or append only, right? */
+ if( S_ISLNK( inode -> i_mode ) )
+ inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND );
+
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_size = i_size;
inode->i_blocks = (inode->i_size + 511) >> 9;
@@ -2081,6 +2093,50 @@
unlock_kernel();
}
return ret ;
+}
+
+void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode )
+{
+ if( reiserfs_attrs( inode -> i_sb ) ) {
+ if( sd_attrs & REISERFS_SYNC_FL )
+ inode -> i_flags |= S_SYNC;
+ else
+ inode -> i_flags &= ~S_SYNC;
+ if( sd_attrs & REISERFS_IMMUTABLE_FL )
+ inode -> i_flags |= S_IMMUTABLE;
+ else
+ inode -> i_flags &= ~S_IMMUTABLE;
+ if( sd_attrs & REISERFS_NOATIME_FL )
+ inode -> i_flags |= S_NOATIME;
+ else
+ inode -> i_flags &= ~S_NOATIME;
+ if( sd_attrs & REISERFS_NOTAIL_FL )
+ inode->u.reiserfs_i.i_flags |= i_nopack_mask;
+ else
+ inode->u.reiserfs_i.i_flags &= ~i_nopack_mask;
+ }
+}
+
+void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs )
+{
+ if( reiserfs_attrs( inode -> i_sb ) ) {
+ if( inode -> i_flags & S_IMMUTABLE )
+ *sd_attrs |= REISERFS_IMMUTABLE_FL;
+ else
+ *sd_attrs &= ~REISERFS_IMMUTABLE_FL;
+ if( inode -> i_flags & S_SYNC )
+ *sd_attrs |= REISERFS_SYNC_FL;
+ else
+ *sd_attrs &= ~REISERFS_SYNC_FL;
+ if( inode -> i_flags & S_NOATIME )
+ *sd_attrs |= REISERFS_NOATIME_FL;
+ else
+ *sd_attrs &= ~REISERFS_NOATIME_FL;
+ if( inode->u.reiserfs_i.i_flags & i_nopack_mask )
+ *sd_attrs |= REISERFS_NOTAIL_FL;
+ else
+ *sd_attrs &= ~REISERFS_NOTAIL_FL;
+ }
}
struct address_space_operations reiserfs_address_space_operations = {
diff -uNr linux-2.4.18.o1/fs/reiserfs/ioctl.c linux-2.4.18.o/fs/reiserfs/ioctl.c
--- linux-2.4.18.o1/fs/reiserfs/ioctl.c Tue Feb 26 15:52:56 2002
+++ linux-2.4.18.o/fs/reiserfs/ioctl.c Thu Feb 28 19:25:22 2002
@@ -14,17 +14,70 @@
** supported commands:
** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
** and prevent packing file (argument arg has to be non-zero)
-** 2) That's all for a while ...
+** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
+** 3) That's all for a while ...
*/
int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
unsigned long arg)
{
+ unsigned int flags;
+
switch (cmd) {
case REISERFS_IOC_UNPACK:
+ if( S_ISREG( inode -> i_mode ) ) {
if (arg)
return reiserfs_unpack (inode, filp);
+ else
+ return 0;
+ } else
+ return -ENOTTY;
+ /* following two cases are taken from fs/ext2/ioctl.c by Remy
+ Card (
[email protected]) */
+ case REISERFS_IOC_GETFLAGS:
+ flags = inode -> u.reiserfs_i.i_attrs;
+ i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
+ return put_user(flags, (int *) arg);
+ case REISERFS_IOC_SETFLAGS: {
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EPERM;
+
+ if (get_user(flags, (int *) arg))
+ return -EFAULT;
+
+ if ( ( flags & REISERFS_IMMUTABLE_FL ) &&
+ !capable( CAP_LINUX_IMMUTABLE ) )
+ return -EPERM;
- default:
+ if( ( flags & REISERFS_NOTAIL_FL ) &&
+ S_ISREG( inode -> i_mode ) ) {
+ int result;
+
+ result = reiserfs_unpack( inode, filp );
+ if( result )
+ return result;
+ }
+ sd_attrs_to_i_attrs( flags, inode );
+ inode -> u.reiserfs_i.i_attrs = flags;
+ inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ return 0;
+ }
+ case REISERFS_IOC_GETVERSION:
+ return put_user(inode->i_generation, (int *) arg);
+ case REISERFS_IOC_SETVERSION:
+ if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+ return -EPERM;
+ if (IS_RDONLY(inode))
+ return -EROFS;
+ if (get_user(inode->i_generation, (int *) arg))
+ return -EFAULT;
+ inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ return 0;
+ default:
return -ENOTTY;
}
}
@@ -43,7 +96,8 @@
unsigned long blocksize = inode->i_sb->s_blocksize ;
if (inode->i_size == 0) {
- return -EINVAL ;
+ inode->u.reiserfs_i.i_flags |= i_nopack_mask;
+ return 0 ;
}
/* ioctl already done */
if (inode->u.reiserfs_i.i_flags & i_nopack_mask) {
diff -uNr linux-2.4.18.o1/fs/reiserfs/procfs.c linux-2.4.18.o/fs/reiserfs/procfs.c
--- linux-2.4.18.o1/fs/reiserfs/procfs.c Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/fs/reiserfs/procfs.c Thu Feb 28 19:25:22 2002
@@ -354,6 +354,7 @@
struct reiserfs_sb_info *sb_info;
struct reiserfs_super_block *rs;
int hash_code;
+ __u32 flags;
int len = 0;
sb = procinfo_prologue( ( kdev_t ) ( long ) data );
@@ -362,6 +363,7 @@
sb_info = &sb->u.reiserfs_sb;
rs = sb_info -> s_rs;
hash_code = DFL( s_hash_function_code );
+ flags = DFL( s_flags );
len += sprintf( &buffer[ len ],
"block_count: \t%i\n"
@@ -375,7 +377,8 @@
"hash: \t%s\n"
"tree_height: \t%i\n"
"bmap_nr: \t%i\n"
- "version: \t%i\n",
+ "version: \t%i\n"
+ "flags: \t%x[%s]\n",
DFL( s_block_count ),
DFL( s_free_blocks ),
@@ -391,7 +394,10 @@
( hash_code == UNSET_HASH ) ? "unset" : "unknown",
DF( s_tree_height ),
DF( s_bmap_nr ),
- DF( s_version ) );
+ DF( s_version ),
+ flags,
+ ( flags & reiserfs_attrs_cleared )
+ ? "attrs_cleared" : "" );
procinfo_epilogue( sb );
return reiserfs_proc_tail( len, buffer, start, offset, count, eof );
diff -uNr linux-2.4.18.o1/fs/reiserfs/super.c linux-2.4.18.o/fs/reiserfs/super.c
--- linux-2.4.18.o1/fs/reiserfs/super.c Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/fs/reiserfs/super.c Thu Feb 28 19:26:30 2002
@@ -490,6 +490,8 @@
printk("reiserfs: hash option requires a value\n");
return 0 ;
}
+ } else if (!strcmp (this_char, "attrs")) {
+ set_bit (REISERFS_ATTRS, mount_options);
} else {
printk ("reiserfs: Unrecognized mount option %s\n", this_char);
return 0;
@@ -504,6 +506,24 @@
}
+static void handle_attrs( struct super_block *s )
+{
+ struct reiserfs_super_block * rs;
+
+ if( reiserfs_attrs( s ) ) {
+ rs = SB_DISK_SUPER_BLOCK (s);
+ if( old_format_only(s) ) {
+ reiserfs_warning( "reiserfs: cannot support attributes on 3.5.x disk format\n" );
+ s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
+ return;
+ }
+ if( !( le32_to_cpu( rs -> s_flags ) & reiserfs_attrs_cleared ) ) {
+ reiserfs_warning( "reiserfs: cannot support attributes until flag is set in super-block\n" );
+ s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
+ }
+ }
+}
+
//
// a portion of this function, particularly the VFS interface portion,
// was derived from minix or ext2's analog and evolved as the
@@ -533,8 +553,11 @@
SET_OPT( REISERFS_NO_UNHASHED_RELOCATION, mount_options, s );
SET_OPT( REISERFS_HASHED_RELOCATION, mount_options, s );
SET_OPT( REISERFS_TEST4, mount_options, s );
+ SET_OPT( REISERFS_ATTRS, mount_options, s );
#undef SET_OPT
+ handle_attrs( s );
+
if(blocks) {
int rc = reiserfs_resize(s, blocks);
if (rc != 0)
@@ -962,6 +985,8 @@
old_format = 1;
}
+ rs = SB_DISK_SUPER_BLOCK (s);
+
s->u.reiserfs_sb.s_mount_state = SB_REISERFS_STATE(s);
s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
@@ -1061,6 +1086,8 @@
}
// mark hash in super block: it could be unset. overwrite should be ok
set_sb_hash_function_code( rs, function2code(s->u.reiserfs_sb.s_hash_function ) );
+
+ handle_attrs( s );
reiserfs_proc_info_init( s );
reiserfs_proc_register( s, "version", reiserfs_version_in_proc );
diff -uNr linux-2.4.18.o1/include/linux/reiserfs_fs.h linux-2.4.18.o/include/linux/reiserfs_fs.h
--- linux-2.4.18.o1/include/linux/reiserfs_fs.h Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/include/linux/reiserfs_fs.h Thu Feb 28 19:25:22 2002
@@ -717,11 +717,41 @@
#define set_sd_v1_first_direct_byte(sdp,v) \
((sdp)->sd_first_direct_byte = cpu_to_le32(v))
+#include <linux/ext2_fs.h>
+
+/* inode flags stored in sd_attrs (nee sd_reserved) */
+
+/* we want common flags to have the same values as in ext2,
+ so chattr(1) will work without problems */
+#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
+#define REISERFS_SYNC_FL EXT2_SYNC_FL
+#define REISERFS_NOATIME_FL EXT2_NOATIME_FL
+#define REISERFS_NODUMP_FL EXT2_NODUMP_FL
+#define REISERFS_SECRM_FL EXT2_SECRM_FL
+#define REISERFS_UNRM_FL EXT2_UNRM_FL
+#define REISERFS_COMPR_FL EXT2_COMPR_FL
+/* persistent flag to disable tails on per-file basic.
+ Note, that is inheritable: mark directory with this and
+ all new files inside will not have tails.
+
+ Teodore Tso allocated EXT2_NODUMP_FL (0x00008000) for this. Change
+ numeric constant to ext2 macro when available. */
+#define REISERFS_NOTAIL_FL (0x00008000) /* EXT2_NOTAIL_FL */
+
+/* persistent flags that file inherits from the parent directory */
+#define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \
+ REISERFS_SYNC_FL | \
+ REISERFS_NOATIME_FL | \
+ REISERFS_NODUMP_FL | \
+ REISERFS_SECRM_FL | \
+ REISERFS_COMPR_FL | \
+ REISERFS_NOTAIL_FL )
+
/* Stat Data on disk (reiserfs version of UFS disk inode minus the
address blocks) */
struct stat_data {
__u16 sd_mode; /* file type, permissions */
- __u16 sd_reserved;
+ __u16 sd_attrs; /* persistent inode flags */
__u32 sd_nlink; /* number of hard links */
__u64 sd_size; /* file size */
__u32 sd_uid; /* owner */
@@ -774,6 +804,8 @@
#define set_sd_v2_rdev(sdp,v) ((sdp)->u.sd_rdev = cpu_to_le32(v))
#define sd_v2_generation(sdp) (le32_to_cpu((sdp)->u.sd_generation))
#define set_sd_v2_generation(sdp,v) ((sdp)->u.sd_generation = cpu_to_le32(v))
+#define sd_v2_attrs(sdp) (le16_to_cpu((sdp)->sd_attrs))
+#define set_sd_v2_attrs(sdp,v) ((sdp)->sd_attrs = cpu_to_le16(v))
/***************************************************************************/
@@ -1700,6 +1732,9 @@
int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode);
void reiserfs_update_sd (struct reiserfs_transaction_handle *th, struct inode * inode);
+void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode );
+void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
+
/* namei.c */
inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
int search_by_entry_key (struct super_block * sb, const struct cpu_key * key,
@@ -1924,6 +1959,12 @@
/* ioctl's command */
#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long)
+/* define following flags to be the same as in ext2, so that chattr(1),
+ lsattr(1) will work with us. */
+#define REISERFS_IOC_GETFLAGS EXT2_IOC_GETFLAGS
+#define REISERFS_IOC_SETFLAGS EXT2_IOC_SETFLAGS
+#define REISERFS_IOC_GETVERSION EXT2_IOC_GETVERSION
+#define REISERFS_IOC_SETVERSION EXT2_IOC_SETVERSION
#endif /* _LINUX_REISER_FS_H */
diff -uNr linux-2.4.18.o1/include/linux/reiserfs_fs_i.h linux-2.4.18.o/include/linux/reiserfs_fs_i.h
--- linux-2.4.18.o1/include/linux/reiserfs_fs_i.h Tue Feb 26 15:52:56 2002
+++ linux-2.4.18.o/include/linux/reiserfs_fs_i.h Thu Feb 28 19:25:22 2002
@@ -33,6 +33,9 @@
__u32 i_first_direct_byte; // offset of first byte stored in direct item.
+ /* copy of persistent inode flags read from sd_attrs. */
+ __u32 i_attrs;
+
int i_prealloc_block; /* first unused block of a sequence of unused blocks */
int i_prealloc_count; /* length of that sequence */
struct list_head i_prealloc_list; /* per-transaction list of inodes which
diff -uNr linux-2.4.18.o1/include/linux/reiserfs_fs_sb.h linux-2.4.18.o/include/linux/reiserfs_fs_sb.h
--- linux-2.4.18.o1/include/linux/reiserfs_fs_sb.h Thu Feb 28 19:24:40 2002
+++ linux-2.4.18.o/include/linux/reiserfs_fs_sb.h Thu Feb 28 19:25:22 2002
@@ -70,6 +70,10 @@
* there as well. */
} __attribute__ ((__packed__));
+typedef enum {
+ reiserfs_attrs_cleared = 0x00000001,
+} reiserfs_super_block_flags;
+
#define SB_SIZE (sizeof(struct reiserfs_super_block))
/* struct reiserfs_super_block accessors/mutators
* since this is a disk structure, it will always be in
@@ -484,6 +488,8 @@
#define REISERFS_TEST3 13
#define REISERFS_TEST4 14
+#define REISERFS_ATTRS (15)
+
#define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH))
#define reiserfs_rupasov_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_RUPASOV_HASH))
#define reiserfs_tea_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_TEA_HASH))
@@ -496,6 +502,7 @@
#define dont_have_tails(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << NOTAIL))
#define replay_only(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REPLAYONLY))
#define reiserfs_dont_log(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NOLOG))
+#define reiserfs_attrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_ATTRS))
#define old_format_only(s) ((s)->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5))
#define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT))