aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-03-02 19:41:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-03-02 19:41:54 -0500
commitb695188dd39162a1a6bff11fdbcc4c0b65b933ab (patch)
treea3df7c052d38b5bfaf335fbf3130abcc5c6ca577 /fs/btrfs/ioctl.c
parent48476df99894492a0f7239f2f3c9a2dde4ff38e2 (diff)
parent180e001cd5fc2950dc6a7997dde5b65c954d0e79 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs update from Chris Mason: "The biggest feature in the pull is the new (and still experimental) raid56 code that David Woodhouse started long ago. I'm still working on the parity logging setup that will avoid inconsistent parity after a crash, so this is only for testing right now. But, I'd really like to get it out to a broader audience to hammer out any performance issues or other problems. scrub does not yet correct errors on raid5/6 either. Josef has another pass at fsync performance. The big change here is to combine waiting for metadata with waiting for data, which is a big latency win. It is also step one toward using atomics from the hardware during a commit. Mark Fasheh has a new way to use btrfs send/receive to send only the metadata changes. SUSE is using this to make snapper more efficient at finding changes between snapshosts. Snapshot-aware defrag is also included. Otherwise we have a large number of fixes and cleanups. Eric Sandeen wins the award for removing the most lines, and I'm hoping we steal this idea from XFS over and over again." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (118 commits) btrfs: fixup/remove module.h usage as required Btrfs: delete inline extents when we find them during logging btrfs: try harder to allocate raid56 stripe cache Btrfs: cleanup to make the function btrfs_delalloc_reserve_metadata more logic Btrfs: don't call btrfs_qgroup_free if just btrfs_qgroup_reserve fails Btrfs: remove reduplicate check about root in the function btrfs_clean_quota_tree Btrfs: return ENOMEM rather than use BUG_ON when btrfs_alloc_path fails Btrfs: fix missing deleted items in btrfs_clean_quota_tree btrfs: use only inline_pages from extent buffer Btrfs: fix wrong reserved space when deleting a snapshot/subvolume Btrfs: fix wrong reserved space in qgroup during snap/subv creation Btrfs: remove unnecessary dget_parent/dput when creating the pending snapshot btrfs: remove a printk from scan_one_device Btrfs: fix NULL pointer after aborting a transaction Btrfs: fix memory leak of log roots Btrfs: copy everything if we've created an inline extent btrfs: cleanup for open-coded alignment Btrfs: do not change inode flags in rename Btrfs: use reserved space for creating a snapshot clear chunk_alloc flag on retryable failure ...
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c211
1 files changed, 163 insertions, 48 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c3f09f71bedd..c83086fdda05 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -42,12 +42,12 @@
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/blkdev.h> 43#include <linux/blkdev.h>
44#include <linux/uuid.h> 44#include <linux/uuid.h>
45#include <linux/btrfs.h>
45#include "compat.h" 46#include "compat.h"
46#include "ctree.h" 47#include "ctree.h"
47#include "disk-io.h" 48#include "disk-io.h"
48#include "transaction.h" 49#include "transaction.h"
49#include "btrfs_inode.h" 50#include "btrfs_inode.h"
50#include "ioctl.h"
51#include "print-tree.h" 51#include "print-tree.h"
52#include "volumes.h" 52#include "volumes.h"
53#include "locking.h" 53#include "locking.h"
@@ -363,46 +363,52 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
363 return 0; 363 return 0;
364} 364}
365 365
366static noinline int create_subvol(struct btrfs_root *root, 366static noinline int create_subvol(struct inode *dir,
367 struct dentry *dentry, 367 struct dentry *dentry,
368 char *name, int namelen, 368 char *name, int namelen,
369 u64 *async_transid, 369 u64 *async_transid,
370 struct btrfs_qgroup_inherit **inherit) 370 struct btrfs_qgroup_inherit *inherit)
371{ 371{
372 struct btrfs_trans_handle *trans; 372 struct btrfs_trans_handle *trans;
373 struct btrfs_key key; 373 struct btrfs_key key;
374 struct btrfs_root_item root_item; 374 struct btrfs_root_item root_item;
375 struct btrfs_inode_item *inode_item; 375 struct btrfs_inode_item *inode_item;
376 struct extent_buffer *leaf; 376 struct extent_buffer *leaf;
377 struct btrfs_root *root = BTRFS_I(dir)->root;
377 struct btrfs_root *new_root; 378 struct btrfs_root *new_root;
378 struct dentry *parent = dentry->d_parent; 379 struct btrfs_block_rsv block_rsv;
379 struct inode *dir;
380 struct timespec cur_time = CURRENT_TIME; 380 struct timespec cur_time = CURRENT_TIME;
381 int ret; 381 int ret;
382 int err; 382 int err;
383 u64 objectid; 383 u64 objectid;
384 u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; 384 u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
385 u64 index = 0; 385 u64 index = 0;
386 u64 qgroup_reserved;
386 uuid_le new_uuid; 387 uuid_le new_uuid;
387 388
388 ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); 389 ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
389 if (ret) 390 if (ret)
390 return ret; 391 return ret;
391 392
392 dir = parent->d_inode; 393 btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
393
394 /* 394 /*
395 * 1 - inode item 395 * The same as the snapshot creation, please see the comment
396 * 2 - refs 396 * of create_snapshot().
397 * 1 - root item
398 * 2 - dir items
399 */ 397 */
400 trans = btrfs_start_transaction(root, 6); 398 ret = btrfs_subvolume_reserve_metadata(root, &block_rsv,
401 if (IS_ERR(trans)) 399 7, &qgroup_reserved);
402 return PTR_ERR(trans); 400 if (ret)
401 return ret;
402
403 trans = btrfs_start_transaction(root, 0);
404 if (IS_ERR(trans)) {
405 ret = PTR_ERR(trans);
406 goto out;
407 }
408 trans->block_rsv = &block_rsv;
409 trans->bytes_reserved = block_rsv.size;
403 410
404 ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, 411 ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit);
405 inherit ? *inherit : NULL);
406 if (ret) 412 if (ret)
407 goto fail; 413 goto fail;
408 414
@@ -516,6 +522,8 @@ static noinline int create_subvol(struct btrfs_root *root,
516 BUG_ON(ret); 522 BUG_ON(ret);
517 523
518fail: 524fail:
525 trans->block_rsv = NULL;
526 trans->bytes_reserved = 0;
519 if (async_transid) { 527 if (async_transid) {
520 *async_transid = trans->transid; 528 *async_transid = trans->transid;
521 err = btrfs_commit_transaction_async(trans, root, 1); 529 err = btrfs_commit_transaction_async(trans, root, 1);
@@ -527,13 +535,15 @@ fail:
527 535
528 if (!ret) 536 if (!ret)
529 d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); 537 d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
530 538out:
539 btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
531 return ret; 540 return ret;
532} 541}
533 542
534static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, 543static int create_snapshot(struct btrfs_root *root, struct inode *dir,
535 char *name, int namelen, u64 *async_transid, 544 struct dentry *dentry, char *name, int namelen,
536 bool readonly, struct btrfs_qgroup_inherit **inherit) 545 u64 *async_transid, bool readonly,
546 struct btrfs_qgroup_inherit *inherit)
537{ 547{
538 struct inode *inode; 548 struct inode *inode;
539 struct btrfs_pending_snapshot *pending_snapshot; 549 struct btrfs_pending_snapshot *pending_snapshot;
@@ -549,23 +559,31 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
549 559
550 btrfs_init_block_rsv(&pending_snapshot->block_rsv, 560 btrfs_init_block_rsv(&pending_snapshot->block_rsv,
551 BTRFS_BLOCK_RSV_TEMP); 561 BTRFS_BLOCK_RSV_TEMP);
562 /*
563 * 1 - parent dir inode
564 * 2 - dir entries
565 * 1 - root item
566 * 2 - root ref/backref
567 * 1 - root of snapshot
568 */
569 ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
570 &pending_snapshot->block_rsv, 7,
571 &pending_snapshot->qgroup_reserved);
572 if (ret)
573 goto out;
574
552 pending_snapshot->dentry = dentry; 575 pending_snapshot->dentry = dentry;
553 pending_snapshot->root = root; 576 pending_snapshot->root = root;
554 pending_snapshot->readonly = readonly; 577 pending_snapshot->readonly = readonly;
555 if (inherit) { 578 pending_snapshot->dir = dir;
556 pending_snapshot->inherit = *inherit; 579 pending_snapshot->inherit = inherit;
557 *inherit = NULL; /* take responsibility to free it */
558 }
559 580
560 trans = btrfs_start_transaction(root->fs_info->extent_root, 6); 581 trans = btrfs_start_transaction(root, 0);
561 if (IS_ERR(trans)) { 582 if (IS_ERR(trans)) {
562 ret = PTR_ERR(trans); 583 ret = PTR_ERR(trans);
563 goto fail; 584 goto fail;
564 } 585 }
565 586
566 ret = btrfs_snap_reserve_metadata(trans, pending_snapshot);
567 BUG_ON(ret);
568
569 spin_lock(&root->fs_info->trans_lock); 587 spin_lock(&root->fs_info->trans_lock);
570 list_add(&pending_snapshot->list, 588 list_add(&pending_snapshot->list,
571 &trans->transaction->pending_snapshots); 589 &trans->transaction->pending_snapshots);
@@ -602,6 +620,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
602 d_instantiate(dentry, inode); 620 d_instantiate(dentry, inode);
603 ret = 0; 621 ret = 0;
604fail: 622fail:
623 btrfs_subvolume_release_metadata(BTRFS_I(dir)->root,
624 &pending_snapshot->block_rsv,
625 pending_snapshot->qgroup_reserved);
626out:
605 kfree(pending_snapshot); 627 kfree(pending_snapshot);
606 return ret; 628 return ret;
607} 629}
@@ -695,7 +717,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
695 char *name, int namelen, 717 char *name, int namelen,
696 struct btrfs_root *snap_src, 718 struct btrfs_root *snap_src,
697 u64 *async_transid, bool readonly, 719 u64 *async_transid, bool readonly,
698 struct btrfs_qgroup_inherit **inherit) 720 struct btrfs_qgroup_inherit *inherit)
699{ 721{
700 struct inode *dir = parent->dentry->d_inode; 722 struct inode *dir = parent->dentry->d_inode;
701 struct dentry *dentry; 723 struct dentry *dentry;
@@ -732,11 +754,11 @@ static noinline int btrfs_mksubvol(struct path *parent,
732 goto out_up_read; 754 goto out_up_read;
733 755
734 if (snap_src) { 756 if (snap_src) {
735 error = create_snapshot(snap_src, dentry, name, namelen, 757 error = create_snapshot(snap_src, dir, dentry, name, namelen,
736 async_transid, readonly, inherit); 758 async_transid, readonly, inherit);
737 } else { 759 } else {
738 error = create_subvol(BTRFS_I(dir)->root, dentry, 760 error = create_subvol(dir, dentry, name, namelen,
739 name, namelen, async_transid, inherit); 761 async_transid, inherit);
740 } 762 }
741 if (!error) 763 if (!error)
742 fsnotify_mkdir(dir, dentry); 764 fsnotify_mkdir(dir, dentry);
@@ -818,7 +840,7 @@ static int find_new_extents(struct btrfs_root *root,
818 840
819 while(1) { 841 while(1) {
820 ret = btrfs_search_forward(root, &min_key, &max_key, 842 ret = btrfs_search_forward(root, &min_key, &max_key,
821 path, 0, newer_than); 843 path, newer_than);
822 if (ret != 0) 844 if (ret != 0)
823 goto none; 845 goto none;
824 if (min_key.objectid != ino) 846 if (min_key.objectid != ino)
@@ -1206,6 +1228,12 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
1206 if (!(inode->i_sb->s_flags & MS_ACTIVE)) 1228 if (!(inode->i_sb->s_flags & MS_ACTIVE))
1207 break; 1229 break;
1208 1230
1231 if (btrfs_defrag_cancelled(root->fs_info)) {
1232 printk(KERN_DEBUG "btrfs: defrag_file cancelled\n");
1233 ret = -EAGAIN;
1234 break;
1235 }
1236
1209 if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, 1237 if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT,
1210 extent_thresh, &last_len, &skip, 1238 extent_thresh, &last_len, &skip,
1211 &defrag_end, range->flags & 1239 &defrag_end, range->flags &
@@ -1329,9 +1357,6 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1329 int ret = 0; 1357 int ret = 0;
1330 int mod = 0; 1358 int mod = 0;
1331 1359
1332 if (root->fs_info->sb->s_flags & MS_RDONLY)
1333 return -EROFS;
1334
1335 if (!capable(CAP_SYS_ADMIN)) 1360 if (!capable(CAP_SYS_ADMIN))
1336 return -EPERM; 1361 return -EPERM;
1337 1362
@@ -1363,6 +1388,10 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1363 *devstr = '\0'; 1388 *devstr = '\0';
1364 devstr = vol_args->name; 1389 devstr = vol_args->name;
1365 devid = simple_strtoull(devstr, &end, 10); 1390 devid = simple_strtoull(devstr, &end, 10);
1391 if (!devid) {
1392 ret = -EINVAL;
1393 goto out_free;
1394 }
1366 printk(KERN_INFO "btrfs: resizing devid %llu\n", 1395 printk(KERN_INFO "btrfs: resizing devid %llu\n",
1367 (unsigned long long)devid); 1396 (unsigned long long)devid);
1368 } 1397 }
@@ -1371,7 +1400,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1371 if (!device) { 1400 if (!device) {
1372 printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", 1401 printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
1373 (unsigned long long)devid); 1402 (unsigned long long)devid);
1374 ret = -EINVAL; 1403 ret = -ENODEV;
1375 goto out_free; 1404 goto out_free;
1376 } 1405 }
1377 1406
@@ -1379,7 +1408,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1379 printk(KERN_INFO "btrfs: resizer unable to apply on " 1408 printk(KERN_INFO "btrfs: resizer unable to apply on "
1380 "readonly device %llu\n", 1409 "readonly device %llu\n",
1381 (unsigned long long)devid); 1410 (unsigned long long)devid);
1382 ret = -EINVAL; 1411 ret = -EPERM;
1383 goto out_free; 1412 goto out_free;
1384 } 1413 }
1385 1414
@@ -1401,7 +1430,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1401 } 1430 }
1402 1431
1403 if (device->is_tgtdev_for_dev_replace) { 1432 if (device->is_tgtdev_for_dev_replace) {
1404 ret = -EINVAL; 1433 ret = -EPERM;
1405 goto out_free; 1434 goto out_free;
1406 } 1435 }
1407 1436
@@ -1457,7 +1486,7 @@ out:
1457static noinline int btrfs_ioctl_snap_create_transid(struct file *file, 1486static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
1458 char *name, unsigned long fd, int subvol, 1487 char *name, unsigned long fd, int subvol,
1459 u64 *transid, bool readonly, 1488 u64 *transid, bool readonly,
1460 struct btrfs_qgroup_inherit **inherit) 1489 struct btrfs_qgroup_inherit *inherit)
1461{ 1490{
1462 int namelen; 1491 int namelen;
1463 int ret = 0; 1492 int ret = 0;
@@ -1566,7 +1595,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
1566 1595
1567 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, 1596 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
1568 vol_args->fd, subvol, ptr, 1597 vol_args->fd, subvol, ptr,
1569 readonly, &inherit); 1598 readonly, inherit);
1570 1599
1571 if (ret == 0 && ptr && 1600 if (ret == 0 && ptr &&
1572 copy_to_user(arg + 1601 copy_to_user(arg +
@@ -1863,7 +1892,7 @@ static noinline int search_ioctl(struct inode *inode,
1863 path->keep_locks = 1; 1892 path->keep_locks = 1;
1864 1893
1865 while(1) { 1894 while(1) {
1866 ret = btrfs_search_forward(root, &key, &max_key, path, 0, 1895 ret = btrfs_search_forward(root, &key, &max_key, path,
1867 sk->min_transid); 1896 sk->min_transid);
1868 if (ret != 0) { 1897 if (ret != 0) {
1869 if (ret > 0) 1898 if (ret > 0)
@@ -2035,6 +2064,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
2035 struct btrfs_root *dest = NULL; 2064 struct btrfs_root *dest = NULL;
2036 struct btrfs_ioctl_vol_args *vol_args; 2065 struct btrfs_ioctl_vol_args *vol_args;
2037 struct btrfs_trans_handle *trans; 2066 struct btrfs_trans_handle *trans;
2067 struct btrfs_block_rsv block_rsv;
2068 u64 qgroup_reserved;
2038 int namelen; 2069 int namelen;
2039 int ret; 2070 int ret;
2040 int err = 0; 2071 int err = 0;
@@ -2124,12 +2155,23 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
2124 if (err) 2155 if (err)
2125 goto out_up_write; 2156 goto out_up_write;
2126 2157
2158 btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
2159 /*
2160 * One for dir inode, two for dir entries, two for root
2161 * ref/backref.
2162 */
2163 err = btrfs_subvolume_reserve_metadata(root, &block_rsv,
2164 5, &qgroup_reserved);
2165 if (err)
2166 goto out_up_write;
2167
2127 trans = btrfs_start_transaction(root, 0); 2168 trans = btrfs_start_transaction(root, 0);
2128 if (IS_ERR(trans)) { 2169 if (IS_ERR(trans)) {
2129 err = PTR_ERR(trans); 2170 err = PTR_ERR(trans);
2130 goto out_up_write; 2171 goto out_release;
2131 } 2172 }
2132 trans->block_rsv = &root->fs_info->global_block_rsv; 2173 trans->block_rsv = &block_rsv;
2174 trans->bytes_reserved = block_rsv.size;
2133 2175
2134 ret = btrfs_unlink_subvol(trans, root, dir, 2176 ret = btrfs_unlink_subvol(trans, root, dir,
2135 dest->root_key.objectid, 2177 dest->root_key.objectid,
@@ -2159,10 +2201,14 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
2159 } 2201 }
2160 } 2202 }
2161out_end_trans: 2203out_end_trans:
2204 trans->block_rsv = NULL;
2205 trans->bytes_reserved = 0;
2162 ret = btrfs_end_transaction(trans, root); 2206 ret = btrfs_end_transaction(trans, root);
2163 if (ret && !err) 2207 if (ret && !err)
2164 err = ret; 2208 err = ret;
2165 inode->i_flags |= S_DEAD; 2209 inode->i_flags |= S_DEAD;
2210out_release:
2211 btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
2166out_up_write: 2212out_up_write:
2167 up_write(&root->fs_info->subvol_sem); 2213 up_write(&root->fs_info->subvol_sem);
2168out_unlock: 2214out_unlock:
@@ -2171,6 +2217,12 @@ out_unlock:
2171 shrink_dcache_sb(root->fs_info->sb); 2217 shrink_dcache_sb(root->fs_info->sb);
2172 btrfs_invalidate_inodes(dest); 2218 btrfs_invalidate_inodes(dest);
2173 d_delete(dentry); 2219 d_delete(dentry);
2220
2221 /* the last ref */
2222 if (dest->cache_inode) {
2223 iput(dest->cache_inode);
2224 dest->cache_inode = NULL;
2225 }
2174 } 2226 }
2175out_dput: 2227out_dput:
2176 dput(dentry); 2228 dput(dentry);
@@ -2211,10 +2263,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
2211 ret = -EPERM; 2263 ret = -EPERM;
2212 goto out; 2264 goto out;
2213 } 2265 }
2214 ret = btrfs_defrag_root(root, 0); 2266 ret = btrfs_defrag_root(root);
2215 if (ret) 2267 if (ret)
2216 goto out; 2268 goto out;
2217 ret = btrfs_defrag_root(root->fs_info->extent_root, 0); 2269 ret = btrfs_defrag_root(root->fs_info->extent_root);
2218 break; 2270 break;
2219 case S_IFREG: 2271 case S_IFREG:
2220 if (!(file->f_mode & FMODE_WRITE)) { 2272 if (!(file->f_mode & FMODE_WRITE)) {
@@ -3111,7 +3163,7 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
3111 u64 transid; 3163 u64 transid;
3112 int ret; 3164 int ret;
3113 3165
3114 trans = btrfs_attach_transaction(root); 3166 trans = btrfs_attach_transaction_barrier(root);
3115 if (IS_ERR(trans)) { 3167 if (IS_ERR(trans)) {
3116 if (PTR_ERR(trans) != -ENOENT) 3168 if (PTR_ERR(trans) != -ENOENT)
3117 return PTR_ERR(trans); 3169 return PTR_ERR(trans);
@@ -3289,7 +3341,7 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
3289 struct inode_fs_paths *ipath = NULL; 3341 struct inode_fs_paths *ipath = NULL;
3290 struct btrfs_path *path; 3342 struct btrfs_path *path;
3291 3343
3292 if (!capable(CAP_SYS_ADMIN)) 3344 if (!capable(CAP_DAC_READ_SEARCH))
3293 return -EPERM; 3345 return -EPERM;
3294 3346
3295 path = btrfs_alloc_path(); 3347 path = btrfs_alloc_path();
@@ -3914,6 +3966,65 @@ out:
3914 return ret; 3966 return ret;
3915} 3967}
3916 3968
3969static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg)
3970{
3971 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3972 const char *label = root->fs_info->super_copy->label;
3973 size_t len = strnlen(label, BTRFS_LABEL_SIZE);
3974 int ret;
3975
3976 if (len == BTRFS_LABEL_SIZE) {
3977 pr_warn("btrfs: label is too long, return the first %zu bytes\n",
3978 --len);
3979 }
3980
3981 mutex_lock(&root->fs_info->volume_mutex);
3982 ret = copy_to_user(arg, label, len);
3983 mutex_unlock(&root->fs_info->volume_mutex);
3984
3985 return ret ? -EFAULT : 0;
3986}
3987
3988static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
3989{
3990 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3991 struct btrfs_super_block *super_block = root->fs_info->super_copy;
3992 struct btrfs_trans_handle *trans;
3993 char label[BTRFS_LABEL_SIZE];
3994 int ret;
3995
3996 if (!capable(CAP_SYS_ADMIN))
3997 return -EPERM;
3998
3999 if (copy_from_user(label, arg, sizeof(label)))
4000 return -EFAULT;
4001
4002 if (strnlen(label, BTRFS_LABEL_SIZE) == BTRFS_LABEL_SIZE) {
4003 pr_err("btrfs: unable to set label with more than %d bytes\n",
4004 BTRFS_LABEL_SIZE - 1);
4005 return -EINVAL;
4006 }
4007
4008 ret = mnt_want_write_file(file);
4009 if (ret)
4010 return ret;
4011
4012 mutex_lock(&root->fs_info->volume_mutex);
4013 trans = btrfs_start_transaction(root, 0);
4014 if (IS_ERR(trans)) {
4015 ret = PTR_ERR(trans);
4016 goto out_unlock;
4017 }
4018
4019 strcpy(super_block->label, label);
4020 ret = btrfs_end_transaction(trans, root);
4021
4022out_unlock:
4023 mutex_unlock(&root->fs_info->volume_mutex);
4024 mnt_drop_write_file(file);
4025 return ret;
4026}
4027
3917long btrfs_ioctl(struct file *file, unsigned int 4028long btrfs_ioctl(struct file *file, unsigned int
3918 cmd, unsigned long arg) 4029 cmd, unsigned long arg)
3919{ 4030{
@@ -4014,6 +4125,10 @@ long btrfs_ioctl(struct file *file, unsigned int
4014 return btrfs_ioctl_qgroup_limit(file, argp); 4125 return btrfs_ioctl_qgroup_limit(file, argp);
4015 case BTRFS_IOC_DEV_REPLACE: 4126 case BTRFS_IOC_DEV_REPLACE:
4016 return btrfs_ioctl_dev_replace(root, argp); 4127 return btrfs_ioctl_dev_replace(root, argp);
4128 case BTRFS_IOC_GET_FSLABEL:
4129 return btrfs_ioctl_get_fslabel(file, argp);
4130 case BTRFS_IOC_SET_FSLABEL:
4131 return btrfs_ioctl_set_fslabel(file, argp);
4017 } 4132 }
4018 4133
4019 return -ENOTTY; 4134 return -ENOTTY;