2 * linux/fs/ocfs2/ioctl.c
4 * Copyright (C) 2006 Herbert Poetzl
5 * adapted from Remy Card's ext2/ioctl.c
9 #include <linux/mount.h>
10 #include <linux/compat.h>
12 #define MLOG_MASK_PREFIX ML_INODE
13 #include <cluster/masklog.h>
25 #include "refcounttree.h"
27 #include <linux/ext2_fs.h>
29 static int ocfs2_get_inode_attr(struct inode
*inode
, unsigned *flags
)
33 status
= ocfs2_inode_lock(inode
, NULL
, 0);
38 ocfs2_get_inode_flags(OCFS2_I(inode
));
39 *flags
= OCFS2_I(inode
)->ip_attr
;
40 ocfs2_inode_unlock(inode
, 0);
46 static int ocfs2_set_inode_attr(struct inode
*inode
, unsigned flags
,
49 struct ocfs2_inode_info
*ocfs2_inode
= OCFS2_I(inode
);
50 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
51 handle_t
*handle
= NULL
;
52 struct buffer_head
*bh
= NULL
;
56 mutex_lock(&inode
->i_mutex
);
58 status
= ocfs2_inode_lock(inode
, &bh
, 1);
65 if (!is_owner_or_cap(inode
))
68 if (!S_ISDIR(inode
->i_mode
))
69 flags
&= ~OCFS2_DIRSYNC_FL
;
71 handle
= ocfs2_start_trans(osb
, OCFS2_INODE_UPDATE_CREDITS
);
73 status
= PTR_ERR(handle
);
78 oldflags
= ocfs2_inode
->ip_attr
;
80 flags
|= oldflags
& ~mask
;
83 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
84 * the relevant capability.
87 if ((oldflags
& OCFS2_IMMUTABLE_FL
) || ((flags
^ oldflags
) &
88 (OCFS2_APPEND_FL
| OCFS2_IMMUTABLE_FL
))) {
89 if (!capable(CAP_LINUX_IMMUTABLE
))
93 ocfs2_inode
->ip_attr
= flags
;
94 ocfs2_set_inode_flags(inode
);
96 status
= ocfs2_mark_inode_dirty(handle
, inode
, bh
);
100 ocfs2_commit_trans(osb
, handle
);
102 ocfs2_inode_unlock(inode
, 1);
104 mutex_unlock(&inode
->i_mutex
);
112 long ocfs2_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
114 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
118 struct ocfs2_space_resv sr
;
119 struct ocfs2_new_group_input input
;
120 struct reflink_arguments args
;
121 const char *old_path
, *new_path
;
125 case OCFS2_IOC_GETFLAGS
:
126 status
= ocfs2_get_inode_attr(inode
, &flags
);
130 flags
&= OCFS2_FL_VISIBLE
;
131 return put_user(flags
, (int __user
*) arg
);
132 case OCFS2_IOC_SETFLAGS
:
133 if (get_user(flags
, (int __user
*) arg
))
136 status
= mnt_want_write(filp
->f_path
.mnt
);
139 status
= ocfs2_set_inode_attr(inode
, flags
,
140 OCFS2_FL_MODIFIABLE
);
141 mnt_drop_write(filp
->f_path
.mnt
);
143 case OCFS2_IOC_RESVSP
:
144 case OCFS2_IOC_RESVSP64
:
145 case OCFS2_IOC_UNRESVSP
:
146 case OCFS2_IOC_UNRESVSP64
:
147 if (copy_from_user(&sr
, (int __user
*) arg
, sizeof(sr
)))
150 return ocfs2_change_file_space(filp
, cmd
, &sr
);
151 case OCFS2_IOC_GROUP_EXTEND
:
152 if (!capable(CAP_SYS_RESOURCE
))
155 if (get_user(new_clusters
, (int __user
*)arg
))
158 return ocfs2_group_extend(inode
, new_clusters
);
159 case OCFS2_IOC_GROUP_ADD
:
160 case OCFS2_IOC_GROUP_ADD64
:
161 if (!capable(CAP_SYS_RESOURCE
))
164 if (copy_from_user(&input
, (int __user
*) arg
, sizeof(input
)))
167 return ocfs2_group_add(inode
, &input
);
168 case OCFS2_IOC_REFLINK
:
169 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
172 old_path
= (const char *)(unsigned long)args
.old_path
;
173 new_path
= (const char *)(unsigned long)args
.new_path
;
174 preserve
= (args
.preserve
!= 0);
176 return ocfs2_reflink_ioctl(inode
, old_path
, new_path
, preserve
);
183 long ocfs2_compat_ioctl(struct file
*file
, unsigned cmd
, unsigned long arg
)
186 struct reflink_arguments args
;
187 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
190 case OCFS2_IOC32_GETFLAGS
:
191 cmd
= OCFS2_IOC_GETFLAGS
;
193 case OCFS2_IOC32_SETFLAGS
:
194 cmd
= OCFS2_IOC_SETFLAGS
;
196 case OCFS2_IOC_RESVSP
:
197 case OCFS2_IOC_RESVSP64
:
198 case OCFS2_IOC_UNRESVSP
:
199 case OCFS2_IOC_UNRESVSP64
:
200 case OCFS2_IOC_GROUP_EXTEND
:
201 case OCFS2_IOC_GROUP_ADD
:
202 case OCFS2_IOC_GROUP_ADD64
:
204 case OCFS2_IOC_REFLINK
:
205 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
208 preserve
= (args
.preserve
!= 0);
210 return ocfs2_reflink_ioctl(inode
, compat_ptr(args
.old_path
),
211 compat_ptr(args
.new_path
), preserve
);
216 return ocfs2_ioctl(file
, cmd
, arg
);