Skip to content

Commit

Permalink
Merge tag 'xfs-5.6-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xf…
Browse files Browse the repository at this point in the history
…s-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
  ...
  • Loading branch information
torvalds committed Jan 30, 2020
2 parents e5da4c9 + b3531f5 commit 91f1a95
Show file tree
Hide file tree
Showing 33 changed files with 300 additions and 253 deletions.
14 changes: 9 additions & 5 deletions fs/xfs/libxfs/xfs_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{

Expand All @@ -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 */

Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -1007,7 +1011,7 @@ xfs_attr_node_addname(
* 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;
Expand Down
15 changes: 10 additions & 5 deletions fs/xfs/libxfs/xfs_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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" }, \
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/libxfs/xfs_attr_leaf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
9 changes: 0 additions & 9 deletions fs/xfs/libxfs/xfs_attr_leaf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*========================================================================*/
Expand Down
89 changes: 63 additions & 26 deletions fs/xfs/libxfs/xfs_attr_remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
&xfs_attr3_rmt_buf_ops);
if (error)
bp = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt, 0,
&xfs_attr3_rmt_buf_ops);
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;

Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand All @@ -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;

/*
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/libxfs/xfs_attr_remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
int xfs_attr_rmtval_set(struct xfs_da_args *args);
int xfs_attr_rmtval_remove(struct xfs_da_args *args);
int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map,
xfs_buf_flags_t incore_flags);

#endif /* __XFS_ATTR_REMOTE_H__ */
2 changes: 0 additions & 2 deletions fs/xfs/libxfs/xfs_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2389,8 +2389,6 @@ xfs_btree_lshift(
XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1);
if (level > 0) {
/* It's a nonleaf. operate on keys and ptrs */
int i; /* loop index */

for (i = 0; i < rrecs; i++) {
error = xfs_btree_debug_check_ptr(cur, rpp, i + 1, level);
if (error)
Expand Down
4 changes: 3 additions & 1 deletion fs/xfs/libxfs/xfs_da_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,16 @@ typedef struct xfs_da_args {
#define XFS_DA_OP_OKNOENT 0x0008 /* lookup/add op, ENOENT ok, else die */
#define XFS_DA_OP_CILOOKUP 0x0010 /* lookup to return CI name if found */
#define XFS_DA_OP_ALLOCVAL 0x0020 /* lookup to alloc buffer if found */
#define XFS_DA_OP_INCOMPLETE 0x0040 /* lookup INCOMPLETE attr keys */

#define XFS_DA_OP_FLAGS \
{ XFS_DA_OP_JUSTCHECK, "JUSTCHECK" }, \
{ XFS_DA_OP_RENAME, "RENAME" }, \
{ XFS_DA_OP_ADDNAME, "ADDNAME" }, \
{ XFS_DA_OP_OKNOENT, "OKNOENT" }, \
{ XFS_DA_OP_CILOOKUP, "CILOOKUP" }, \
{ XFS_DA_OP_ALLOCVAL, "ALLOCVAL" }
{ XFS_DA_OP_ALLOCVAL, "ALLOCVAL" }, \
{ XFS_DA_OP_INCOMPLETE, "INCOMPLETE" }

/*
* Storage for holding state during Btree searches and split/join ops.
Expand Down
4 changes: 1 addition & 3 deletions fs/xfs/libxfs/xfs_da_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ typedef struct xfs_dir2_sf_entry {
* A 64-bit or 32-bit inode number follows here, at a variable offset
* after the name.
*/
} xfs_dir2_sf_entry_t;
} __packed xfs_dir2_sf_entry_t;

static inline int xfs_dir2_sf_hdr_size(int i8count)
{
Expand Down Expand Up @@ -683,8 +683,6 @@ struct xfs_attr3_leafblock {

/*
* Flags used in the leaf_entry[i].flags field.
* NOTE: the INCOMPLETE bit must not collide with the flags bits specified
* on the system call, they are "or"ed together for various operations.
*/
#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
Expand Down
7 changes: 7 additions & 0 deletions fs/xfs/libxfs/xfs_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,13 @@ typedef struct xfs_bmdr_block {
#define BMBT_BLOCKCOUNT_BITLEN 21

#define BMBT_STARTOFF_MASK ((1ULL << BMBT_STARTOFF_BITLEN) - 1)
#define BMBT_BLOCKCOUNT_MASK ((1ULL << BMBT_BLOCKCOUNT_BITLEN) - 1)

/*
* bmbt records have a file offset (block) field that is 54 bits wide, so this
* is the largest xfs_fileoff_t that we ever expect to see.
*/
#define XFS_MAX_FILEOFF (BMBT_STARTOFF_MASK + BMBT_BLOCKCOUNT_MASK)

typedef struct xfs_bmbt_rec {
__be64 l0, l1;
Expand Down
19 changes: 14 additions & 5 deletions fs/xfs/libxfs/xfs_log_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,20 @@ static inline uint xfs_log_dinode_size(int version)
#define XFS_BLF_GDQUOT_BUF (1<<4)

/*
* This is the structure used to lay out a buf log item in the
* log. The data map describes which 128 byte chunks of the buffer
* have been logged.
*/
#define XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD)
* This is the structure used to lay out a buf log item in the log. The data
* map describes which 128 byte chunks of the buffer have been logged.
*
* The placement of blf_map_size causes blf_data_map to start at an odd
* multiple of sizeof(unsigned int) offset within the struct. Because the data
* bitmap size will always be an even number, the end of the data_map (and
* therefore the structure) will also be at an odd multiple of sizeof(unsigned
* int). Some 64-bit compilers will insert padding at the end of the struct to
* ensure 64-bit alignment of blf_blkno, but 32-bit ones will not. Therefore,
* XFS_BLF_DATAMAP_SIZE must be an odd number to make the padding explicit and
* keep the structure size consistent between 32-bit and 64-bit platforms.
*/
#define __XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD)
#define XFS_BLF_DATAMAP_SIZE (__XFS_BLF_DATAMAP_SIZE + 1)

typedef struct xfs_buf_log_format {
unsigned short blf_type; /* buf log item type indicator */
Expand Down
1 change: 0 additions & 1 deletion fs/xfs/scrub/repair.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ static inline xfs_extlen_t
xrep_calc_ag_resblks(
struct xfs_scrub *sc)
{
ASSERT(!(sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR));
return 0;
}

Expand Down
Loading

0 comments on commit 91f1a95

Please sign in to comment.