diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/Makefile linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/Makefile --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/Makefile 2004-08-14 12:56:09 +0200 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/Makefile 2006-02-01 07:23:18 +0100 @@ -8,7 +8,8 @@ jfs-y := super.o file.o inode.o namei jfs_xtree.o jfs_imap.o jfs_debug.o jfs_dmap.o \ jfs_unicode.o jfs_dtree.o jfs_inode.o \ jfs_extent.o symlink.o jfs_metapage.o \ - jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o resize.o xattr.o + jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o \ + resize.o xattr.o ioctl.o jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/file.c linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/file.c --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/file.c 2006-01-21 18:28:17 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/file.c 2006-02-01 08:09:10 +0100 @@ -98,6 +98,7 @@ struct inode_operations jfs_file_inode_o .setattr = jfs_setattr, .permission = jfs_permission, #endif + .sync_flags = jfs_sync_flags, }; struct file_operations jfs_file_operations = { @@ -114,4 +115,5 @@ struct file_operations jfs_file_operatio .sendpage = generic_file_sendpage, .fsync = jfs_fsync, .release = jfs_release, + .ioctl = jfs_ioctl, }; diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/inode.c linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/inode.c --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/inode.c 2006-01-21 18:28:14 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/inode.c 2006-02-01 09:15:48 +0100 @@ -56,6 +56,7 @@ void jfs_read_inode(struct inode *inode) inode->i_op = &jfs_file_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); } + jfs_set_inode_flags(inode); } /* diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/ioctl.c linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/ioctl.c --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/ioctl.c 1970-01-01 01:00:00 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/ioctl.c 2006-02-01 09:00:29 +0100 @@ -0,0 +1,111 @@ +/* + * linux/fs/jfs/ioctl.c + * + * Copyright (C) 2006 Herbert Poetzl + * adapted from Remy Card's ext2/ioctl.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jfs_incore.h" +#include "jfs_dinode.h" +#include "jfs_inode.h" + + +static struct { + long jfs_flag; + long ext2_flag; +} jfs_map[] = { + {JFS_NOATIME_FL, EXT2_NOATIME_FL}, + {JFS_DIRSYNC_FL, EXT2_DIRSYNC_FL}, + {JFS_SYNC_FL, EXT2_SYNC_FL}, + {JFS_SECRM_FL, EXT2_SECRM_FL}, + {JFS_UNRM_FL, EXT2_UNRM_FL}, + {JFS_APPEND_FL, EXT2_APPEND_FL}, + {JFS_IMMUTABLE_FL, EXT2_IMMUTABLE_FL}, + {0, 0}, +}; + +static long jfs_map_ext2(unsigned long flags, int from) +{ + int index=0; + long mapped=0; + + while (jfs_map[index].jfs_flag) { + if (from) { + if (jfs_map[index].ext2_flag & flags) + mapped |= jfs_map[index].jfs_flag; + } else { + if (jfs_map[index].jfs_flag & flags) + mapped |= jfs_map[index].ext2_flag; + } + index++; + } + return mapped; +} + + +int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, + unsigned long arg) +{ + struct jfs_inode_info *jfs_inode = JFS_IP(inode); + unsigned int flags; + + switch (cmd) { + case JFS_IOC_GETFLAGS: + flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE; + flags = jfs_map_ext2(flags, 0); + return put_user(flags, (int __user *) arg); + case JFS_IOC_SETFLAGS: { + unsigned int oldflags; + + if (IS_RDONLY(inode) || + (filp && MNT_IS_RDONLY(filp->f_vfsmnt))) + return -EROFS; + + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) + return -EACCES; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + + flags = jfs_map_ext2(flags, 1); + if (!S_ISDIR(inode->i_mode)) + flags &= ~JFS_DIRSYNC_FL; + + oldflags = jfs_inode->mode2; + + /* + * The IMMUTABLE and APPEND_ONLY flags can only be changed by + * the relevant capability. + * + * This test looks nicer. Thanks to Pauline Middelink + */ + if ((oldflags & JFS_IMMUTABLE_FL) || + ((flags ^ oldflags) & (JFS_APPEND_FL | + JFS_IMMUTABLE_FL | JFS_IUNLINK_FL))) { + if (!capable(CAP_LINUX_IMMUTABLE)) + return -EPERM; + } + + flags = flags & JFS_FL_USER_MODIFIABLE; + flags |= oldflags & ~JFS_FL_USER_MODIFIABLE; + jfs_inode->mode2 = flags; + + jfs_set_inode_flags(inode); + inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); + return 0; + } + default: + return -ENOTTY; + } +} + diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_dinode.h linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_dinode.h --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_dinode.h 2004-12-25 01:55:20 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_dinode.h 2006-02-01 09:08:53 +0100 @@ -139,13 +139,39 @@ struct dinode { /* more extended mode bits: attributes for OS/2 */ #define IREADONLY 0x02000000 /* no write access to file */ -#define IARCHIVE 0x40000000 /* file archive bit */ -#define ISYSTEM 0x08000000 /* system file */ #define IHIDDEN 0x04000000 /* hidden file */ -#define IRASH 0x4E000000 /* mask for changeable attributes */ -#define INEWNAME 0x80000000 /* non-8.3 filename format */ +#define ISYSTEM 0x08000000 /* system file */ + #define IDIRECTORY 0x20000000 /* directory (shadow of real bit) */ +#define IARCHIVE 0x40000000 /* file archive bit */ +#define INEWNAME 0x80000000 /* non-8.3 filename format */ + +#define IRASH 0x4E000000 /* mask for changeable attributes */ #define ATTRSHIFT 25 /* bits to shift to move attribute specification to mode position */ +/* extended attributes for Linux */ + +#define JFS_NOATIME_FL 0x00080000 /* do not update atime */ + +#define JFS_DIRSYNC_FL 0x00100000 /* dirsync behaviour */ +#define JFS_SYNC_FL 0x00200000 /* Synchronous updates */ +#define JFS_SECRM_FL 0x00400000 /* Secure deletion */ +#define JFS_UNRM_FL 0x00800000 /* allow for undelete */ + +#define JFS_APPEND_FL 0x01000000 /* writes to file may only append */ +#define JFS_IMMUTABLE_FL 0x02000000 /* Immutable file */ + +#define JFS_BARRIER_FL 0x04000000 /* Barrier for chroot() */ +#define JFS_IUNLINK_FL 0x08000000 /* Immutable unlink */ + +#define JFS_FL_USER_VISIBLE 0x0FF80000 +#define JFS_FL_USER_MODIFIABLE 0x03F80000 +#define JFS_FL_INHERIT 0x0BC80000 + + +#define JFS_IOC_GETFLAGS _IOR('f', 1, long) +#define JFS_IOC_SETFLAGS _IOW('f', 2, long) + + #endif /*_H_JFS_DINODE */ diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_inode.c linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_inode.c --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_inode.c 2006-01-25 05:34:51 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_inode.c 2006-02-01 07:36:26 +0100 @@ -27,6 +27,66 @@ #include "jfs_dinode.h" #include "jfs_debug.h" + +void jfs_set_inode_flags(struct inode *inode) +{ + unsigned int flags = JFS_IP(inode)->mode2; + + inode->i_flags &= ~(S_IMMUTABLE | S_IUNLINK | S_BARRIER | + S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC); + + if (flags & JFS_IMMUTABLE_FL) + inode->i_flags |= S_IMMUTABLE; + if (flags & JFS_IUNLINK_FL) + inode->i_flags |= S_IUNLINK; + if (flags & JFS_BARRIER_FL) + inode->i_flags |= S_BARRIER; + + if (flags & JFS_SYNC_FL) + inode->i_flags |= S_SYNC; + if (flags & JFS_APPEND_FL) + inode->i_flags |= S_APPEND; + if (flags & JFS_NOATIME_FL) + inode->i_flags |= S_NOATIME; + if (flags & JFS_DIRSYNC_FL) + inode->i_flags |= S_DIRSYNC; +} + +int jfs_sync_flags(struct inode *inode) +{ + unsigned int oldflags, newflags; + + oldflags = JFS_IP(inode)->mode2; + newflags = oldflags & ~(JFS_APPEND_FL | + JFS_IMMUTABLE_FL | JFS_IUNLINK_FL | + JFS_BARRIER_FL | JFS_NOATIME_FL | + JFS_SYNC_FL | JFS_DIRSYNC_FL); + + if (IS_APPEND(inode)) + newflags |= JFS_APPEND_FL; + if (IS_IMMUTABLE(inode)) + newflags |= JFS_IMMUTABLE_FL; + if (IS_IUNLINK(inode)) + newflags |= JFS_IUNLINK_FL; + if (IS_BARRIER(inode)) + newflags |= JFS_BARRIER_FL; + + /* we do not want to copy superblock flags */ + if (inode->i_flags & S_NOATIME) + newflags |= JFS_NOATIME_FL; + if (inode->i_flags & S_SYNC) + newflags |= JFS_SYNC_FL; + if (inode->i_flags & S_DIRSYNC) + newflags |= JFS_DIRSYNC_FL; + + if (oldflags ^ newflags) { + JFS_IP(inode)->mode2 = newflags; + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + } + return 0; +} + /* * NAME: ialloc() * @@ -83,10 +143,20 @@ struct inode *ialloc(struct inode *paren } inode->i_mode = mode; - if (S_ISDIR(mode)) - jfs_inode->mode2 = IDIRECTORY | mode; + /* inherit flags from parent */ + jfs_inode->mode2 = JFS_IP(parent)->mode2 & JFS_FL_INHERIT; + + if (S_ISDIR(mode)) { + jfs_inode->mode2 |= IDIRECTORY; + jfs_inode->mode2 &= ~JFS_DIRSYNC_FL; + } + else if (S_ISLNK(mode)) + jfs_inode->mode2 &= + ~(JFS_IMMUTABLE_FL|JFS_APPEND_FL); else - jfs_inode->mode2 = INLINEEA | ISPARSE | mode; + jfs_inode->mode2 |= INLINEEA | ISPARSE; + jfs_inode->mode2 |= mode; + inode->i_blksize = sb->s_blocksize; inode->i_blocks = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; @@ -107,6 +177,7 @@ struct inode *ialloc(struct inode *paren jfs_inode->atlhead = 0; jfs_inode->atltail = 0; jfs_inode->xtlid = 0; + jfs_set_inode_flags(inode); jfs_info("ialloc returns inode = 0x%p\n", inode); diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_inode.h linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_inode.h --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/jfs_inode.h 2005-08-29 22:25:32 +0200 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/jfs_inode.h 2006-02-01 08:13:04 +0100 @@ -20,6 +20,8 @@ extern struct inode *ialloc(struct inode *, umode_t); extern int jfs_fsync(struct file *, struct dentry *, int); +extern int jfs_ioctl(struct inode *, struct file *, + unsigned int, unsigned long); extern void jfs_read_inode(struct inode *); extern int jfs_commit_inode(struct inode *, int); extern int jfs_write_inode(struct inode*, int); @@ -29,6 +31,8 @@ extern void jfs_truncate(struct inode *) extern void jfs_truncate_nolock(struct inode *, loff_t); extern void jfs_free_zero_link(struct inode *); extern struct dentry *jfs_get_parent(struct dentry *dentry); +extern int jfs_sync_flags(struct inode *); +extern void jfs_set_inode_flags(struct inode *); extern struct address_space_operations jfs_aops; extern struct inode_operations jfs_dir_inode_operations; diff -NurpP --minimal linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/namei.c linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/namei.c --- linux-2.6.16-rc1-vs2.1.0.9.4/fs/jfs/namei.c 2006-01-25 05:34:51 +0100 +++ linux-2.6.16-rc1-vs2.1.0.9.5/fs/jfs/namei.c 2006-02-01 08:08:38 +0100 @@ -1519,12 +1519,14 @@ struct inode_operations jfs_dir_inode_op .setattr = jfs_setattr, .permission = jfs_permission, #endif + .sync_flags = jfs_sync_flags, }; struct file_operations jfs_dir_operations = { .read = generic_read_dir, .readdir = jfs_readdir, .fsync = jfs_fsync, + .ioctl = jfs_ioctl, }; static int jfs_ci_hash(struct dentry *dir, struct qstr *this)