Commit 91f1a956 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xfs-5.6-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs updates from Darrick Wong:
 "In this release we clean out the last of the old 32-bit timestamp
  code, fix a number of bugs and memory corruptions on 32-bit platforms,
  and a refactoring of some of the extended attribute code.

  I think I'll be back next week with some refactoring of how the XFS
  buffer code returns error codes, however I prefer to hold onto that
  for another week to let it soak a while longer

  Summary:

   - Get rid of compat_time_t

   - Convert time_t to time64_t in quota code

   - Remove shadow variables

   - Prevent ATTR_ flag misuse in the attrmulti ioctls

   - Clean out strlen in the attr code

   - Remove some bogus asserts

   - Fix various file size limit calculation errors with 32-bit kernels

   - Pack xfs_dir2_sf_entry_t to fix build errors on arm oabi

   - Fix nowait inode locking calls for directio aio reads

   - Fix memory corruption bugs when invalidating remote xattr value
     buffers

   - Streamline remote attr value removal

   - Make the buffer log format size consistent across platforms

   - Strengthen buffer log format size checking

   - Fix messed up return types of xfs_inode_need_cow

   - Fix some unused variable warnings"

* tag 'xfs-5.6-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (24 commits)
  xfs: remove unused variable 'done'
  xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
  xfs: change return value of xfs_inode_need_cow to int
  xfs: check log iovec size to make sure it's plausibly a buffer log format
  xfs: make struct xfs_buf_log_format have a consistent size
  xfs: complain if anyone tries to create a too-large buffer log item
  xfs: clean up xfs_buf_item_get_format return value
  xfs: streamline xfs_attr3_leaf_inactive
  xfs: fix memory corruption during remote attr value buffer invalidation
  xfs: refactor remote attr value buffer invalidation
  xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
  xfs: Add __packed to xfs_dir2_sf_entry_t definition
  xfs: fix s_maxbytes computation on 32-bit kernels
  xfs: truncate should remove all blocks, not just to the end of the page cache
  xfs: introduce XFS_MAX_FILEOFF
  xfs: remove bogus assertion when online repair isn't enabled
  xfs: Remove all strlen in all xfs_attr_* functions for attr names.
  xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
  xfs: also remove cached ACLs when removing the underlying attr
  xfs: reject invalid flags combinations in XFS_IOC_ATTRMULTI_BY_HANDLE
  ...
parents e5da4c93 b3531f5f
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ xfs_attr_args_init(
	struct xfs_da_args	*args,
	struct xfs_inode	*dp,
	const unsigned char	*name,
	size_t			namelen,
	int			flags)
{

@@ -74,7 +75,7 @@ xfs_attr_args_init(
	args->dp = dp;
	args->flags = flags;
	args->name = name;
	args->namelen = strlen((const char *)name);
	args->namelen = namelen;
	if (args->namelen >= MAXNAMELEN)
		return -EFAULT;		/* match IRIX behaviour */

@@ -139,6 +140,7 @@ int
xfs_attr_get(
	struct xfs_inode	*ip,
	const unsigned char	*name,
	size_t			namelen,
	unsigned char		**value,
	int			*valuelenp,
	int			flags)
@@ -154,7 +156,7 @@ xfs_attr_get(
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		return -EIO;

	error = xfs_attr_args_init(&args, ip, name, flags);
	error = xfs_attr_args_init(&args, ip, name, namelen, flags);
	if (error)
		return error;

@@ -338,6 +340,7 @@ int
xfs_attr_set(
	struct xfs_inode	*dp,
	const unsigned char	*name,
	size_t			namelen,
	unsigned char		*value,
	int			valuelen,
	int			flags)
@@ -353,7 +356,7 @@ xfs_attr_set(
	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
		return -EIO;

	error = xfs_attr_args_init(&args, dp, name, flags);
	error = xfs_attr_args_init(&args, dp, name, namelen, flags);
	if (error)
		return error;

@@ -442,6 +445,7 @@ int
xfs_attr_remove(
	struct xfs_inode	*dp,
	const unsigned char	*name,
	size_t			namelen,
	int			flags)
{
	struct xfs_mount	*mp = dp->i_mount;
@@ -453,7 +457,7 @@ xfs_attr_remove(
	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
		return -EIO;

	error = xfs_attr_args_init(&args, dp, name, flags);
	error = xfs_attr_args_init(&args, dp, name, namelen, flags);
	if (error)
		return error;

@@ -1007,7 +1011,7 @@ restart:
		 * The INCOMPLETE flag means that we will find the "old"
		 * attr, not the "new" one.
		 */
		args->flags |= XFS_ATTR_INCOMPLETE;
		args->op_flags |= XFS_DA_OP_INCOMPLETE;
		state = xfs_da_state_alloc();
		state->args = args;
		state->mp = mp;
+10 −5
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ struct xfs_attr_list_context;
 *========================================================================*/


#define ATTR_DONTFOLLOW	0x0001	/* -- unused, from IRIX -- */
#define ATTR_DONTFOLLOW	0x0001	/* -- ignored, from IRIX -- */
#define ATTR_ROOT	0x0002	/* use attrs in root (trusted) namespace */
#define ATTR_TRUST	0x0004	/* -- unused, from IRIX -- */
#define ATTR_SECURE	0x0008	/* use attrs in security namespace */
@@ -37,7 +37,10 @@ struct xfs_attr_list_context;
#define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */

#define ATTR_INCOMPLETE	0x4000	/* [kernel] return INCOMPLETE attr keys */
#define ATTR_ALLOC	0x8000	/* allocate xattr buffer on demand */
#define ATTR_ALLOC	0x8000	/* [kernel] allocate xattr buffer on demand */

#define ATTR_KERNEL_FLAGS \
	(ATTR_KERNOTIME | ATTR_KERNOVAL | ATTR_INCOMPLETE | ATTR_ALLOC)

#define XFS_ATTR_FLAGS \
	{ ATTR_DONTFOLLOW, 	"DONTFOLLOW" }, \
@@ -145,11 +148,13 @@ int xfs_attr_list_int(struct xfs_attr_list_context *);
int xfs_inode_hasattr(struct xfs_inode *ip);
int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
		 unsigned char **value, int *valuelenp, int flags);
		 size_t namelen, unsigned char **value, int *valuelenp,
		 int flags);
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
		 unsigned char *value, int valuelen, int flags);
		 size_t namelen, unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name,
		    size_t namelen, int flags);
int xfs_attr_remove_args(struct xfs_da_args *args);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
		  int flags, struct attrlist_cursor_kern *cursor);
+2 −2
Original line number Diff line number Diff line
@@ -2403,8 +2403,8 @@ xfs_attr3_leaf_lookup_int(
		 * If we are looking for INCOMPLETE entries, show only those.
		 * If we are looking for complete entries, show only those.
		 */
		if ((args->flags & XFS_ATTR_INCOMPLETE) !=
		    (entry->flags & XFS_ATTR_INCOMPLETE)) {
		if (!!(args->op_flags & XFS_DA_OP_INCOMPLETE) !=
		    !!(entry->flags & XFS_ATTR_INCOMPLETE)) {
			continue;
		}
		if (entry->flags & XFS_ATTR_LOCAL) {
+0 −9
Original line number Diff line number Diff line
@@ -39,15 +39,6 @@ struct xfs_attr3_icleaf_hdr {
	} freemap[XFS_ATTR_LEAF_MAPSIZE];
};

/*
 * Used to keep a list of "remote value" extents when unlinking an inode.
 */
typedef struct xfs_attr_inactive_list {
	xfs_dablk_t	valueblk;	/* block number of value bytes */
	int		valuelen;	/* number of bytes in value */
} xfs_attr_inactive_list_t;


/*========================================================================
 * Function prototypes for the kernel.
 *========================================================================*/
+63 −26
Original line number Diff line number Diff line
@@ -25,6 +25,23 @@

#define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */

/*
 * Remote Attribute Values
 * =======================
 *
 * Remote extended attribute values are conceptually simple -- they're written
 * to data blocks mapped by an inode's attribute fork, and they have an upper
 * size limit of 64k.  Setting a value does not involve the XFS log.
 *
 * However, on a v5 filesystem, maximally sized remote attr values require one
 * block more than 64k worth of space to hold both the remote attribute value
 * header (64 bytes).  On a 4k block filesystem this results in a 68k buffer;
 * on a 64k block filesystem, this would be a 128k buffer.  Note that the log
 * format can only handle a dirty buffer of XFS_MAX_BLOCKSIZE length (64k).
 * Therefore, we /must/ ensure that remote attribute value buffers never touch
 * the logging system and therefore never have a log item.
 */

/*
 * Each contiguous block has a header, so it is not just a simple attribute
 * length to FSB conversion.
@@ -401,17 +418,25 @@ xfs_attr_rmtval_get(
			       (map[i].br_startblock != HOLESTARTBLOCK));
			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
			dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
			error = xfs_trans_read_buf(mp, args->trans,
						   mp->m_ddev_targp,
						   dblkno, dblkcnt, 0, &bp,
			bp = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt, 0,
					&xfs_attr3_rmt_buf_ops);
			if (error)
			if (!bp)
				return -ENOMEM;
			error = bp->b_error;
			if (error) {
				xfs_buf_ioerror_alert(bp, __func__);
				xfs_buf_relse(bp);

				/* bad CRC means corrupted metadata */
				if (error == -EFSBADCRC)
					error = -EFSCORRUPTED;
				return error;
			}

			error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
							&offset, &valuelen,
							&dst);
			xfs_trans_brelse(args->trans, bp);
			xfs_buf_relse(bp);
			if (error)
				return error;

@@ -552,6 +577,33 @@ xfs_attr_rmtval_set(
	return 0;
}

/* Mark stale any incore buffers for the remote value. */
int
xfs_attr_rmtval_stale(
	struct xfs_inode	*ip,
	struct xfs_bmbt_irec	*map,
	xfs_buf_flags_t		incore_flags)
{
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_buf		*bp;

	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));

	if (XFS_IS_CORRUPT(mp, map->br_startblock == DELAYSTARTBLOCK) ||
	    XFS_IS_CORRUPT(mp, map->br_startblock == HOLESTARTBLOCK))
		return -EFSCORRUPTED;

	bp = xfs_buf_incore(mp->m_ddev_targp,
			XFS_FSB_TO_DADDR(mp, map->br_startblock),
			XFS_FSB_TO_BB(mp, map->br_blockcount), incore_flags);
	if (bp) {
		xfs_buf_stale(bp);
		xfs_buf_relse(bp);
	}

	return 0;
}

/*
 * Remove the value associated with an attribute by deleting the
 * out-of-line buffer that it is stored on.
@@ -560,7 +612,6 @@ int
xfs_attr_rmtval_remove(
	struct xfs_da_args	*args)
{
	struct xfs_mount	*mp = args->dp->i_mount;
	xfs_dablk_t		lblkno;
	int			blkcnt;
	int			error;
@@ -575,9 +626,6 @@ xfs_attr_rmtval_remove(
	blkcnt = args->rmtblkcnt;
	while (blkcnt > 0) {
		struct xfs_bmbt_irec	map;
		struct xfs_buf		*bp;
		xfs_daddr_t		dblkno;
		int			dblkcnt;
		int			nmap;

		/*
@@ -588,22 +636,11 @@ xfs_attr_rmtval_remove(
				       blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
		if (error)
			return error;
		ASSERT(nmap == 1);
		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
		       (map.br_startblock != HOLESTARTBLOCK));

		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
		dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);

		/*
		 * If the "remote" value is in the cache, remove it.
		 */
		bp = xfs_buf_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
		if (bp) {
			xfs_buf_stale(bp);
			xfs_buf_relse(bp);
			bp = NULL;
		}
		if (XFS_IS_CORRUPT(args->dp->i_mount, nmap != 1))
			return -EFSCORRUPTED;
		error = xfs_attr_rmtval_stale(args->dp, &map, XBF_TRYLOCK);
		if (error)
			return error;

		lblkno += map.br_blockcount;
		blkcnt -= map.br_blockcount;
Loading