Add the "btrfs filesystem label" command

Hi all,

this patch adds the command "btrfs filesystem label" to change (or show) the
label of a filesystem.
This patch is a subset of the one written previously by Morey Roof. I
included the user space part only. So it is possible only to change/show a
label of a *single device* and *unounted* filesystem.

The reason of excluding the kernel space part, is to simplify the patch in
order to speed the check and then the merging of the patch itself. In fact I
have to point out that in the past there was almost three attempts to propose
this patch, without success neither complaints.

Chris, let me know how you want to proceed. I know that you are very busy,
and you prefer to work to stabilize btrfs instead adding new feature. But I
think that changing a label is a *essential* feature for a filesystem
managing tool. Think about a mount by LABEL.

To show a label

$ btrfs filesystem label <device>

To set a label

$ btrfs filesystem label <device> <newlabel>

Please guys, give a look to the source.
Comments are welcome.

You can pull the source from the branch "label" of the repository
http://cassiopea.homelinux.net/git/btrfs-progs-unstable.git

Regards
G.Baroncelli

Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
Goffredo Baroncelli 2010-12-05 17:46:44 +00:00 committed by Chris Mason
parent 002d021c5f
commit e8f47cf068
9 changed files with 222 additions and 6 deletions

View File

@ -4,7 +4,7 @@ CFLAGS = -g -Werror -Os
objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
root-tree.o dir-item.o file-item.o inode-item.o \ root-tree.o dir-item.o file-item.o inode-item.o \
inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \ inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \
volumes.o utils.o btrfs-list.o volumes.o utils.o btrfs-list.o btrfslabel.o
# #
CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \

View File

@ -108,11 +108,6 @@ static struct Command commands[] = {
"device delete", "<device> [<device>...] <path>\n" "device delete", "<device> [<device>...] <path>\n"
"Remove a device from a filesystem." "Remove a device from a filesystem."
}, },
/* coming soon
{ 2, "filesystem label", "<label> <path>\n"
"Set the label of a filesystem"
}
*/
{ 0, 0 , 0 } { 0, 0 , 0 }
}; };

View File

@ -40,6 +40,7 @@
#include "volumes.h" #include "volumes.h"
#include "btrfs_cmds.h" #include "btrfs_cmds.h"
#include "btrfslabel.h"
#ifdef __CHECKER__ #ifdef __CHECKER__
#define BLKGETSIZE64 0 #define BLKGETSIZE64 0
@ -874,6 +875,21 @@ int do_set_default_subvol(int nargs, char **argv)
return 0; return 0;
} }
int do_change_label(int nargs, char **argv)
{
/* check the number of argument */
if ( nargs > 3 ){
fprintf(stderr, "ERROR: '%s' requires maximum 2 args\n",
argv[0]);
return -2;
}else if (nargs == 2){
return get_label(argv[1]);
} else { /* nargs == 0 */
return set_label(argv[1], argv[2]);
}
}
int do_df_filesystem(int nargs, char **argv) int do_df_filesystem(int nargs, char **argv)
{ {
struct btrfs_ioctl_space_args *sargs; struct btrfs_ioctl_space_args *sargs;

View File

@ -32,3 +32,4 @@ int list_subvols(int fd);
int do_df_filesystem(int nargs, char **argv); int do_df_filesystem(int nargs, char **argv);
int find_updated_files(int fd, u64 root_id, u64 oldest_gen); int find_updated_files(int fd, u64 root_id, u64 oldest_gen);
int do_find_newer(int argc, char **argv); int do_find_newer(int argc, char **argv);
int do_change_label(int argc, char **argv);

121
btrfslabel.c Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2008 Morey Roof. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#define _GNU_SOURCE
#ifndef __CHECKER__
#include <sys/ioctl.h>
#include <sys/mount.h>
#include "ioctl.h"
#endif /* __CHECKER__ */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <ctype.h>
#include "kerncompat.h"
#include "ctree.h"
#include "utils.h"
#include "version.h"
#include "disk-io.h"
#include "transaction.h"
#define MOUNTED 1
#define UNMOUNTED 2
#define GET_LABEL 3
#define SET_LABEL 4
static void change_label_unmounted(char *dev, char *nLabel)
{
struct btrfs_root *root;
struct btrfs_trans_handle *trans;
/* Open the super_block at the default location
* and as read-write.
*/
root = open_ctree(dev, 0, 1);
trans = btrfs_start_transaction(root, 1);
strncpy(root->fs_info->super_copy.label, nLabel, BTRFS_LABEL_SIZE);
btrfs_commit_transaction(trans, root);
/* Now we close it since we are done. */
close_ctree(root);
}
static void get_label_unmounted(char *dev)
{
struct btrfs_root *root;
/* Open the super_block at the default location
* and as read-only.
*/
root = open_ctree(dev, 0, 0);
fprintf(stdout, "%s\n", root->fs_info->super_copy.label);
/* Now we close it since we are done. */
close_ctree(root);
}
int get_label(char *btrfs_dev)
{
int ret;
ret = check_mounted(btrfs_dev);
if (ret < 0)
{
fprintf(stderr, "FATAL: error checking %s mount status\n", btrfs_dev);
return -1;
}
if(ret != 0)
{
fprintf(stderr, "FATAL: the filesystem has to be unmounted\n");
return -2;
}
get_label_unmounted(btrfs_dev);
return 0;
}
int set_label(char *btrfs_dev, char *nLabel)
{
int ret;
ret = check_mounted(btrfs_dev);
if (ret < 0)
{
fprintf(stderr, "FATAL: error checking %s mount status\n", btrfs_dev);
return -1;
}
if(ret != 0)
{
fprintf(stderr, "FATAL: the filesystem has to be unmounted\n");
return -2;
}
change_label_unmounted(btrfs_dev, nLabel);
return 0;
}

5
btrfslabel.h Normal file
View File

@ -0,0 +1,5 @@
/* btrflabel.h */
int get_label(char *btrfs_dev);
int set_label(char *btrfs_dev, char *nLabel);

View File

@ -19,6 +19,8 @@ btrfs \- control a btrfs filesystem
.PP .PP
\fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
.PP .PP
\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
.PP
\fBbtrfs\fP \fBfilesystem defrag\fP\fI [options] <file>|<dir> [<file>|<dir>...]\fP \fBbtrfs\fP \fBfilesystem defrag\fP\fI [options] <file>|<dir> [<file>|<dir>...]\fP
.PP .PP
\fBbtrfs\fP \fBsubvolume find-new\fP\fI <subvolume> <last_gen>\fP \fBbtrfs\fP \fBsubvolume find-new\fP\fI <subvolume> <last_gen>\fP
@ -164,6 +166,23 @@ can expand the partition before enlarging the filesystem and shrink the
partition after reducing the size of the filesystem. partition after reducing the size of the filesystem.
.TP .TP
\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
Show or update the label of a filesystem. \fI<dev>\fR is used to identify the
filesystem.
If a \fInewlabel\fR optional argument is passed, the label is changed. The
following costraints exist for a label:
.IP
- the maximum allowable lenght shall be less or equal than 256 chars
.IP
- the label shall not contain the '/' or '\\' characters.
NOTE: Currently there are the following limitations:
.IP
- the filesystem has to be unmounted
.IP
- the filesystem should not have more than one device.
.TP
\fBfilesystem show\fR [<uuid>|<label>]\fR \fBfilesystem show\fR [<uuid>|<label>]\fR
Show the btrfs filesystem with some additional info. If no UUID or label is Show the btrfs filesystem with some additional info. If no UUID or label is
passed, \fBbtrfs\fR show info of all the btrfs filesystem. passed, \fBbtrfs\fR show info of all the btrfs filesystem.

57
utils.c
View File

@ -812,6 +812,39 @@ out_mntloop_err:
return ret; return ret;
} }
/* Gets the mount point of btrfs filesystem that is using the specified device.
* Returns 0 is everything is good, <0 if we have an error.
* TODO: Fix this fucntion and check_mounted to work with multiple drive BTRFS
* setups.
*/
int get_mountpt(char *dev, char *mntpt, size_t size)
{
struct mntent *mnt;
FILE *f;
int ret = 0;
f = setmntent("/proc/mounts", "r");
if (f == NULL)
return -errno;
while ((mnt = getmntent(f)) != NULL )
{
if (strcmp(dev, mnt->mnt_fsname) == 0)
{
strncpy(mntpt, mnt->mnt_dir, size);
break;
}
}
if (mnt == NULL)
{
/* We didn't find an entry so lets report an error */
ret = -1;
}
return ret;
}
struct pending_dir { struct pending_dir {
struct list_head list; struct list_head list;
char name[256]; char name[256];
@ -1002,3 +1035,27 @@ char *pretty_sizes(u64 size)
return pretty; return pretty;
} }
/*
* Checks to make sure that the label matches our requirements.
* Returns:
0 if everything is safe and usable
-1 if the label is too long
-2 if the label contains an invalid character
*/
int check_label(char *input)
{
int i;
int len = strlen(input);
if (len > BTRFS_LABEL_SIZE) {
return -1;
}
for (i = 0; i < len; i++) {
if (input[i] == '/' || input[i] == '\\') {
return -2;
}
}
return 0;
}

View File

@ -40,4 +40,6 @@ int check_mounted(const char *devicename);
int btrfs_device_already_in_root(struct btrfs_root *root, int fd, int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
int super_offset); int super_offset);
char *pretty_sizes(u64 size); char *pretty_sizes(u64 size);
int check_label(char *input);
int get_mountpt(char *dev, char *mntpt, size_t size);
#endif #endif