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 #include <cluster/masklog.h>
24 #include "refcounttree.h"
26 #include <linux/ext2_fs.h>
28 #define o2info_from_user(a, b) \
29 copy_from_user(&(a), (b), sizeof(a))
30 #define o2info_to_user(a, b) \
31 copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
34 * This call is void because we are already reporting an error that may
35 * be -EFAULT. The error will be returned from the ioctl(2) call. It's
36 * just a best-effort to tell userspace that this request caused the error.
38 static inline void __o2info_set_request_error(struct ocfs2_info_request
*kreq
,
39 struct ocfs2_info_request __user
*req
)
41 kreq
->ir_flags
|= OCFS2_INFO_FL_ERROR
;
42 (void)put_user(kreq
->ir_flags
, (__u32 __user
*)&(req
->ir_flags
));
45 #define o2info_set_request_error(a, b) \
46 __o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
48 static inline void __o2info_set_request_filled(struct ocfs2_info_request
*req
)
50 req
->ir_flags
|= OCFS2_INFO_FL_FILLED
;
53 #define o2info_set_request_filled(a) \
54 __o2info_set_request_filled((struct ocfs2_info_request *)&(a))
56 static inline void __o2info_clear_request_filled(struct ocfs2_info_request
*req
)
58 req
->ir_flags
&= ~OCFS2_INFO_FL_FILLED
;
61 #define o2info_clear_request_filled(a) \
62 __o2info_clear_request_filled((struct ocfs2_info_request *)&(a))
64 static int ocfs2_get_inode_attr(struct inode
*inode
, unsigned *flags
)
68 status
= ocfs2_inode_lock(inode
, NULL
, 0);
73 ocfs2_get_inode_flags(OCFS2_I(inode
));
74 *flags
= OCFS2_I(inode
)->ip_attr
;
75 ocfs2_inode_unlock(inode
, 0);
80 static int ocfs2_set_inode_attr(struct inode
*inode
, unsigned flags
,
83 struct ocfs2_inode_info
*ocfs2_inode
= OCFS2_I(inode
);
84 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
85 handle_t
*handle
= NULL
;
86 struct buffer_head
*bh
= NULL
;
90 mutex_lock(&inode
->i_mutex
);
92 status
= ocfs2_inode_lock(inode
, &bh
, 1);
99 if (!inode_owner_or_capable(inode
))
102 if (!S_ISDIR(inode
->i_mode
))
103 flags
&= ~OCFS2_DIRSYNC_FL
;
105 handle
= ocfs2_start_trans(osb
, OCFS2_INODE_UPDATE_CREDITS
);
106 if (IS_ERR(handle
)) {
107 status
= PTR_ERR(handle
);
112 oldflags
= ocfs2_inode
->ip_attr
;
113 flags
= flags
& mask
;
114 flags
|= oldflags
& ~mask
;
117 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
118 * the relevant capability.
121 if ((oldflags
& OCFS2_IMMUTABLE_FL
) || ((flags
^ oldflags
) &
122 (OCFS2_APPEND_FL
| OCFS2_IMMUTABLE_FL
))) {
123 if (!capable(CAP_LINUX_IMMUTABLE
))
127 ocfs2_inode
->ip_attr
= flags
;
128 ocfs2_set_inode_flags(inode
);
130 status
= ocfs2_mark_inode_dirty(handle
, inode
, bh
);
134 ocfs2_commit_trans(osb
, handle
);
136 ocfs2_inode_unlock(inode
, 1);
138 mutex_unlock(&inode
->i_mutex
);
145 int ocfs2_info_handle_blocksize(struct inode
*inode
,
146 struct ocfs2_info_request __user
*req
)
148 int status
= -EFAULT
;
149 struct ocfs2_info_blocksize oib
;
151 if (o2info_from_user(oib
, req
))
154 oib
.ib_blocksize
= inode
->i_sb
->s_blocksize
;
156 o2info_set_request_filled(oib
);
158 if (o2info_to_user(oib
, req
))
164 o2info_set_request_error(oib
, req
);
169 int ocfs2_info_handle_clustersize(struct inode
*inode
,
170 struct ocfs2_info_request __user
*req
)
172 int status
= -EFAULT
;
173 struct ocfs2_info_clustersize oic
;
174 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
176 if (o2info_from_user(oic
, req
))
179 oic
.ic_clustersize
= osb
->s_clustersize
;
181 o2info_set_request_filled(oic
);
183 if (o2info_to_user(oic
, req
))
189 o2info_set_request_error(oic
, req
);
194 int ocfs2_info_handle_maxslots(struct inode
*inode
,
195 struct ocfs2_info_request __user
*req
)
197 int status
= -EFAULT
;
198 struct ocfs2_info_maxslots oim
;
199 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
201 if (o2info_from_user(oim
, req
))
204 oim
.im_max_slots
= osb
->max_slots
;
206 o2info_set_request_filled(oim
);
208 if (o2info_to_user(oim
, req
))
214 o2info_set_request_error(oim
, req
);
219 int ocfs2_info_handle_label(struct inode
*inode
,
220 struct ocfs2_info_request __user
*req
)
222 int status
= -EFAULT
;
223 struct ocfs2_info_label oil
;
224 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
226 if (o2info_from_user(oil
, req
))
229 memcpy(oil
.il_label
, osb
->vol_label
, OCFS2_MAX_VOL_LABEL_LEN
);
231 o2info_set_request_filled(oil
);
233 if (o2info_to_user(oil
, req
))
239 o2info_set_request_error(oil
, req
);
244 int ocfs2_info_handle_uuid(struct inode
*inode
,
245 struct ocfs2_info_request __user
*req
)
247 int status
= -EFAULT
;
248 struct ocfs2_info_uuid oiu
;
249 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
251 if (o2info_from_user(oiu
, req
))
254 memcpy(oiu
.iu_uuid_str
, osb
->uuid_str
, OCFS2_TEXT_UUID_LEN
+ 1);
256 o2info_set_request_filled(oiu
);
258 if (o2info_to_user(oiu
, req
))
264 o2info_set_request_error(oiu
, req
);
269 int ocfs2_info_handle_fs_features(struct inode
*inode
,
270 struct ocfs2_info_request __user
*req
)
272 int status
= -EFAULT
;
273 struct ocfs2_info_fs_features oif
;
274 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
276 if (o2info_from_user(oif
, req
))
279 oif
.if_compat_features
= osb
->s_feature_compat
;
280 oif
.if_incompat_features
= osb
->s_feature_incompat
;
281 oif
.if_ro_compat_features
= osb
->s_feature_ro_compat
;
283 o2info_set_request_filled(oif
);
285 if (o2info_to_user(oif
, req
))
291 o2info_set_request_error(oif
, req
);
296 int ocfs2_info_handle_journal_size(struct inode
*inode
,
297 struct ocfs2_info_request __user
*req
)
299 int status
= -EFAULT
;
300 struct ocfs2_info_journal_size oij
;
301 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
303 if (o2info_from_user(oij
, req
))
306 oij
.ij_journal_size
= osb
->journal
->j_inode
->i_size
;
308 o2info_set_request_filled(oij
);
310 if (o2info_to_user(oij
, req
))
316 o2info_set_request_error(oij
, req
);
321 int ocfs2_info_handle_unknown(struct inode
*inode
,
322 struct ocfs2_info_request __user
*req
)
324 int status
= -EFAULT
;
325 struct ocfs2_info_request oir
;
327 if (o2info_from_user(oir
, req
))
330 o2info_clear_request_filled(oir
);
332 if (o2info_to_user(oir
, req
))
338 o2info_set_request_error(oir
, req
);
344 * Validate and distinguish OCFS2_IOC_INFO requests.
346 * - validate the magic number.
347 * - distinguish different requests.
348 * - validate size of different requests.
350 int ocfs2_info_handle_request(struct inode
*inode
,
351 struct ocfs2_info_request __user
*req
)
353 int status
= -EFAULT
;
354 struct ocfs2_info_request oir
;
356 if (o2info_from_user(oir
, req
))
360 if (oir
.ir_magic
!= OCFS2_INFO_MAGIC
)
363 switch (oir
.ir_code
) {
364 case OCFS2_INFO_BLOCKSIZE
:
365 if (oir
.ir_size
== sizeof(struct ocfs2_info_blocksize
))
366 status
= ocfs2_info_handle_blocksize(inode
, req
);
368 case OCFS2_INFO_CLUSTERSIZE
:
369 if (oir
.ir_size
== sizeof(struct ocfs2_info_clustersize
))
370 status
= ocfs2_info_handle_clustersize(inode
, req
);
372 case OCFS2_INFO_MAXSLOTS
:
373 if (oir
.ir_size
== sizeof(struct ocfs2_info_maxslots
))
374 status
= ocfs2_info_handle_maxslots(inode
, req
);
376 case OCFS2_INFO_LABEL
:
377 if (oir
.ir_size
== sizeof(struct ocfs2_info_label
))
378 status
= ocfs2_info_handle_label(inode
, req
);
380 case OCFS2_INFO_UUID
:
381 if (oir
.ir_size
== sizeof(struct ocfs2_info_uuid
))
382 status
= ocfs2_info_handle_uuid(inode
, req
);
384 case OCFS2_INFO_FS_FEATURES
:
385 if (oir
.ir_size
== sizeof(struct ocfs2_info_fs_features
))
386 status
= ocfs2_info_handle_fs_features(inode
, req
);
388 case OCFS2_INFO_JOURNAL_SIZE
:
389 if (oir
.ir_size
== sizeof(struct ocfs2_info_journal_size
))
390 status
= ocfs2_info_handle_journal_size(inode
, req
);
393 status
= ocfs2_info_handle_unknown(inode
, req
);
401 int ocfs2_get_request_ptr(struct ocfs2_info
*info
, int idx
,
402 u64
*req_addr
, int compat_flag
)
404 int status
= -EFAULT
;
405 u64 __user
*bp
= NULL
;
410 * pointer bp stores the base address of a pointers array,
411 * which collects all addresses of separate request.
413 bp
= (u64 __user
*)(unsigned long)compat_ptr(info
->oi_requests
);
418 bp
= (u64 __user
*)(unsigned long)(info
->oi_requests
);
420 if (o2info_from_user(*req_addr
, bp
+ idx
))
429 * OCFS2_IOC_INFO handles an array of requests passed from userspace.
431 * ocfs2_info_handle() recevies a large info aggregation, grab and
432 * validate the request count from header, then break it into small
433 * pieces, later specific handlers can handle them one by one.
435 * Idea here is to make each separate request small enough to ensure
436 * a better backward&forward compatibility, since a small piece of
437 * request will be less likely to be broken if disk layout get changed.
439 int ocfs2_info_handle(struct inode
*inode
, struct ocfs2_info
*info
,
444 struct ocfs2_info_request __user
*reqp
;
446 if ((info
->oi_count
> OCFS2_INFO_MAX_REQUEST
) ||
447 (!info
->oi_requests
)) {
452 for (i
= 0; i
< info
->oi_count
; i
++) {
454 status
= ocfs2_get_request_ptr(info
, i
, &req_addr
, compat_flag
);
458 reqp
= (struct ocfs2_info_request
*)(unsigned long)req_addr
;
464 status
= ocfs2_info_handle_request(inode
, reqp
);
473 long ocfs2_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
475 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
479 struct ocfs2_space_resv sr
;
480 struct ocfs2_new_group_input input
;
481 struct reflink_arguments args
;
482 const char *old_path
, *new_path
;
484 struct ocfs2_info info
;
487 case OCFS2_IOC_GETFLAGS
:
488 status
= ocfs2_get_inode_attr(inode
, &flags
);
492 flags
&= OCFS2_FL_VISIBLE
;
493 return put_user(flags
, (int __user
*) arg
);
494 case OCFS2_IOC_SETFLAGS
:
495 if (get_user(flags
, (int __user
*) arg
))
498 status
= mnt_want_write(filp
->f_path
.mnt
);
501 status
= ocfs2_set_inode_attr(inode
, flags
,
502 OCFS2_FL_MODIFIABLE
);
503 mnt_drop_write(filp
->f_path
.mnt
);
505 case OCFS2_IOC_RESVSP
:
506 case OCFS2_IOC_RESVSP64
:
507 case OCFS2_IOC_UNRESVSP
:
508 case OCFS2_IOC_UNRESVSP64
:
509 if (copy_from_user(&sr
, (int __user
*) arg
, sizeof(sr
)))
512 return ocfs2_change_file_space(filp
, cmd
, &sr
);
513 case OCFS2_IOC_GROUP_EXTEND
:
514 if (!capable(CAP_SYS_RESOURCE
))
517 if (get_user(new_clusters
, (int __user
*)arg
))
520 return ocfs2_group_extend(inode
, new_clusters
);
521 case OCFS2_IOC_GROUP_ADD
:
522 case OCFS2_IOC_GROUP_ADD64
:
523 if (!capable(CAP_SYS_RESOURCE
))
526 if (copy_from_user(&input
, (int __user
*) arg
, sizeof(input
)))
529 return ocfs2_group_add(inode
, &input
);
530 case OCFS2_IOC_REFLINK
:
531 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
534 old_path
= (const char *)(unsigned long)args
.old_path
;
535 new_path
= (const char *)(unsigned long)args
.new_path
;
536 preserve
= (args
.preserve
!= 0);
538 return ocfs2_reflink_ioctl(inode
, old_path
, new_path
, preserve
);
540 if (copy_from_user(&info
, (struct ocfs2_info __user
*)arg
,
541 sizeof(struct ocfs2_info
)))
544 return ocfs2_info_handle(inode
, &info
, 0);
551 long ocfs2_compat_ioctl(struct file
*file
, unsigned cmd
, unsigned long arg
)
554 struct reflink_arguments args
;
555 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
556 struct ocfs2_info info
;
559 case OCFS2_IOC32_GETFLAGS
:
560 cmd
= OCFS2_IOC_GETFLAGS
;
562 case OCFS2_IOC32_SETFLAGS
:
563 cmd
= OCFS2_IOC_SETFLAGS
;
565 case OCFS2_IOC_RESVSP
:
566 case OCFS2_IOC_RESVSP64
:
567 case OCFS2_IOC_UNRESVSP
:
568 case OCFS2_IOC_UNRESVSP64
:
569 case OCFS2_IOC_GROUP_EXTEND
:
570 case OCFS2_IOC_GROUP_ADD
:
571 case OCFS2_IOC_GROUP_ADD64
:
573 case OCFS2_IOC_REFLINK
:
574 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
577 preserve
= (args
.preserve
!= 0);
579 return ocfs2_reflink_ioctl(inode
, compat_ptr(args
.old_path
),
580 compat_ptr(args
.new_path
), preserve
);
582 if (copy_from_user(&info
, (struct ocfs2_info __user
*)arg
,
583 sizeof(struct ocfs2_info
)))
586 return ocfs2_info_handle(inode
, &info
, 1);
591 return ocfs2_ioctl(file
, cmd
, arg
);