~ubuntu-branches/ubuntu/lucid/linux-rt/lucid

« back to all changes in this revision

Viewing changes to fs/btrfs/ioctl.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-08-05 23:00:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090805230052-7xedvqcyk9dnnxb2
Tags: 2.6.31-1.1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include <linux/time.h>
28
28
#include <linux/init.h>
29
29
#include <linux/string.h>
30
 
#include <linux/smp_lock.h>
31
30
#include <linux/backing-dev.h>
32
31
#include <linux/mount.h>
33
32
#include <linux/mpage.h>
50
49
#include "volumes.h"
51
50
#include "locking.h"
52
51
 
53
 
 
 
52
/* Mask out flags that are inappropriate for the given type of inode. */
 
53
static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
 
54
{
 
55
        if (S_ISDIR(mode))
 
56
                return flags;
 
57
        else if (S_ISREG(mode))
 
58
                return flags & ~FS_DIRSYNC_FL;
 
59
        else
 
60
                return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
 
61
}
 
62
 
 
63
/*
 
64
 * Export inode flags to the format expected by the FS_IOC_GETFLAGS ioctl.
 
65
 */
 
66
static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
 
67
{
 
68
        unsigned int iflags = 0;
 
69
 
 
70
        if (flags & BTRFS_INODE_SYNC)
 
71
                iflags |= FS_SYNC_FL;
 
72
        if (flags & BTRFS_INODE_IMMUTABLE)
 
73
                iflags |= FS_IMMUTABLE_FL;
 
74
        if (flags & BTRFS_INODE_APPEND)
 
75
                iflags |= FS_APPEND_FL;
 
76
        if (flags & BTRFS_INODE_NODUMP)
 
77
                iflags |= FS_NODUMP_FL;
 
78
        if (flags & BTRFS_INODE_NOATIME)
 
79
                iflags |= FS_NOATIME_FL;
 
80
        if (flags & BTRFS_INODE_DIRSYNC)
 
81
                iflags |= FS_DIRSYNC_FL;
 
82
 
 
83
        return iflags;
 
84
}
 
85
 
 
86
/*
 
87
 * Update inode->i_flags based on the btrfs internal flags.
 
88
 */
 
89
void btrfs_update_iflags(struct inode *inode)
 
90
{
 
91
        struct btrfs_inode *ip = BTRFS_I(inode);
 
92
 
 
93
        inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
 
94
 
 
95
        if (ip->flags & BTRFS_INODE_SYNC)
 
96
                inode->i_flags |= S_SYNC;
 
97
        if (ip->flags & BTRFS_INODE_IMMUTABLE)
 
98
                inode->i_flags |= S_IMMUTABLE;
 
99
        if (ip->flags & BTRFS_INODE_APPEND)
 
100
                inode->i_flags |= S_APPEND;
 
101
        if (ip->flags & BTRFS_INODE_NOATIME)
 
102
                inode->i_flags |= S_NOATIME;
 
103
        if (ip->flags & BTRFS_INODE_DIRSYNC)
 
104
                inode->i_flags |= S_DIRSYNC;
 
105
}
 
106
 
 
107
/*
 
108
 * Inherit flags from the parent inode.
 
109
 *
 
110
 * Unlike extN we don't have any flags we don't want to inherit currently.
 
111
 */
 
112
void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
 
113
{
 
114
        unsigned int flags;
 
115
 
 
116
        if (!dir)
 
117
                return;
 
118
 
 
119
        flags = BTRFS_I(dir)->flags;
 
120
 
 
121
        if (S_ISREG(inode->i_mode))
 
122
                flags &= ~BTRFS_INODE_DIRSYNC;
 
123
        else if (!S_ISDIR(inode->i_mode))
 
124
                flags &= (BTRFS_INODE_NODUMP | BTRFS_INODE_NOATIME);
 
125
 
 
126
        BTRFS_I(inode)->flags = flags;
 
127
        btrfs_update_iflags(inode);
 
128
}
 
129
 
 
130
static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
 
131
{
 
132
        struct btrfs_inode *ip = BTRFS_I(file->f_path.dentry->d_inode);
 
133
        unsigned int flags = btrfs_flags_to_ioctl(ip->flags);
 
134
 
 
135
        if (copy_to_user(arg, &flags, sizeof(flags)))
 
136
                return -EFAULT;
 
137
        return 0;
 
138
}
 
139
 
 
140
static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 
141
{
 
142
        struct inode *inode = file->f_path.dentry->d_inode;
 
143
        struct btrfs_inode *ip = BTRFS_I(inode);
 
144
        struct btrfs_root *root = ip->root;
 
145
        struct btrfs_trans_handle *trans;
 
146
        unsigned int flags, oldflags;
 
147
        int ret;
 
148
 
 
149
        if (copy_from_user(&flags, arg, sizeof(flags)))
 
150
                return -EFAULT;
 
151
 
 
152
        if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
 
153
                      FS_NOATIME_FL | FS_NODUMP_FL | \
 
154
                      FS_SYNC_FL | FS_DIRSYNC_FL))
 
155
                return -EOPNOTSUPP;
 
156
 
 
157
        if (!is_owner_or_cap(inode))
 
158
                return -EACCES;
 
159
 
 
160
        mutex_lock(&inode->i_mutex);
 
161
 
 
162
        flags = btrfs_mask_flags(inode->i_mode, flags);
 
163
        oldflags = btrfs_flags_to_ioctl(ip->flags);
 
164
        if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
 
165
                if (!capable(CAP_LINUX_IMMUTABLE)) {
 
166
                        ret = -EPERM;
 
167
                        goto out_unlock;
 
168
                }
 
169
        }
 
170
 
 
171
        ret = mnt_want_write(file->f_path.mnt);
 
172
        if (ret)
 
173
                goto out_unlock;
 
174
 
 
175
        if (flags & FS_SYNC_FL)
 
176
                ip->flags |= BTRFS_INODE_SYNC;
 
177
        else
 
178
                ip->flags &= ~BTRFS_INODE_SYNC;
 
179
        if (flags & FS_IMMUTABLE_FL)
 
180
                ip->flags |= BTRFS_INODE_IMMUTABLE;
 
181
        else
 
182
                ip->flags &= ~BTRFS_INODE_IMMUTABLE;
 
183
        if (flags & FS_APPEND_FL)
 
184
                ip->flags |= BTRFS_INODE_APPEND;
 
185
        else
 
186
                ip->flags &= ~BTRFS_INODE_APPEND;
 
187
        if (flags & FS_NODUMP_FL)
 
188
                ip->flags |= BTRFS_INODE_NODUMP;
 
189
        else
 
190
                ip->flags &= ~BTRFS_INODE_NODUMP;
 
191
        if (flags & FS_NOATIME_FL)
 
192
                ip->flags |= BTRFS_INODE_NOATIME;
 
193
        else
 
194
                ip->flags &= ~BTRFS_INODE_NOATIME;
 
195
        if (flags & FS_DIRSYNC_FL)
 
196
                ip->flags |= BTRFS_INODE_DIRSYNC;
 
197
        else
 
198
                ip->flags &= ~BTRFS_INODE_DIRSYNC;
 
199
 
 
200
 
 
201
        trans = btrfs_join_transaction(root, 1);
 
202
        BUG_ON(!trans);
 
203
 
 
204
        ret = btrfs_update_inode(trans, root, inode);
 
205
        BUG_ON(ret);
 
206
 
 
207
        btrfs_update_iflags(inode);
 
208
        inode->i_ctime = CURRENT_TIME;
 
209
        btrfs_end_transaction(trans, root);
 
210
 
 
211
        mnt_drop_write(file->f_path.mnt);
 
212
 out_unlock:
 
213
        mutex_unlock(&inode->i_mutex);
 
214
        return 0;
 
215
}
 
216
 
 
217
static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
 
218
{
 
219
        struct inode *inode = file->f_path.dentry->d_inode;
 
220
 
 
221
        return put_user(inode->i_generation, arg);
 
222
}
54
223
 
55
224
static noinline int create_subvol(struct btrfs_root *root,
56
225
                                  struct dentry *dentry,
82
251
        if (ret)
83
252
                goto fail;
84
253
 
85
 
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
86
 
                                      objectid, trans->transid, 0, 0, 0);
 
254
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
 
255
                                      0, objectid, NULL, 0, 0, 0);
87
256
        if (IS_ERR(leaf)) {
88
257
                ret = PTR_ERR(leaf);
89
258
                goto fail;
90
259
        }
91
260
 
92
 
        btrfs_set_header_nritems(leaf, 0);
93
 
        btrfs_set_header_level(leaf, 0);
 
261
        memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header));
94
262
        btrfs_set_header_bytenr(leaf, leaf->start);
95
263
        btrfs_set_header_generation(leaf, trans->transid);
 
264
        btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
96
265
        btrfs_set_header_owner(leaf, objectid);
97
266
 
98
267
        write_extent_buffer(leaf, root->fs_info->fsid,
99
268
                            (unsigned long)btrfs_header_fsid(leaf),
100
269
                            BTRFS_FSID_SIZE);
 
270
        write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid,
 
271
                            (unsigned long)btrfs_header_chunk_tree_uuid(leaf),
 
272
                            BTRFS_UUID_SIZE);
101
273
        btrfs_mark_buffer_dirty(leaf);
102
274
 
103
275
        inode_item = &root_item.inode;
125
297
        btrfs_set_root_dirid(&root_item, new_dirid);
126
298
 
127
299
        key.objectid = objectid;
128
 
        key.offset = 1;
 
300
        key.offset = 0;
129
301
        btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
130
302
        ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
131
303
                                &root_item);
267
439
                goto out_dput;
268
440
 
269
441
        if (!IS_POSIXACL(parent->dentry->d_inode))
270
 
                mode &= ~current->fs->umask;
 
442
                mode &= ~current_umask();
271
443
 
272
444
        error = mnt_want_write(parent->mnt);
273
445
        if (error)
437
609
        return 0;
438
610
}
439
611
 
440
 
/*
441
 
 * Called inside transaction, so use GFP_NOFS
442
 
 */
443
 
 
444
612
static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
445
613
{
446
614
        u64 new_size;
461
629
        if (!capable(CAP_SYS_ADMIN))
462
630
                return -EPERM;
463
631
 
464
 
        vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
465
 
 
466
 
        if (!vol_args)
467
 
                return -ENOMEM;
468
 
 
469
 
        if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
470
 
                ret = -EFAULT;
471
 
                goto out;
472
 
        }
 
632
        vol_args = memdup_user(arg, sizeof(*vol_args));
 
633
        if (IS_ERR(vol_args))
 
634
                return PTR_ERR(vol_args);
473
635
 
474
636
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
475
637
        namelen = strlen(vol_args->name);
483
645
                *devstr = '\0';
484
646
                devstr = vol_args->name;
485
647
                devid = simple_strtoull(devstr, &end, 10);
486
 
                printk(KERN_INFO "resizing devid %llu\n", devid);
 
648
                printk(KERN_INFO "resizing devid %llu\n",
 
649
                       (unsigned long long)devid);
487
650
        }
488
651
        device = btrfs_find_device(root, devid, NULL, NULL);
489
652
        if (!device) {
490
 
                printk(KERN_INFO "resizer unable to find device %llu\n", devid);
 
653
                printk(KERN_INFO "resizer unable to find device %llu\n",
 
654
                       (unsigned long long)devid);
491
655
                ret = -EINVAL;
492
656
                goto out_unlock;
493
657
        }
545
709
 
546
710
out_unlock:
547
711
        mutex_unlock(&root->fs_info->volume_mutex);
548
 
out:
549
712
        kfree(vol_args);
550
713
        return ret;
551
714
}
565
728
        if (root->fs_info->sb->s_flags & MS_RDONLY)
566
729
                return -EROFS;
567
730
 
568
 
        vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
569
 
 
570
 
        if (!vol_args)
571
 
                return -ENOMEM;
572
 
 
573
 
        if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
574
 
                ret = -EFAULT;
575
 
                goto out;
576
 
        }
 
731
        vol_args = memdup_user(arg, sizeof(*vol_args));
 
732
        if (IS_ERR(vol_args))
 
733
                return PTR_ERR(vol_args);
577
734
 
578
735
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
579
736
        namelen = strlen(vol_args->name);
675
832
        if (!capable(CAP_SYS_ADMIN))
676
833
                return -EPERM;
677
834
 
678
 
        vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
679
 
 
680
 
        if (!vol_args)
681
 
                return -ENOMEM;
682
 
 
683
 
        if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
684
 
                ret = -EFAULT;
685
 
                goto out;
686
 
        }
 
835
        vol_args = memdup_user(arg, sizeof(*vol_args));
 
836
        if (IS_ERR(vol_args))
 
837
                return PTR_ERR(vol_args);
 
838
 
687
839
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
688
840
        ret = btrfs_init_new_device(root, vol_args->name);
689
841
 
690
 
out:
691
842
        kfree(vol_args);
692
843
        return ret;
693
844
}
703
854
        if (root->fs_info->sb->s_flags & MS_RDONLY)
704
855
                return -EROFS;
705
856
 
706
 
        vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
707
 
 
708
 
        if (!vol_args)
709
 
                return -ENOMEM;
710
 
 
711
 
        if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
712
 
                ret = -EFAULT;
713
 
                goto out;
714
 
        }
 
857
        vol_args = memdup_user(arg, sizeof(*vol_args));
 
858
        if (IS_ERR(vol_args))
 
859
                return PTR_ERR(vol_args);
 
860
 
715
861
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
716
862
        ret = btrfs_rm_device(root, vol_args->name);
717
863
 
718
 
out:
719
864
        kfree(vol_args);
720
865
        return ret;
721
866
}
830
975
        BUG_ON(!trans);
831
976
 
832
977
        /* punch hole in destination first */
833
 
        btrfs_drop_extents(trans, root, inode, off, off+len, 0, &hint_byte);
 
978
        btrfs_drop_extents(trans, root, inode, off, off + len,
 
979
                           off + len, 0, &hint_byte);
834
980
 
835
981
        /* clone data */
836
982
        key.objectid = src->i_ino;
881
1027
                                                struct btrfs_file_extent_item);
882
1028
                        comp = btrfs_file_extent_compression(leaf, extent);
883
1029
                        type = btrfs_file_extent_type(leaf, extent);
884
 
                        if (type == BTRFS_FILE_EXTENT_REG) {
 
1030
                        if (type == BTRFS_FILE_EXTENT_REG ||
 
1031
                            type == BTRFS_FILE_EXTENT_PREALLOC) {
885
1032
                                disko = btrfs_file_extent_disk_bytenr(leaf,
886
1033
                                                                      extent);
887
1034
                                diskl = btrfs_file_extent_disk_num_bytes(leaf,
904
1051
                        new_key.objectid = inode->i_ino;
905
1052
                        new_key.offset = key.offset + destoff - off;
906
1053
 
907
 
                        if (type == BTRFS_FILE_EXTENT_REG) {
 
1054
                        if (type == BTRFS_FILE_EXTENT_REG ||
 
1055
                            type == BTRFS_FILE_EXTENT_PREALLOC) {
908
1056
                                ret = btrfs_insert_empty_item(trans, root, path,
909
1057
                                                              &new_key, size);
910
1058
                                if (ret)
937
1085
                                if (disko) {
938
1086
                                        inode_add_bytes(inode, datal);
939
1087
                                        ret = btrfs_inc_extent_ref(trans, root,
940
 
                                                   disko, diskl, leaf->start,
941
 
                                                   root->root_key.objectid,
942
 
                                                   trans->transid,
943
 
                                                   inode->i_ino);
 
1088
                                                        disko, diskl, 0,
 
1089
                                                        root->root_key.objectid,
 
1090
                                                        inode->i_ino,
 
1091
                                                        new_key.offset - datao);
944
1092
                                        BUG_ON(ret);
945
1093
                                }
946
1094
                        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
1100
1248
        void __user *argp = (void __user *)arg;
1101
1249
 
1102
1250
        switch (cmd) {
 
1251
        case FS_IOC_GETFLAGS:
 
1252
                return btrfs_ioctl_getflags(file, argp);
 
1253
        case FS_IOC_SETFLAGS:
 
1254
                return btrfs_ioctl_setflags(file, argp);
 
1255
        case FS_IOC_GETVERSION:
 
1256
                return btrfs_ioctl_getversion(file, argp);
1103
1257
        case BTRFS_IOC_SNAP_CREATE:
1104
1258
                return btrfs_ioctl_snap_create(file, argp, 0);
1105
1259
        case BTRFS_IOC_SUBVOL_CREATE: