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 #define o2info_from_user(a, b) \
30 copy_from_user(&(a), (b), sizeof(a))
31 #define o2info_to_user(a, b) \
32 copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
35 * This call is void because we are already reporting an error that may
36 * be -EFAULT. The error will be returned from the ioctl(2) call. It's
37 * just a best-effort to tell userspace that this request caused the error.
39 static inline void __o2info_set_request_error(struct ocfs2_info_request
*kreq
,
40 struct ocfs2_info_request __user
*req
)
42 kreq
->ir_flags
|= OCFS2_INFO_FL_ERROR
;
43 (void)put_user(kreq
->ir_flags
, (__u32 __user
*)&(req
->ir_flags
));
46 #define o2info_set_request_error(a, b) \
47 __o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
49 static int ocfs2_get_inode_attr(struct inode
*inode
, unsigned *flags
)
53 status
= ocfs2_inode_lock(inode
, NULL
, 0);
58 ocfs2_get_inode_flags(OCFS2_I(inode
));
59 *flags
= OCFS2_I(inode
)->ip_attr
;
60 ocfs2_inode_unlock(inode
, 0);
66 static int ocfs2_set_inode_attr(struct inode
*inode
, unsigned flags
,
69 struct ocfs2_inode_info
*ocfs2_inode
= OCFS2_I(inode
);
70 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
71 handle_t
*handle
= NULL
;
72 struct buffer_head
*bh
= NULL
;
76 mutex_lock(&inode
->i_mutex
);
78 status
= ocfs2_inode_lock(inode
, &bh
, 1);
85 if (!is_owner_or_cap(inode
))
88 if (!S_ISDIR(inode
->i_mode
))
89 flags
&= ~OCFS2_DIRSYNC_FL
;
91 handle
= ocfs2_start_trans(osb
, OCFS2_INODE_UPDATE_CREDITS
);
93 status
= PTR_ERR(handle
);
98 oldflags
= ocfs2_inode
->ip_attr
;
100 flags
|= oldflags
& ~mask
;
103 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
104 * the relevant capability.
107 if ((oldflags
& OCFS2_IMMUTABLE_FL
) || ((flags
^ oldflags
) &
108 (OCFS2_APPEND_FL
| OCFS2_IMMUTABLE_FL
))) {
109 if (!capable(CAP_LINUX_IMMUTABLE
))
113 ocfs2_inode
->ip_attr
= flags
;
114 ocfs2_set_inode_flags(inode
);
116 status
= ocfs2_mark_inode_dirty(handle
, inode
, bh
);
120 ocfs2_commit_trans(osb
, handle
);
122 ocfs2_inode_unlock(inode
, 1);
124 mutex_unlock(&inode
->i_mutex
);
132 int ocfs2_info_handle_blocksize(struct inode
*inode
,
133 struct ocfs2_info_request __user
*req
)
135 int status
= -EFAULT
;
136 struct ocfs2_info_blocksize oib
;
138 if (o2info_from_user(oib
, req
))
141 oib
.ib_blocksize
= inode
->i_sb
->s_blocksize
;
142 oib
.ib_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
144 if (o2info_to_user(oib
, req
))
150 o2info_set_request_error(oib
, req
);
155 int ocfs2_info_handle_clustersize(struct inode
*inode
,
156 struct ocfs2_info_request __user
*req
)
158 int status
= -EFAULT
;
159 struct ocfs2_info_clustersize oic
;
160 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
162 if (o2info_from_user(oic
, req
))
165 oic
.ic_clustersize
= osb
->s_clustersize
;
166 oic
.ic_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
168 if (o2info_to_user(oic
, req
))
174 o2info_set_request_error(oic
, req
);
179 int ocfs2_info_handle_maxslots(struct inode
*inode
,
180 struct ocfs2_info_request __user
*req
)
182 int status
= -EFAULT
;
183 struct ocfs2_info_maxslots oim
;
184 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
186 if (o2info_from_user(oim
, req
))
189 oim
.im_max_slots
= osb
->max_slots
;
190 oim
.im_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
192 if (o2info_to_user(oim
, req
))
198 o2info_set_request_error(oim
, req
);
203 int ocfs2_info_handle_label(struct inode
*inode
,
204 struct ocfs2_info_request __user
*req
)
206 int status
= -EFAULT
;
207 struct ocfs2_info_label oil
;
208 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
210 if (o2info_from_user(oil
, req
))
213 memcpy(oil
.il_label
, osb
->vol_label
, OCFS2_MAX_VOL_LABEL_LEN
);
214 oil
.il_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
216 if (o2info_to_user(oil
, req
))
222 o2info_set_request_error(oil
, req
);
227 int ocfs2_info_handle_uuid(struct inode
*inode
,
228 struct ocfs2_info_request __user
*req
)
230 int status
= -EFAULT
;
231 struct ocfs2_info_uuid oiu
;
232 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
234 if (o2info_from_user(oiu
, req
))
237 memcpy(oiu
.iu_uuid_str
, osb
->uuid_str
, OCFS2_TEXT_UUID_LEN
+ 1);
238 oiu
.iu_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
240 if (o2info_to_user(oiu
, req
))
246 o2info_set_request_error(oiu
, req
);
251 int ocfs2_info_handle_fs_features(struct inode
*inode
,
252 struct ocfs2_info_request __user
*req
)
254 int status
= -EFAULT
;
255 struct ocfs2_info_fs_features oif
;
256 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
258 if (o2info_from_user(oif
, req
))
261 oif
.if_compat_features
= osb
->s_feature_compat
;
262 oif
.if_incompat_features
= osb
->s_feature_incompat
;
263 oif
.if_ro_compat_features
= osb
->s_feature_ro_compat
;
264 oif
.if_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
266 if (o2info_to_user(oif
, req
))
272 o2info_set_request_error(oif
, req
);
277 int ocfs2_info_handle_journal_size(struct inode
*inode
,
278 struct ocfs2_info_request __user
*req
)
280 int status
= -EFAULT
;
281 struct ocfs2_info_journal_size oij
;
282 struct ocfs2_super
*osb
= OCFS2_SB(inode
->i_sb
);
284 if (o2info_from_user(oij
, req
))
287 oij
.ij_journal_size
= osb
->journal
->j_inode
->i_size
;
289 oij
.ij_req
.ir_flags
|= OCFS2_INFO_FL_FILLED
;
291 if (o2info_to_user(oij
, req
))
297 o2info_set_request_error(oij
, req
);
302 int ocfs2_info_handle_unknown(struct inode
*inode
,
303 struct ocfs2_info_request __user
*req
)
305 int status
= -EFAULT
;
306 struct ocfs2_info_request oir
;
308 if (o2info_from_user(oir
, req
))
311 oir
.ir_flags
&= ~OCFS2_INFO_FL_FILLED
;
313 if (o2info_to_user(oir
, req
))
319 o2info_set_request_error(oir
, req
);
325 * Validate and distinguish OCFS2_IOC_INFO requests.
327 * - validate the magic number.
328 * - distinguish different requests.
329 * - validate size of different requests.
331 int ocfs2_info_handle_request(struct inode
*inode
,
332 struct ocfs2_info_request __user
*req
)
334 int status
= -EFAULT
;
335 struct ocfs2_info_request oir
;
337 if (o2info_from_user(oir
, req
))
341 if (oir
.ir_magic
!= OCFS2_INFO_MAGIC
)
344 switch (oir
.ir_code
) {
345 case OCFS2_INFO_BLOCKSIZE
:
346 if (oir
.ir_size
== sizeof(struct ocfs2_info_blocksize
))
347 status
= ocfs2_info_handle_blocksize(inode
, req
);
349 case OCFS2_INFO_CLUSTERSIZE
:
350 if (oir
.ir_size
== sizeof(struct ocfs2_info_clustersize
))
351 status
= ocfs2_info_handle_clustersize(inode
, req
);
353 case OCFS2_INFO_MAXSLOTS
:
354 if (oir
.ir_size
== sizeof(struct ocfs2_info_maxslots
))
355 status
= ocfs2_info_handle_maxslots(inode
, req
);
357 case OCFS2_INFO_LABEL
:
358 if (oir
.ir_size
== sizeof(struct ocfs2_info_label
))
359 status
= ocfs2_info_handle_label(inode
, req
);
361 case OCFS2_INFO_UUID
:
362 if (oir
.ir_size
== sizeof(struct ocfs2_info_uuid
))
363 status
= ocfs2_info_handle_uuid(inode
, req
);
365 case OCFS2_INFO_FS_FEATURES
:
366 if (oir
.ir_size
== sizeof(struct ocfs2_info_fs_features
))
367 status
= ocfs2_info_handle_fs_features(inode
, req
);
369 case OCFS2_INFO_JOURNAL_SIZE
:
370 if (oir
.ir_size
== sizeof(struct ocfs2_info_journal_size
))
371 status
= ocfs2_info_handle_journal_size(inode
, req
);
374 status
= ocfs2_info_handle_unknown(inode
, req
);
382 int ocfs2_get_request_ptr(struct ocfs2_info
*info
, int idx
,
383 u64
*req_addr
, int compat_flag
)
385 int status
= -EFAULT
;
386 u64 __user
*bp
= NULL
;
391 * pointer bp stores the base address of a pointers array,
392 * which collects all addresses of separate request.
394 bp
= (u64 __user
*)(unsigned long)compat_ptr(info
->oi_requests
);
399 bp
= (u64 __user
*)(unsigned long)(info
->oi_requests
);
401 if (o2info_from_user(*req_addr
, bp
+ idx
))
410 * OCFS2_IOC_INFO handles an array of requests passed from userspace.
412 * ocfs2_info_handle() recevies a large info aggregation, grab and
413 * validate the request count from header, then break it into small
414 * pieces, later specific handlers can handle them one by one.
416 * Idea here is to make each separate request small enough to ensure
417 * a better backward&forward compatibility, since a small piece of
418 * request will be less likely to be broken if disk layout get changed.
420 int ocfs2_info_handle(struct inode
*inode
, struct ocfs2_info
*info
,
425 struct ocfs2_info_request __user
*reqp
;
427 if ((info
->oi_count
> OCFS2_INFO_MAX_REQUEST
) ||
428 (!info
->oi_requests
)) {
433 for (i
= 0; i
< info
->oi_count
; i
++) {
435 status
= ocfs2_get_request_ptr(info
, i
, &req_addr
, compat_flag
);
439 reqp
= (struct ocfs2_info_request
*)(unsigned long)req_addr
;
445 status
= ocfs2_info_handle_request(inode
, reqp
);
454 long ocfs2_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
456 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
460 struct ocfs2_space_resv sr
;
461 struct ocfs2_new_group_input input
;
462 struct reflink_arguments args
;
463 const char *old_path
, *new_path
;
465 struct ocfs2_info info
;
468 case OCFS2_IOC_GETFLAGS
:
469 status
= ocfs2_get_inode_attr(inode
, &flags
);
473 flags
&= OCFS2_FL_VISIBLE
;
474 return put_user(flags
, (int __user
*) arg
);
475 case OCFS2_IOC_SETFLAGS
:
476 if (get_user(flags
, (int __user
*) arg
))
479 status
= mnt_want_write(filp
->f_path
.mnt
);
482 status
= ocfs2_set_inode_attr(inode
, flags
,
483 OCFS2_FL_MODIFIABLE
);
484 mnt_drop_write(filp
->f_path
.mnt
);
486 case OCFS2_IOC_RESVSP
:
487 case OCFS2_IOC_RESVSP64
:
488 case OCFS2_IOC_UNRESVSP
:
489 case OCFS2_IOC_UNRESVSP64
:
490 if (copy_from_user(&sr
, (int __user
*) arg
, sizeof(sr
)))
493 return ocfs2_change_file_space(filp
, cmd
, &sr
);
494 case OCFS2_IOC_GROUP_EXTEND
:
495 if (!capable(CAP_SYS_RESOURCE
))
498 if (get_user(new_clusters
, (int __user
*)arg
))
501 return ocfs2_group_extend(inode
, new_clusters
);
502 case OCFS2_IOC_GROUP_ADD
:
503 case OCFS2_IOC_GROUP_ADD64
:
504 if (!capable(CAP_SYS_RESOURCE
))
507 if (copy_from_user(&input
, (int __user
*) arg
, sizeof(input
)))
510 return ocfs2_group_add(inode
, &input
);
511 case OCFS2_IOC_REFLINK
:
512 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
515 old_path
= (const char *)(unsigned long)args
.old_path
;
516 new_path
= (const char *)(unsigned long)args
.new_path
;
517 preserve
= (args
.preserve
!= 0);
519 return ocfs2_reflink_ioctl(inode
, old_path
, new_path
, preserve
);
521 if (copy_from_user(&info
, (struct ocfs2_info __user
*)arg
,
522 sizeof(struct ocfs2_info
)))
525 return ocfs2_info_handle(inode
, &info
, 0);
532 long ocfs2_compat_ioctl(struct file
*file
, unsigned cmd
, unsigned long arg
)
535 struct reflink_arguments args
;
536 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
537 struct ocfs2_info info
;
540 case OCFS2_IOC32_GETFLAGS
:
541 cmd
= OCFS2_IOC_GETFLAGS
;
543 case OCFS2_IOC32_SETFLAGS
:
544 cmd
= OCFS2_IOC_SETFLAGS
;
546 case OCFS2_IOC_RESVSP
:
547 case OCFS2_IOC_RESVSP64
:
548 case OCFS2_IOC_UNRESVSP
:
549 case OCFS2_IOC_UNRESVSP64
:
550 case OCFS2_IOC_GROUP_EXTEND
:
551 case OCFS2_IOC_GROUP_ADD
:
552 case OCFS2_IOC_GROUP_ADD64
:
554 case OCFS2_IOC_REFLINK
:
555 if (copy_from_user(&args
, (struct reflink_arguments
*)arg
,
558 preserve
= (args
.preserve
!= 0);
560 return ocfs2_reflink_ioctl(inode
, compat_ptr(args
.old_path
),
561 compat_ptr(args
.new_path
), preserve
);
563 if (copy_from_user(&info
, (struct ocfs2_info __user
*)arg
,
564 sizeof(struct ocfs2_info
)))
567 return ocfs2_info_handle(inode
, &info
, 1);
572 return ocfs2_ioctl(file
, cmd
, arg
);