aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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: