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

Commit e6395b68 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-v3.10-rc5' of git://oss.sgi.com/xfs/xfs

Pull more xfs updates from Ben Myers:
 "Here are several fixes for filesystems with CRC support turned on:
  fixes for quota, remote attributes, and recovery.  There is also some
  feature work related to CRCs: the implementation of CRCs for the inode
  unlinked lists, disabling noattr2/attr2 options when appropriate, and
  bumping the maximum number of ACLs.

  I would have preferred to defer this last category of items to 3.11.
  This would require setting a feature bit for the on-disk changes, so
  there is some pressure to get these in 3.10.  I believe this
  represents the end of the CRC related queue.

   - Rework of dquot CRCs
   - Fix for remote attribute invalidation of a leaf
   - Fix ordering of transaction replay in recovery
   - Implement CRCs for inode unlinked list
   - Disable noattr2/attr2 mount options when CRCs are enabled
   - Bump the limitation of ACL entries for v5 superblocks"

* tag 'for-linus-v3.10-rc5' of git://oss.sgi.com/xfs/xfs:
  xfs: increase number of ACL entries for V5 superblocks
  xfs: disable noattr2/attr2 mount options for CRC enabled filesystems
  xfs: inode unlinked list needs to recalculate the inode CRC
  xfs: fix log recovery transaction item reordering
  xfs: fix remote attribute invalidation for a leaf
  xfs: rework dquot CRCs
parents 29eb7782 0a8aa193
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ When mounting an XFS filesystem, the following options are accepted.
	removing extended attributes) the on-disk superblock feature
	bit field will be updated to reflect this format being in use.

	CRC enabled filesystems always use the attr2 format, and so
	will reject the noattr2 mount option if it is set.

  barrier
	Enables the use of block layer write barriers for writes into
	the journal and unwritten extent conversion.  This allows for
+18 −13
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
#include "xfs_vnodeops.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
#include "xfs_trace.h"
#include <linux/slab.h>
#include <linux/xattr.h>
@@ -34,7 +36,9 @@
 */

STATIC struct posix_acl *
xfs_acl_from_disk(struct xfs_acl *aclp)
xfs_acl_from_disk(
	struct xfs_acl	*aclp,
	int		max_entries)
{
	struct posix_acl_entry *acl_e;
	struct posix_acl *acl;
@@ -42,7 +46,7 @@ xfs_acl_from_disk(struct xfs_acl *aclp)
	unsigned int count, i;

	count = be32_to_cpu(aclp->acl_cnt);
	if (count > XFS_ACL_MAX_ENTRIES)
	if (count > max_entries)
		return ERR_PTR(-EFSCORRUPTED);

	acl = posix_acl_alloc(count, GFP_KERNEL);
@@ -108,9 +112,9 @@ xfs_get_acl(struct inode *inode, int type)
	struct xfs_inode *ip = XFS_I(inode);
	struct posix_acl *acl;
	struct xfs_acl *xfs_acl;
	int len = sizeof(struct xfs_acl);
	unsigned char *ea_name;
	int error;
	int len;

	acl = get_cached_acl(inode, type);
	if (acl != ACL_NOT_CACHED)
@@ -133,8 +137,8 @@ xfs_get_acl(struct inode *inode, int type)
	 * If we have a cached ACLs value just return it, not need to
	 * go out to the disk.
	 */

	xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
	len = XFS_ACL_MAX_SIZE(ip->i_mount);
	xfs_acl = kzalloc(len, GFP_KERNEL);
	if (!xfs_acl)
		return ERR_PTR(-ENOMEM);

@@ -153,7 +157,7 @@ xfs_get_acl(struct inode *inode, int type)
		goto out;
	}

	acl = xfs_acl_from_disk(xfs_acl);
	acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount));
	if (IS_ERR(acl))
		goto out;

@@ -189,16 +193,17 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)

	if (acl) {
		struct xfs_acl *xfs_acl;
		int len;
		int len = XFS_ACL_MAX_SIZE(ip->i_mount);

		xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
		xfs_acl = kzalloc(len, GFP_KERNEL);
		if (!xfs_acl)
			return -ENOMEM;

		xfs_acl_to_disk(xfs_acl, acl);
		len = sizeof(struct xfs_acl) -
			(sizeof(struct xfs_acl_entry) *
			 (XFS_ACL_MAX_ENTRIES - acl->a_count));

		/* subtract away the unused acl entries */
		len -= sizeof(struct xfs_acl_entry) *
			 (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);

		error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
				len, ATTR_ROOT);
@@ -243,7 +248,7 @@ xfs_set_mode(struct inode *inode, umode_t mode)
static int
xfs_acl_exists(struct inode *inode, unsigned char *name)
{
	int len = sizeof(struct xfs_acl);
	int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb));

	return (xfs_attr_get(XFS_I(inode), name, NULL, &len,
			    ATTR_ROOT|ATTR_KERNOVAL) == 0);
@@ -379,7 +384,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
		goto out_release;

	error = -EINVAL;
	if (acl->a_count > XFS_ACL_MAX_ENTRIES)
	if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
		goto out_release;

	if (type == ACL_TYPE_ACCESS) {
+24 −7
Original line number Diff line number Diff line
@@ -22,19 +22,36 @@ struct inode;
struct posix_acl;
struct xfs_inode;

#define XFS_ACL_MAX_ENTRIES 25
#define XFS_ACL_NOT_PRESENT (-1)

/* On-disk XFS access control list structure */
struct xfs_acl {
	__be32		acl_cnt;
struct xfs_acl_entry {
	__be32	ae_tag;
	__be32	ae_id;
	__be16	ae_perm;
	} acl_entry[XFS_ACL_MAX_ENTRIES];
	__be16	ae_pad;		/* fill the implicit hole in the structure */
};

struct xfs_acl {
	__be32			acl_cnt;
	struct xfs_acl_entry	acl_entry[0];
};

/*
 * The number of ACL entries allowed is defined by the on-disk format.
 * For v4 superblocks, that is limited to 25 entries. For v5 superblocks, it is
 * limited only by the maximum size of the xattr that stores the information.
 */
#define XFS_ACL_MAX_ENTRIES(mp)	\
	(xfs_sb_version_hascrc(&mp->m_sb) \
		?  (XATTR_SIZE_MAX - sizeof(struct xfs_acl)) / \
						sizeof(struct xfs_acl_entry) \
		: 25)

#define XFS_ACL_MAX_SIZE(mp) \
	(sizeof(struct xfs_acl) + \
		sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp)))

/* On-disk XFS extended attribute names */
#define SGI_ACL_FILE		(unsigned char *)"SGI_ACL_FILE"
#define SGI_ACL_DEFAULT		(unsigned char *)"SGI_ACL_DEFAULT"
+1 −1
Original line number Diff line number Diff line
@@ -3258,7 +3258,7 @@ xfs_attr3_leaf_inactive(
			name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
			if (name_rmt->valueblk) {
				lp->valueblk = be32_to_cpu(name_rmt->valueblk);
				lp->valuelen = XFS_B_TO_FSB(dp->i_mount,
				lp->valuelen = xfs_attr3_rmt_blocks(dp->i_mount,
						    be32_to_cpu(name_rmt->valuelen));
				lp++;
			}
+16 −21
Original line number Diff line number Diff line
@@ -249,8 +249,11 @@ xfs_qm_init_dquot_blk(
		d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
		d->dd_diskdq.d_id = cpu_to_be32(curid);
		d->dd_diskdq.d_flags = type;
		if (xfs_sb_version_hascrc(&mp->m_sb))
		if (xfs_sb_version_hascrc(&mp->m_sb)) {
			uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
			xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
					 XFS_DQUOT_CRC_OFF);
		}
	}

	xfs_trans_dquot_buf(tp, bp,
@@ -286,23 +289,6 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
	dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
}

STATIC void
xfs_dquot_buf_calc_crc(
	struct xfs_mount	*mp,
	struct xfs_buf		*bp)
{
	struct xfs_dqblk	*d = (struct xfs_dqblk *)bp->b_addr;
	int			i;

	if (!xfs_sb_version_hascrc(&mp->m_sb))
		return;

	for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++, d++) {
		xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
				 offsetof(struct xfs_dqblk, dd_crc));
	}
}

STATIC bool
xfs_dquot_buf_verify_crc(
	struct xfs_mount	*mp,
@@ -328,12 +314,11 @@ xfs_dquot_buf_verify_crc(

	for (i = 0; i < ndquots; i++, d++) {
		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
				 offsetof(struct xfs_dqblk, dd_crc)))
				 XFS_DQUOT_CRC_OFF))
			return false;
		if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
			return false;
	}

	return true;
}

@@ -393,6 +378,11 @@ xfs_dquot_buf_read_verify(
	}
}

/*
 * we don't calculate the CRC here as that is done when the dquot is flushed to
 * the buffer after the update is done. This ensures that the dquot in the
 * buffer always has an up-to-date CRC value.
 */
void
xfs_dquot_buf_write_verify(
	struct xfs_buf	*bp)
@@ -404,7 +394,6 @@ xfs_dquot_buf_write_verify(
		xfs_buf_ioerror(bp, EFSCORRUPTED);
		return;
	}
	xfs_dquot_buf_calc_crc(mp, bp);
}

const struct xfs_buf_ops xfs_dquot_buf_ops = {
@@ -1151,11 +1140,17 @@ xfs_qm_dqflush(
	 * copy the lsn into the on-disk dquot now while we have the in memory
	 * dquot here. This can't be done later in the write verifier as we
	 * can't get access to the log item at that point in time.
	 *
	 * We also calculate the CRC here so that the on-disk dquot in the
	 * buffer always has a valid CRC. This ensures there is no possibility
	 * of a dquot without an up-to-date CRC getting to disk.
	 */
	if (xfs_sb_version_hascrc(&mp->m_sb)) {
		struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddqp;

		dqb->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
		xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
				 XFS_DQUOT_CRC_OFF);
	}

	/*
Loading