diff -rup -X dontdiff linux/fs/reiserfs/dir.c linux.patched/fs/reiserfs/dir.c --- linux/fs/reiserfs/dir.c Wed Nov 21 12:02:35 2001 +++ linux.patched/fs/reiserfs/dir.c Tue Nov 20 22:47:11 2001 @@ -20,6 +20,7 @@ struct file_operations reiserfs_dir_oper 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 -rup -X dontdiff linux/fs/reiserfs/inode.c linux.patched/fs/reiserfs/inode.c --- linux/fs/reiserfs/inode.c Wed Nov 21 12:02:35 2001 +++ linux.patched/fs/reiserfs/inode.c Wed Nov 21 12:26:25 2001 @@ -910,6 +910,9 @@ static void init_inode (struct inode * i 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) @@ -937,10 +940,12 @@ static void init_inode (struct inode * i set_inode_item_key_version (inode, KEY_FORMAT_3_5); else set_inode_item_key_version (inode, KEY_FORMAT_3_6); - } - /* nopack = 0, by default */ - inode->u.reiserfs_i.i_flags &= ~i_nopack_mask; + /* read persistemt 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 ); + } pathrelse (path); if (S_ISREG (inode->i_mode)) { @@ -964,6 +969,7 @@ static void init_inode (struct inode * i 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 ); @@ -974,13 +980,13 @@ static void inode2sd (void * sd, struct 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 ); } @@ -1450,7 +1456,9 @@ struct inode * reiserfs_new_inode (struc } 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; @@ -1509,6 +1517,10 @@ struct inode * reiserfs_new_inode (struc } 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; @@ -2028,6 +2040,50 @@ static int reiserfs_commit_write(struct unlock_kernel(); } return ret ; +} + +void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode ) +{ + if( !reiserfs_noattrs( 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_noattrs( 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 -rup -X dontdiff linux/fs/reiserfs/ioctl.c linux.patched/fs/reiserfs/ioctl.c --- linux/fs/reiserfs/ioctl.c Wed Nov 21 12:02:35 2001 +++ linux.patched/fs/reiserfs/ioctl.c Tue Nov 20 22:47:11 2001 @@ -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 (card@masi.ibp.fr) */ + 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 @@ int reiserfs_unpack (struct inode * inod 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 -rup -X dontdiff linux/fs/reiserfs/super.c linux.patched/fs/reiserfs/super.c --- linux/fs/reiserfs/super.c Wed Nov 21 12:02:35 2001 +++ linux.patched/fs/reiserfs/super.c Wed Nov 21 12:27:27 2001 @@ -472,6 +472,8 @@ static int parse_options (char * options printk("reiserfs: hash option requires a value\n"); return 0 ; } + } else if (!strcmp (this_char, "noattrs")) { + set_bit (REISERFS_NOATTRS, mount_options); } else { printk ("reiserfs: Unrecognized mount option %s\n", this_char); return 0; Only in linux.patched/include/linux: modules diff -rup -X dontdiff linux/include/linux/reiserfs_fs.h linux.patched/include/linux/reiserfs_fs.h --- linux/include/linux/reiserfs_fs.h Wed Nov 21 12:02:35 2001 +++ linux.patched/include/linux/reiserfs_fs.h Wed Nov 21 12:38:59 2001 @@ -718,11 +718,41 @@ struct stat_data_v1 #define set_sd_v1_first_direct_byte(sdp,v) \ ((sdp)->sd_first_direct_byte = cpu_to_le32(v)) +#include + +/* 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 */ @@ -775,6 +805,8 @@ struct stat_data { #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)) /***************************************************************************/ @@ -1701,6 +1733,9 @@ struct inode * reiserfs_new_inode (struc 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, @@ -1918,6 +1953,12 @@ int reiserfs_unpack (struct inode * inod /* 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 -rup -X dontdiff linux/include/linux/reiserfs_fs_i.h linux.patched/include/linux/reiserfs_fs_i.h --- linux/include/linux/reiserfs_fs_i.h Wed Nov 21 12:02:35 2001 +++ linux.patched/include/linux/reiserfs_fs_i.h Wed Nov 21 12:33:57 2001 @@ -33,6 +33,9 @@ struct reiserfs_inode_info { __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 -rup -X dontdiff linux/include/linux/reiserfs_fs_sb.h linux.patched/include/linux/reiserfs_fs_sb.h --- linux/include/linux/reiserfs_fs_sb.h Wed Nov 21 12:02:23 2001 +++ linux.patched/include/linux/reiserfs_fs_sb.h Wed Nov 21 12:33:57 2001 @@ -462,6 +462,8 @@ struct reiserfs_sb_info #define REISERFS_TEST3 13 #define REISERFS_TEST4 14 +#define REISERFS_NOATTRS (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)) @@ -474,8 +476,8 @@ struct reiserfs_sb_info #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_noattrs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NOATTRS)) #define old_format_only(s) ((SB_VERSION(s) != REISERFS_VERSION_2) && !((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT))) - void reiserfs_file_buffer (struct buffer_head * bh, int list); int reiserfs_is_super(struct super_block *s) ; .