Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73d59314 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (864 commits)
  Btrfs: explicitly mark the tree log root for writeback
  Btrfs: Drop the hardware crc32c asm code
  Btrfs: Add Documentation/filesystem/btrfs.txt, remove old COPYING
  Btrfs: kmap_atomic(KM_USER0) is safe for btrfs_readpage_end_io_hook
  Btrfs: Don't use kmap_atomic(..., KM_IRQ0) during checksum verifies
  Btrfs: tree logging checksum fixes
  Btrfs: don't change file extent's ram_bytes in btrfs_drop_extents
  Btrfs: Use btrfs_join_transaction to avoid deadlocks during snapshot creation
  Btrfs: drop remaining LINUX_KERNEL_VERSION checks and compat code
  Btrfs: drop EXPORT symbols from extent_io.c
  Btrfs: Fix checkpatch.pl warnings
  Btrfs: Fix free block discard calls down to the block layer
  Btrfs: avoid orphan inode caused by log replay
  Btrfs: avoid potential super block corruption
  Btrfs: do not call kfree if kmalloc failed in btrfs_sysfs_add_super
  Btrfs: fix a memory leak in btrfs_get_sb
  Btrfs: Fix typo in clear_state_cb
  Btrfs: Fix memset length in btrfs_file_write
  Btrfs: update directory's size when creating subvol/snapshot
  Btrfs: add permission checks to the ioctls
  ...
parents 6ddaab20 e293e97e
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line

	BTRFS
	=====

Btrfs is a new copy on write filesystem for Linux aimed at
implementing advanced features while focusing on fault tolerance,
repair and easy administration. Initially developed by Oracle, Btrfs
is licensed under the GPL and open for contribution from anyone.

Linux has a wealth of filesystems to choose from, but we are facing a
number of challenges with scaling to the large storage subsystems that
are becoming common in today's data centers. Filesystems need to scale
in their ability to address and manage large storage, and also in
their ability to detect, repair and tolerate errors in the data stored
on disk.  Btrfs is under heavy development, and is not suitable for
any uses other than benchmarking and review. The Btrfs disk format is
not yet finalized.

The main Btrfs features include:

    * Extent based file storage (2^64 max file size)
    * Space efficient packing of small files
    * Space efficient indexed directories
    * Dynamic inode allocation
    * Writable snapshots
    * Subvolumes (separate internal filesystem roots)
    * Object level mirroring and striping
    * Checksums on data and metadata (multiple algorithms available)
    * Compression
    * Integrated multiple device support, with several raid algorithms
    * Online filesystem check (not yet implemented)
    * Very fast offline filesystem check
    * Efficient incremental backup and FS mirroring (not yet implemented)
    * Online filesystem defragmentation



	MAILING LIST
	============

There is a Btrfs mailing list hosted on vger.kernel.org. You can
find details on how to subscribe here:

http://vger.kernel.org/vger-lists.html#linux-btrfs

Mailing list archives are available from gmane:

http://dir.gmane.org/gmane.comp.file-systems.btrfs



	IRC
	===

Discussion of Btrfs also occurs on the #btrfs channel of the Freenode
IRC network.



	UTILITIES
	=========

Userspace tools for creating and manipulating Btrfs file systems are
available from the git repository at the following location:

 http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
 git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git

These include the following tools:

mkfs.btrfs: create a filesystem

btrfsctl: control program to create snapshots and subvolumes:

	mount /dev/sda2 /mnt
	btrfsctl -s new_subvol_name /mnt
	btrfsctl -s snapshot_of_default /mnt/default
	btrfsctl -s snapshot_of_new_subvol /mnt/new_subvol_name
	btrfsctl -s snapshot_of_a_snapshot /mnt/snapshot_of_new_subvol
	ls /mnt
	default snapshot_of_a_snapshot snapshot_of_new_subvol
	new_subvol_name snapshot_of_default

	Snapshots and subvolumes cannot be deleted right now, but you can
	rm -rf all the files and directories inside them.

btrfsck: do a limited check of the FS extent trees.

btrfs-debug-tree: print all of the FS metadata in text form.  Example:

	btrfs-debug-tree /dev/sda2 >& big_output_file
+19 −0
Original line number Diff line number Diff line
@@ -269,6 +269,25 @@ config OCFS2_FS_POSIX_ACL
	  Posix Access Control Lists (ACLs) support permissions for users and
	  groups beyond the owner/group/world scheme.

config BTRFS_FS
	tristate "Btrfs filesystem (EXPERIMENTAL) Unstable disk format"
	depends on EXPERIMENTAL
	select LIBCRC32C
	select ZLIB_INFLATE
	select ZLIB_DEFLATE
	help
	  Btrfs is a new filesystem with extents, writable snapshotting,
	  support for multiple devices and many more features.

	  Btrfs is highly experimental, and THE DISK FORMAT IS NOT YET
	  FINALIZED.  You should say N here unless you are interested in
	  testing Btrfs with non-critical data.

	  To compile this file system support as a module, choose M here. The
	  module will be called btrfs.

	  If unsure, say N.

endif # BLOCK

source "fs/notify/Kconfig"
+1 −0
Original line number Diff line number Diff line
@@ -119,4 +119,5 @@ obj-$(CONFIG_HOSTFS) += hostfs/
obj-$(CONFIG_HPPFS)		+= hppfs/
obj-$(CONFIG_DEBUG_FS)		+= debugfs/
obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
obj-$(CONFIG_BTRFS_FS)		+= btrfs/
obj-$(CONFIG_GFS2_FS)           += gfs2/

fs/btrfs/Makefile

0 → 100644
+25 −0
Original line number Diff line number Diff line
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile

obj-$(CONFIG_BTRFS_FS) := btrfs.o
btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
	   file-item.o inode-item.o inode-map.o disk-io.o \
	   transaction.o inode.o file.o tree-defrag.o \
	   extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
	   extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
	   ref-cache.o export.o tree-log.o acl.o free-space-cache.o zlib.o \
	   compression.o
else

# Normal Makefile

KERNELDIR := /lib/modules/`uname -r`/build
all:
	$(MAKE) -C $(KERNELDIR) M=`pwd` CONFIG_BTRFS_FS=m modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=`pwd` modules_install
clean:
	$(MAKE) -C $(KERNELDIR) M=`pwd` clean

endif

fs/btrfs/acl.c

0 → 100644
+351 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 Red Hat.  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.
 */

#include <linux/fs.h>
#include <linux/string.h>
#include <linux/xattr.h>
#include <linux/posix_acl_xattr.h>
#include <linux/posix_acl.h>
#include <linux/sched.h>

#include "ctree.h"
#include "btrfs_inode.h"
#include "xattr.h"

#ifdef CONFIG_FS_POSIX_ACL

static void btrfs_update_cached_acl(struct inode *inode,
				    struct posix_acl **p_acl,
				    struct posix_acl *acl)
{
	spin_lock(&inode->i_lock);
	if (*p_acl && *p_acl != BTRFS_ACL_NOT_CACHED)
		posix_acl_release(*p_acl);
	*p_acl = posix_acl_dup(acl);
	spin_unlock(&inode->i_lock);
}

static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
{
	int size;
	const char *name;
	char *value = NULL;
	struct posix_acl *acl = NULL, **p_acl;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		p_acl = &BTRFS_I(inode)->i_acl;
		break;
	case ACL_TYPE_DEFAULT:
		name = POSIX_ACL_XATTR_DEFAULT;
		p_acl = &BTRFS_I(inode)->i_default_acl;
		break;
	default:
		return ERR_PTR(-EINVAL);
	}

	spin_lock(&inode->i_lock);
	if (*p_acl != BTRFS_ACL_NOT_CACHED)
		acl = posix_acl_dup(*p_acl);
	spin_unlock(&inode->i_lock);

	if (acl)
		return acl;


	size = __btrfs_getxattr(inode, name, "", 0);
	if (size > 0) {
		value = kzalloc(size, GFP_NOFS);
		if (!value)
			return ERR_PTR(-ENOMEM);
		size = __btrfs_getxattr(inode, name, value, size);
		if (size > 0) {
			acl = posix_acl_from_xattr(value, size);
			btrfs_update_cached_acl(inode, p_acl, acl);
		}
		kfree(value);
	} else if (size == -ENOENT) {
		acl = NULL;
		btrfs_update_cached_acl(inode, p_acl, acl);
	}

	return acl;
}

static int btrfs_xattr_get_acl(struct inode *inode, int type,
			       void *value, size_t size)
{
	struct posix_acl *acl;
	int ret = 0;

	acl = btrfs_get_acl(inode, type);

	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (acl == NULL)
		return -ENODATA;
	ret = posix_acl_to_xattr(acl, value, size);
	posix_acl_release(acl);

	return ret;
}

/*
 * Needs to be called with fs_mutex held
 */
static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int ret, size = 0;
	const char *name;
	struct posix_acl **p_acl;
	char *value = NULL;
	mode_t mode;

	if (acl) {
		ret = posix_acl_valid(acl);
		if (ret < 0)
			return ret;
		ret = 0;
	}

	switch (type) {
	case ACL_TYPE_ACCESS:
		mode = inode->i_mode;
		ret = posix_acl_equiv_mode(acl, &mode);
		if (ret < 0)
			return ret;
		ret = 0;
		inode->i_mode = mode;
		name = POSIX_ACL_XATTR_ACCESS;
		p_acl = &BTRFS_I(inode)->i_acl;
		break;
	case ACL_TYPE_DEFAULT:
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EINVAL : 0;
		name = POSIX_ACL_XATTR_DEFAULT;
		p_acl = &BTRFS_I(inode)->i_default_acl;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_NOFS);
		if (!value) {
			ret = -ENOMEM;
			goto out;
		}

		ret = posix_acl_to_xattr(acl, value, size);
		if (ret < 0)
			goto out;
	}

	ret = __btrfs_setxattr(inode, name, value, size, 0);

out:
	kfree(value);

	if (!ret)
		btrfs_update_cached_acl(inode, p_acl, acl);

	return ret;
}

static int btrfs_xattr_set_acl(struct inode *inode, int type,
			       const void *value, size_t size)
{
	int ret = 0;
	struct posix_acl *acl = NULL;

	if (value) {
		acl = posix_acl_from_xattr(value, size);
		if (acl == NULL) {
			value = NULL;
			size = 0;
		} else if (IS_ERR(acl)) {
			return PTR_ERR(acl);
		}
	}

	ret = btrfs_set_acl(inode, acl, type);

	posix_acl_release(acl);

	return ret;
}


static int btrfs_xattr_acl_access_get(struct inode *inode, const char *name,
				      void *value, size_t size)
{
	return btrfs_xattr_get_acl(inode, ACL_TYPE_ACCESS, value, size);
}

static int btrfs_xattr_acl_access_set(struct inode *inode, const char *name,
				      const void *value, size_t size, int flags)
{
	return btrfs_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}

static int btrfs_xattr_acl_default_get(struct inode *inode, const char *name,
				       void *value, size_t size)
{
	return btrfs_xattr_get_acl(inode, ACL_TYPE_DEFAULT, value, size);
}

static int btrfs_xattr_acl_default_set(struct inode *inode, const char *name,
			       const void *value, size_t size, int flags)
{
	return btrfs_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}

int btrfs_check_acl(struct inode *inode, int mask)
{
	struct posix_acl *acl;
	int error = -EAGAIN;

	acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);

	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (acl) {
		error = posix_acl_permission(inode, acl, mask);
		posix_acl_release(acl);
	}

	return error;
}

/*
 * btrfs_init_acl is already generally called under fs_mutex, so the locking
 * stuff has been fixed to work with that.  If the locking stuff changes, we
 * need to re-evaluate the acl locking stuff.
 */
int btrfs_init_acl(struct inode *inode, struct inode *dir)
{
	struct posix_acl *acl = NULL;
	int ret = 0;

	/* this happens with subvols */
	if (!dir)
		return 0;

	if (!S_ISLNK(inode->i_mode)) {
		if (IS_POSIXACL(dir)) {
			acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT);
			if (IS_ERR(acl))
				return PTR_ERR(acl);
		}

		if (!acl)
			inode->i_mode &= ~current->fs->umask;
	}

	if (IS_POSIXACL(dir) && acl) {
		struct posix_acl *clone;
		mode_t mode;

		if (S_ISDIR(inode->i_mode)) {
			ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
			if (ret)
				goto failed;
		}
		clone = posix_acl_clone(acl, GFP_NOFS);
		ret = -ENOMEM;
		if (!clone)
			goto failed;

		mode = inode->i_mode;
		ret = posix_acl_create_masq(clone, &mode);
		if (ret >= 0) {
			inode->i_mode = mode;
			if (ret > 0) {
				/* we need an acl */
				ret = btrfs_set_acl(inode, clone,
						    ACL_TYPE_ACCESS);
			}
		}
	}
failed:
	posix_acl_release(acl);

	return ret;
}

int btrfs_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
	int ret = 0;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	if (!IS_POSIXACL(inode))
		return 0;

	acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);

	clone = posix_acl_clone(acl, GFP_KERNEL);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;

	ret = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!ret)
		ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);

	posix_acl_release(clone);

	return ret;
}

struct xattr_handler btrfs_xattr_acl_default_handler = {
	.prefix = POSIX_ACL_XATTR_DEFAULT,
	.get	= btrfs_xattr_acl_default_get,
	.set	= btrfs_xattr_acl_default_set,
};

struct xattr_handler btrfs_xattr_acl_access_handler = {
	.prefix = POSIX_ACL_XATTR_ACCESS,
	.get	= btrfs_xattr_acl_access_get,
	.set	= btrfs_xattr_acl_access_set,
};

#else /* CONFIG_FS_POSIX_ACL */

int btrfs_acl_chmod(struct inode *inode)
{
	return 0;
}

int btrfs_init_acl(struct inode *inode, struct inode *dir)
{
	return 0;
}

int btrfs_check_acl(struct inode *inode, int mask)
{
	return 0;
}

#endif /* CONFIG_FS_POSIX_ACL */
Loading