]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/ocfs2/ioctl.c
Ocfs2: Using macro to set/clear *FILLED* flags in info handler.
[karo-tx-linux.git] / fs / ocfs2 / ioctl.c
1 /*
2  * linux/fs/ocfs2/ioctl.c
3  *
4  * Copyright (C) 2006 Herbert Poetzl
5  * adapted from Remy Card's ext2/ioctl.c
6  */
7
8 #include <linux/fs.h>
9 #include <linux/mount.h>
10 #include <linux/compat.h>
11
12 #define MLOG_MASK_PREFIX ML_INODE
13 #include <cluster/masklog.h>
14
15 #include "ocfs2.h"
16 #include "alloc.h"
17 #include "dlmglue.h"
18 #include "file.h"
19 #include "inode.h"
20 #include "journal.h"
21
22 #include "ocfs2_fs.h"
23 #include "ioctl.h"
24 #include "resize.h"
25 #include "refcounttree.h"
26
27 #include <linux/ext2_fs.h>
28
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))
33
34 /*
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.
38  */
39 static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq,
40                                         struct ocfs2_info_request __user *req)
41 {
42         kreq->ir_flags |= OCFS2_INFO_FL_ERROR;
43         (void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags));
44 }
45
46 #define o2info_set_request_error(a, b) \
47                 __o2info_set_request_error((struct ocfs2_info_request *)&(a), b)
48
49 static inline void __o2info_set_request_filled(struct ocfs2_info_request *req)
50 {
51         req->ir_flags |= OCFS2_INFO_FL_FILLED;
52 }
53
54 #define o2info_set_request_filled(a) \
55                 __o2info_set_request_filled((struct ocfs2_info_request *)&(a))
56
57 static inline void __o2info_clear_request_filled(struct ocfs2_info_request *req)
58 {
59         req->ir_flags &= ~OCFS2_INFO_FL_FILLED;
60 }
61
62 #define o2info_clear_request_filled(a) \
63                 __o2info_clear_request_filled((struct ocfs2_info_request *)&(a))
64
65 static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
66 {
67         int status;
68
69         status = ocfs2_inode_lock(inode, NULL, 0);
70         if (status < 0) {
71                 mlog_errno(status);
72                 return status;
73         }
74         ocfs2_get_inode_flags(OCFS2_I(inode));
75         *flags = OCFS2_I(inode)->ip_attr;
76         ocfs2_inode_unlock(inode, 0);
77
78         mlog_exit(status);
79         return status;
80 }
81
82 static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
83                                 unsigned mask)
84 {
85         struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
86         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
87         handle_t *handle = NULL;
88         struct buffer_head *bh = NULL;
89         unsigned oldflags;
90         int status;
91
92         mutex_lock(&inode->i_mutex);
93
94         status = ocfs2_inode_lock(inode, &bh, 1);
95         if (status < 0) {
96                 mlog_errno(status);
97                 goto bail;
98         }
99
100         status = -EACCES;
101         if (!is_owner_or_cap(inode))
102                 goto bail_unlock;
103
104         if (!S_ISDIR(inode->i_mode))
105                 flags &= ~OCFS2_DIRSYNC_FL;
106
107         handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
108         if (IS_ERR(handle)) {
109                 status = PTR_ERR(handle);
110                 mlog_errno(status);
111                 goto bail_unlock;
112         }
113
114         oldflags = ocfs2_inode->ip_attr;
115         flags = flags & mask;
116         flags |= oldflags & ~mask;
117
118         /*
119          * The IMMUTABLE and APPEND_ONLY flags can only be changed by
120          * the relevant capability.
121          */
122         status = -EPERM;
123         if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
124                 (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
125                 if (!capable(CAP_LINUX_IMMUTABLE))
126                         goto bail_unlock;
127         }
128
129         ocfs2_inode->ip_attr = flags;
130         ocfs2_set_inode_flags(inode);
131
132         status = ocfs2_mark_inode_dirty(handle, inode, bh);
133         if (status < 0)
134                 mlog_errno(status);
135
136         ocfs2_commit_trans(osb, handle);
137 bail_unlock:
138         ocfs2_inode_unlock(inode, 1);
139 bail:
140         mutex_unlock(&inode->i_mutex);
141
142         brelse(bh);
143
144         mlog_exit(status);
145         return status;
146 }
147
148 int ocfs2_info_handle_blocksize(struct inode *inode,
149                                 struct ocfs2_info_request __user *req)
150 {
151         int status = -EFAULT;
152         struct ocfs2_info_blocksize oib;
153
154         if (o2info_from_user(oib, req))
155                 goto bail;
156
157         oib.ib_blocksize = inode->i_sb->s_blocksize;
158
159         o2info_set_request_filled(oib);
160
161         if (o2info_to_user(oib, req))
162                 goto bail;
163
164         status = 0;
165 bail:
166         if (status)
167                 o2info_set_request_error(oib, req);
168
169         return status;
170 }
171
172 int ocfs2_info_handle_clustersize(struct inode *inode,
173                                   struct ocfs2_info_request __user *req)
174 {
175         int status = -EFAULT;
176         struct ocfs2_info_clustersize oic;
177         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
178
179         if (o2info_from_user(oic, req))
180                 goto bail;
181
182         oic.ic_clustersize = osb->s_clustersize;
183
184         o2info_set_request_filled(oic);
185
186         if (o2info_to_user(oic, req))
187                 goto bail;
188
189         status = 0;
190 bail:
191         if (status)
192                 o2info_set_request_error(oic, req);
193
194         return status;
195 }
196
197 int ocfs2_info_handle_maxslots(struct inode *inode,
198                                struct ocfs2_info_request __user *req)
199 {
200         int status = -EFAULT;
201         struct ocfs2_info_maxslots oim;
202         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
203
204         if (o2info_from_user(oim, req))
205                 goto bail;
206
207         oim.im_max_slots = osb->max_slots;
208
209         o2info_set_request_filled(oim);
210
211         if (o2info_to_user(oim, req))
212                 goto bail;
213
214         status = 0;
215 bail:
216         if (status)
217                 o2info_set_request_error(oim, req);
218
219         return status;
220 }
221
222 int ocfs2_info_handle_label(struct inode *inode,
223                             struct ocfs2_info_request __user *req)
224 {
225         int status = -EFAULT;
226         struct ocfs2_info_label oil;
227         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
228
229         if (o2info_from_user(oil, req))
230                 goto bail;
231
232         memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
233
234         o2info_set_request_filled(oil);
235
236         if (o2info_to_user(oil, req))
237                 goto bail;
238
239         status = 0;
240 bail:
241         if (status)
242                 o2info_set_request_error(oil, req);
243
244         return status;
245 }
246
247 int ocfs2_info_handle_uuid(struct inode *inode,
248                            struct ocfs2_info_request __user *req)
249 {
250         int status = -EFAULT;
251         struct ocfs2_info_uuid oiu;
252         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
253
254         if (o2info_from_user(oiu, req))
255                 goto bail;
256
257         memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
258
259         o2info_set_request_filled(oiu);
260
261         if (o2info_to_user(oiu, req))
262                 goto bail;
263
264         status = 0;
265 bail:
266         if (status)
267                 o2info_set_request_error(oiu, req);
268
269         return status;
270 }
271
272 int ocfs2_info_handle_fs_features(struct inode *inode,
273                                   struct ocfs2_info_request __user *req)
274 {
275         int status = -EFAULT;
276         struct ocfs2_info_fs_features oif;
277         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
278
279         if (o2info_from_user(oif, req))
280                 goto bail;
281
282         oif.if_compat_features = osb->s_feature_compat;
283         oif.if_incompat_features = osb->s_feature_incompat;
284         oif.if_ro_compat_features = osb->s_feature_ro_compat;
285
286         o2info_set_request_filled(oif);
287
288         if (o2info_to_user(oif, req))
289                 goto bail;
290
291         status = 0;
292 bail:
293         if (status)
294                 o2info_set_request_error(oif, req);
295
296         return status;
297 }
298
299 int ocfs2_info_handle_journal_size(struct inode *inode,
300                                    struct ocfs2_info_request __user *req)
301 {
302         int status = -EFAULT;
303         struct ocfs2_info_journal_size oij;
304         struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
305
306         if (o2info_from_user(oij, req))
307                 goto bail;
308
309         oij.ij_journal_size = osb->journal->j_inode->i_size;
310
311         o2info_set_request_filled(oij);
312
313         if (o2info_to_user(oij, req))
314                 goto bail;
315
316         status = 0;
317 bail:
318         if (status)
319                 o2info_set_request_error(oij, req);
320
321         return status;
322 }
323
324 int ocfs2_info_handle_unknown(struct inode *inode,
325                               struct ocfs2_info_request __user *req)
326 {
327         int status = -EFAULT;
328         struct ocfs2_info_request oir;
329
330         if (o2info_from_user(oir, req))
331                 goto bail;
332
333         o2info_clear_request_filled(oir);
334
335         if (o2info_to_user(oir, req))
336                 goto bail;
337
338         status = 0;
339 bail:
340         if (status)
341                 o2info_set_request_error(oir, req);
342
343         return status;
344 }
345
346 /*
347  * Validate and distinguish OCFS2_IOC_INFO requests.
348  *
349  * - validate the magic number.
350  * - distinguish different requests.
351  * - validate size of different requests.
352  */
353 int ocfs2_info_handle_request(struct inode *inode,
354                               struct ocfs2_info_request __user *req)
355 {
356         int status = -EFAULT;
357         struct ocfs2_info_request oir;
358
359         if (o2info_from_user(oir, req))
360                 goto bail;
361
362         status = -EINVAL;
363         if (oir.ir_magic != OCFS2_INFO_MAGIC)
364                 goto bail;
365
366         switch (oir.ir_code) {
367         case OCFS2_INFO_BLOCKSIZE:
368                 if (oir.ir_size == sizeof(struct ocfs2_info_blocksize))
369                         status = ocfs2_info_handle_blocksize(inode, req);
370                 break;
371         case OCFS2_INFO_CLUSTERSIZE:
372                 if (oir.ir_size == sizeof(struct ocfs2_info_clustersize))
373                         status = ocfs2_info_handle_clustersize(inode, req);
374                 break;
375         case OCFS2_INFO_MAXSLOTS:
376                 if (oir.ir_size == sizeof(struct ocfs2_info_maxslots))
377                         status = ocfs2_info_handle_maxslots(inode, req);
378                 break;
379         case OCFS2_INFO_LABEL:
380                 if (oir.ir_size == sizeof(struct ocfs2_info_label))
381                         status = ocfs2_info_handle_label(inode, req);
382                 break;
383         case OCFS2_INFO_UUID:
384                 if (oir.ir_size == sizeof(struct ocfs2_info_uuid))
385                         status = ocfs2_info_handle_uuid(inode, req);
386                 break;
387         case OCFS2_INFO_FS_FEATURES:
388                 if (oir.ir_size == sizeof(struct ocfs2_info_fs_features))
389                         status = ocfs2_info_handle_fs_features(inode, req);
390                 break;
391         case OCFS2_INFO_JOURNAL_SIZE:
392                 if (oir.ir_size == sizeof(struct ocfs2_info_journal_size))
393                         status = ocfs2_info_handle_journal_size(inode, req);
394                 break;
395         default:
396                 status = ocfs2_info_handle_unknown(inode, req);
397                 break;
398         }
399
400 bail:
401         return status;
402 }
403
404 int ocfs2_get_request_ptr(struct ocfs2_info *info, int idx,
405                           u64 *req_addr, int compat_flag)
406 {
407         int status = -EFAULT;
408         u64 __user *bp = NULL;
409
410         if (compat_flag) {
411 #ifdef CONFIG_COMPAT
412                 /*
413                  * pointer bp stores the base address of a pointers array,
414                  * which collects all addresses of separate request.
415                  */
416                 bp = (u64 __user *)(unsigned long)compat_ptr(info->oi_requests);
417 #else
418                 BUG();
419 #endif
420         } else
421                 bp = (u64 __user *)(unsigned long)(info->oi_requests);
422
423         if (o2info_from_user(*req_addr, bp + idx))
424                 goto bail;
425
426         status = 0;
427 bail:
428         return status;
429 }
430
431 /*
432  * OCFS2_IOC_INFO handles an array of requests passed from userspace.
433  *
434  * ocfs2_info_handle() recevies a large info aggregation, grab and
435  * validate the request count from header, then break it into small
436  * pieces, later specific handlers can handle them one by one.
437  *
438  * Idea here is to make each separate request small enough to ensure
439  * a better backward&forward compatibility, since a small piece of
440  * request will be less likely to be broken if disk layout get changed.
441  */
442 int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
443                       int compat_flag)
444 {
445         int i, status = 0;
446         u64 req_addr;
447         struct ocfs2_info_request __user *reqp;
448
449         if ((info->oi_count > OCFS2_INFO_MAX_REQUEST) ||
450             (!info->oi_requests)) {
451                 status = -EINVAL;
452                 goto bail;
453         }
454
455         for (i = 0; i < info->oi_count; i++) {
456
457                 status = ocfs2_get_request_ptr(info, i, &req_addr, compat_flag);
458                 if (status)
459                         break;
460
461                 reqp = (struct ocfs2_info_request *)(unsigned long)req_addr;
462                 if (!reqp) {
463                         status = -EINVAL;
464                         goto bail;
465                 }
466
467                 status = ocfs2_info_handle_request(inode, reqp);
468                 if (status)
469                         break;
470         }
471
472 bail:
473         return status;
474 }
475
476 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
477 {
478         struct inode *inode = filp->f_path.dentry->d_inode;
479         unsigned int flags;
480         int new_clusters;
481         int status;
482         struct ocfs2_space_resv sr;
483         struct ocfs2_new_group_input input;
484         struct reflink_arguments args;
485         const char *old_path, *new_path;
486         bool preserve;
487         struct ocfs2_info info;
488
489         switch (cmd) {
490         case OCFS2_IOC_GETFLAGS:
491                 status = ocfs2_get_inode_attr(inode, &flags);
492                 if (status < 0)
493                         return status;
494
495                 flags &= OCFS2_FL_VISIBLE;
496                 return put_user(flags, (int __user *) arg);
497         case OCFS2_IOC_SETFLAGS:
498                 if (get_user(flags, (int __user *) arg))
499                         return -EFAULT;
500
501                 status = mnt_want_write(filp->f_path.mnt);
502                 if (status)
503                         return status;
504                 status = ocfs2_set_inode_attr(inode, flags,
505                         OCFS2_FL_MODIFIABLE);
506                 mnt_drop_write(filp->f_path.mnt);
507                 return status;
508         case OCFS2_IOC_RESVSP:
509         case OCFS2_IOC_RESVSP64:
510         case OCFS2_IOC_UNRESVSP:
511         case OCFS2_IOC_UNRESVSP64:
512                 if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
513                         return -EFAULT;
514
515                 return ocfs2_change_file_space(filp, cmd, &sr);
516         case OCFS2_IOC_GROUP_EXTEND:
517                 if (!capable(CAP_SYS_RESOURCE))
518                         return -EPERM;
519
520                 if (get_user(new_clusters, (int __user *)arg))
521                         return -EFAULT;
522
523                 return ocfs2_group_extend(inode, new_clusters);
524         case OCFS2_IOC_GROUP_ADD:
525         case OCFS2_IOC_GROUP_ADD64:
526                 if (!capable(CAP_SYS_RESOURCE))
527                         return -EPERM;
528
529                 if (copy_from_user(&input, (int __user *) arg, sizeof(input)))
530                         return -EFAULT;
531
532                 return ocfs2_group_add(inode, &input);
533         case OCFS2_IOC_REFLINK:
534                 if (copy_from_user(&args, (struct reflink_arguments *)arg,
535                                    sizeof(args)))
536                         return -EFAULT;
537                 old_path = (const char *)(unsigned long)args.old_path;
538                 new_path = (const char *)(unsigned long)args.new_path;
539                 preserve = (args.preserve != 0);
540
541                 return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
542         case OCFS2_IOC_INFO:
543                 if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
544                                    sizeof(struct ocfs2_info)))
545                         return -EFAULT;
546
547                 return ocfs2_info_handle(inode, &info, 0);
548         default:
549                 return -ENOTTY;
550         }
551 }
552
553 #ifdef CONFIG_COMPAT
554 long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
555 {
556         bool preserve;
557         struct reflink_arguments args;
558         struct inode *inode = file->f_path.dentry->d_inode;
559         struct ocfs2_info info;
560
561         switch (cmd) {
562         case OCFS2_IOC32_GETFLAGS:
563                 cmd = OCFS2_IOC_GETFLAGS;
564                 break;
565         case OCFS2_IOC32_SETFLAGS:
566                 cmd = OCFS2_IOC_SETFLAGS;
567                 break;
568         case OCFS2_IOC_RESVSP:
569         case OCFS2_IOC_RESVSP64:
570         case OCFS2_IOC_UNRESVSP:
571         case OCFS2_IOC_UNRESVSP64:
572         case OCFS2_IOC_GROUP_EXTEND:
573         case OCFS2_IOC_GROUP_ADD:
574         case OCFS2_IOC_GROUP_ADD64:
575                 break;
576         case OCFS2_IOC_REFLINK:
577                 if (copy_from_user(&args, (struct reflink_arguments *)arg,
578                                    sizeof(args)))
579                         return -EFAULT;
580                 preserve = (args.preserve != 0);
581
582                 return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
583                                            compat_ptr(args.new_path), preserve);
584         case OCFS2_IOC_INFO:
585                 if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
586                                    sizeof(struct ocfs2_info)))
587                         return -EFAULT;
588
589                 return ocfs2_info_handle(inode, &info, 1);
590         default:
591                 return -ENOIOCTLCMD;
592         }
593
594         return ocfs2_ioctl(file, cmd, arg);
595 }
596 #endif