aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-01-19 12:09:53 -0500
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-03-08 00:58:30 -0500
commitcde98f0f84ccff78e87235cb7b551747d6ad00de (patch)
treeb5cb657b0e0360adf41437819d43a0c9c75912f8 /fs/nilfs2
parentb253a3e4f2b8eed69b804952ef926df0ac788595 (diff)
nilfs2: implement FS_IOC_GETFLAGS/SETFLAGS/GETVERSION
Add support for the standard attributes set via chattr and read via lsattr. These attributes are already in the flags value in the nilfs2 inode, but currently we don't have any ioctl commands that expose them to the userland. Collaterally, this adds the FS_IOC_GETVERSION ioctl for getting i_generation, which allows users to list the file's generation number with "lsattr -v". Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r--fs/nilfs2/ioctl.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 496738963fdb..3aad6413aba4 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -97,6 +97,70 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
97 return ret; 97 return ret;
98} 98}
99 99
100static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
101{
102 unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
103
104 return put_user(flags, (int __user *)argp);
105}
106
107static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
108 void __user *argp)
109{
110 struct nilfs_transaction_info ti;
111 unsigned int flags, oldflags;
112 int ret;
113
114 if (!is_owner_or_cap(inode))
115 return -EACCES;
116
117 if (get_user(flags, (int __user *)argp))
118 return -EFAULT;
119
120 ret = mnt_want_write(filp->f_path.mnt);
121 if (ret)
122 return ret;
123
124 flags = nilfs_mask_flags(inode->i_mode, flags);
125
126 mutex_lock(&inode->i_mutex);
127
128 oldflags = NILFS_I(inode)->i_flags;
129
130 /*
131 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
132 * relevant capability.
133 */
134 ret = -EPERM;
135 if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
136 !capable(CAP_LINUX_IMMUTABLE))
137 goto out;
138
139 ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
140 if (ret)
141 goto out;
142
143 NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
144 (flags & FS_FL_USER_MODIFIABLE);
145
146 nilfs_set_inode_flags(inode);
147 inode->i_ctime = CURRENT_TIME;
148 if (IS_SYNC(inode))
149 nilfs_set_transaction_flag(NILFS_TI_SYNC);
150
151 nilfs_mark_inode_dirty(inode);
152 ret = nilfs_transaction_commit(inode->i_sb);
153out:
154 mutex_unlock(&inode->i_mutex);
155 mnt_drop_write(filp->f_path.mnt);
156 return ret;
157}
158
159static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
160{
161 return put_user(inode->i_generation, (int __user *)argp);
162}
163
100static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, 164static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
101 unsigned int cmd, void __user *argp) 165 unsigned int cmd, void __user *argp)
102{ 166{
@@ -666,6 +730,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
666 void __user *argp = (void __user *)arg; 730 void __user *argp = (void __user *)arg;
667 731
668 switch (cmd) { 732 switch (cmd) {
733 case FS_IOC_GETFLAGS:
734 return nilfs_ioctl_getflags(inode, argp);
735 case FS_IOC_SETFLAGS:
736 return nilfs_ioctl_setflags(inode, filp, argp);
737 case FS_IOC_GETVERSION:
738 return nilfs_ioctl_getversion(inode, argp);
669 case NILFS_IOCTL_CHANGE_CPMODE: 739 case NILFS_IOCTL_CHANGE_CPMODE:
670 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); 740 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
671 case NILFS_IOCTL_DELETE_CHECKPOINT: 741 case NILFS_IOCTL_DELETE_CHECKPOINT: