static const cmdinfo_t attr_set_cmd =
{ "attr_set", "aset", attr_set_f, 1, -1, 0,
- "[-r|-s|-p|-u] [-R|-C] [-v n] name",
+ "[-r|-s|-p|-u] [-n] [-R|-C] [-v n] name",
"set the named attribute on the current inode", attrset_help };
static const cmdinfo_t attr_remove_cmd =
{ "attr_remove", "aremove", attr_remove_f, 1, -1, 0,
- "[-r|-s|-p|-u] name",
+ "[-r|-s|-p|-u] [-n] name",
"remove the named attribute from the current inode", attrset_help };
static void
" -u -- 'user' (default)\n"
" -s -- 'secure'\n"
"\n"
-" For attr_set, these options further define the type of set:\n"
+" For attr_set, these options further define the type of set operation:\n"
" -C -- 'create' - create attribute, fail if it already exists\n"
" -R -- 'replace' - replace attribute, fail if it does not exist\n"
+" The backward compatibility mode 'noattr2' can be emulated (-n) also.\n"
"\n");
}
return 0;
}
- while ((c = getopt(argc, argv, "rusCRv:")) != EOF) {
+ while ((c = getopt(argc, argv, "rusCRnv:")) != EOF) {
switch (c) {
/* namespaces */
case 'r':
flags |= LIBXFS_ATTR_REPLACE;
break;
+ case 'n':
+ mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR;
+ break;
+
/* value length */
case 'v':
valuelen = (int)strtol(optarg, &sp, 0);
set_cur_inode(iocur_top->ino);
out:
+ mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR;
if (ip)
libxfs_iput(ip, 0);
if (value)
return 0;
}
- while ((c = getopt(argc, argv, "rus")) != EOF) {
+ while ((c = getopt(argc, argv, "rusn")) != EOF) {
switch (c) {
/* namespaces */
case 'r':
flags &= ~LIBXFS_ATTR_ROOT;
break;
+ case 'n':
+ mp->m_flags |= LIBXFS_MOUNT_COMPAT_ATTR;
+ break;
+
default:
dbprintf("bad option for attr_remove command\n");
return 0;
set_cur_inode(iocur_top->ino);
out:
+ mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR;
if (ip)
libxfs_iput(ip, 0);
return 0;
} xfs_mount_t;
#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1)
-#define LIBXFS_MOUNT_ROOTINOS 0x0001
-#define LIBXFS_MOUNT_DEBUGGER 0x0002
+#define LIBXFS_MOUNT_ROOTINOS 0x0001
+#define LIBXFS_MOUNT_DEBUGGER 0x0002
+#define LIBXFS_MOUNT_32BITINODES 0x0004
+#define LIBXFS_MOUNT_32BITINOOPT 0x0008
+#define LIBXFS_MOUNT_COMPAT_ATTR 0x0010
extern xfs_mount_t *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
dev_t, dev_t, dev_t, int);
extern xfs_dahash_t libxfs_da_hashname (uchar_t *, int);
extern int libxfs_attr_leaf_newentsize (int, int, int, int *);
-extern int libxfs_attr_set_int (xfs_inode_t*, char*, int, char*, int, int);
-extern int libxfs_attr_remove_int (xfs_inode_t *, char *, int, int);
+extern int libxfs_attr_set_int (xfs_inode_t*, const char *, int, char *,
+ int, int);
+extern int libxfs_attr_remove_int (xfs_inode_t *, const char *, int, int);
extern void libxfs_bmbt_get_all (xfs_bmbt_rec_t *, xfs_bmbt_irec_t *);
* Structure to ease passing around component names.
*/
typedef struct xfs_da_args {
- uchar_t *name; /* string (maybe not NULL terminated) */
+ const uchar_t *name; /* string (maybe not NULL terminated) */
int namelen; /* length of string (maybe no NULL) */
uchar_t *value; /* set of bytes (maybe contain NULLs) */
int valuelen; /* length of value */
return 0;
}
-#define XFS_MOUNT_32BITINODES 0x1
-#define XFS_MOUNT_32BITINOOPT 0x2
/*
* Mount structure initialization, provides a filled-in xfs_mount_t
* such that the numerous XFS_* macros can be used. If dev is zero,
mp->m_dev = dev;
mp->m_rtdev = rtdev;
mp->m_logdev = logdev;
- mp->m_flags = (XFS_MOUNT_32BITINODES|XFS_MOUNT_32BITINOOPT);
+ mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT);
mp->m_sb = *sb;
sbp = &(mp->m_sb);
manage_zones(0);
#define XFS_STATS_ADD(count, x) do { } while (0)
#define XFS_MOUNT_WSYNC 0 /* ignored in userspace */
#define XFS_MOUNT_NOALIGN 0 /* ignored in userspace */
-#define XFS_MOUNT_32BITINODES 0x1 /* enforce in userspace */
-#define XFS_MOUNT_32BITINOOPT 0x2 /* enforce in userspace */
+#define XFS_MOUNT_32BITINODES LIBXFS_MOUNT_32BITINODES
+#define XFS_MOUNT_32BITINOOPT LIBXFS_MOUNT_32BITINOOPT
+#define XFS_MOUNT_COMPAT_ATTR LIBXFS_MOUNT_COMPAT_ATTR
#define XFS_ILOCK_EXCL 0
+#define xfs_sort qsort
#define down_read(a) ((void) 0)
#define up_read(a) ((void) 0)
#define mrlock(a,b,c) ((void) 0)
*========================================================================*/
int
-xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen,
+xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
char *value, int valuelen, int flags)
{
xfs_da_args_t args;
}
STATIC int
-xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags)
+xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
{
xfs_da_args_t args;
xfs_fsblock_t firstblock;
*========================================================================*/
/*
- * Query whether additional requested number of bytes of extended attribute
- * space will be able to fit inline.
+ * Query whether the requested number of additional bytes of extended
+ * attribute space will be able to fit inline.
* Returns zero if not, else the di_forkoff fork offset to be used in the
* literal area for attribute data once the new bytes have been added.
+ *
+ * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value;
+ * special case for dev/uuid inodes, they have fixed size data forks.
*/
int
xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
{
- int offset, minforkoff, maxforkoff;
+ int offset;
+ int minforkoff; /* lower limit on valid forkoff locations */
+ int maxforkoff; /* upper limit on valid forkoff locations */
+ xfs_mount_t *mp = dp->i_mount;
- offset = (XFS_LITINO(dp->i_mount) - bytes) >> 3; /* rounded down */
+ offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
switch (dp->i_d.di_format) {
case XFS_DINODE_FMT_DEV:
return (offset >= minforkoff) ? minforkoff : 0;
}
+ if (unlikely(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) {
+ if (bytes <= XFS_IFORK_ASIZE(dp))
+ return mp->m_attroffset >> 3;
+ return 0;
+ }
+
/* data fork btree root can have at least this many key/ptr pairs */
minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
minforkoff = roundup(minforkoff, 8) >> 3;
/* attr fork btree root can have at least this many key/ptr pairs */
- maxforkoff = XFS_LITINO(dp->i_mount) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
maxforkoff = maxforkoff >> 3; /* rounded down */
if (offset >= minforkoff && offset < maxforkoff)
return 0;
}
+/*
+ * Switch on the ATTR2 superblock bit (implies also FEATURES2)
+ */
+STATIC void
+xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
+{
+ unsigned long s;
+
+ if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR) &&
+ !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
+ s = XFS_SB_LOCK(mp);
+ if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
+ XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
+ XFS_SB_UNLOCK(mp, s);
+ xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
+ } else
+ XFS_SB_UNLOCK(mp, s);
+ }
+}
+
/*
* Create the initial contents of a shortform attribute list.
*/
xfs_attr_shortform_t *sf;
xfs_attr_sf_entry_t *sfe;
int i, offset, size;
- unsigned long s;
xfs_mount_t *mp;
xfs_inode_t *dp;
xfs_ifork_t *ifp;
INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
- if (unlikely(!XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
- s = XFS_SB_LOCK(mp);
- if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
- XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
- XFS_SB_UNLOCK(mp, s);
- xfs_mod_sb(args->trans,
- XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
- } else
- XFS_SB_UNLOCK(mp, s);
- }
+ xfs_sbversion_add_attr2(mp, args->trans);
}
/*
xfs_attr_shortform_t *sf;
xfs_attr_sf_entry_t *sfe;
int base, size=0, end, totsize, i;
- unsigned long s;
xfs_mount_t *mp;
xfs_inode_t *dp;
XFS_ILOG_CORE | XFS_ILOG_ADATA);
}
- if (unlikely(!XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
- s = XFS_SB_LOCK(mp);
- if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
- XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
- XFS_SB_UNLOCK(mp, s);
- xfs_mod_sb(args->trans,
- XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
- } else
- XFS_SB_UNLOCK(mp, s);
- }
+ xfs_sbversion_add_attr2(mp, args->trans);
return(0);
}
case XFS_DINODE_FMT_EXTENTS:
case XFS_DINODE_FMT_BTREE:
ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
- if (ip->i_d.di_forkoff)
- version = 2;
- else
+ if (!ip->i_d.di_forkoff)
ip->i_d.di_forkoff = mp->m_attroffset >> 3;
+ else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR))
+ version = 2;
break;
default:
ASSERT(0);
*/
if (whichfork == XFS_DATA_FORK) {
maxleafents = MAXEXTNUM;
- sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+ sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
+ mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS);
} else {
maxleafents = MAXAEXTNUM;
- sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
+ mp->m_sb.sb_inodesize - mp->m_attroffset :
+ XFS_BMDR_SPACE_CALC(MINABTPTRS);
}
maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
minleafrecs = mp->m_bmap_dmnr[0];
uint shortcount, leafcount, count;
mp->m_dirversion = 1;
- shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
- (uint)sizeof(xfs_dir_sf_hdr_t)) /
- (uint)sizeof(xfs_dir_sf_entry_t);
- leafcount = (XFS_LBSIZE(mp) - (uint)sizeof(xfs_dir_leaf_hdr_t)) /
- ((uint)sizeof(xfs_dir_leaf_entry_t) +
- (uint)sizeof(xfs_dir_leaf_name_t));
+ if (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) {
+ shortcount = (mp->m_attroffset -
+ (uint)sizeof(xfs_dir_sf_hdr_t)) /
+ (uint)sizeof(xfs_dir_sf_entry_t);
+ leafcount = (XFS_LBSIZE(mp) -
+ (uint)sizeof(xfs_dir_leaf_hdr_t)) /
+ ((uint)sizeof(xfs_dir_leaf_entry_t) +
+ (uint)sizeof(xfs_dir_leaf_name_t));
+ } else {
+ shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
+ (uint)sizeof(xfs_dir_sf_hdr_t)) /
+ (uint)sizeof(xfs_dir_sf_entry_t);
+ leafcount = (XFS_LBSIZE(mp) -
+ (uint)sizeof(xfs_dir_leaf_hdr_t)) /
+ ((uint)sizeof(xfs_dir_leaf_entry_t) +
+ (uint)sizeof(xfs_dir_leaf_name_t));
+ }
count = shortcount > leafcount ? shortcount : leafcount;
mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
/*
* Sort the leaf entries by hash value.
*/
- qsort(blp, INT_GET(btp->count, ARCH_CONVERT), sizeof(*blp), xfs_dir2_block_sort);
+ xfs_sort(blp, INT_GET(btp->count, ARCH_CONVERT), sizeof(*blp), xfs_dir2_block_sort);
/*
* Log the leaf entry area and tail.
* Already logged the header in data_init, ignore needlog.
int isdotdot; /* entry is ".." */
xfs_mount_t *mp; /* mount structure pointer */
int namelen; /* total name bytes */
- int inode_size; /* inode number bytes */
xfs_ino_t parent; /* parent inode number */
int size=0; /* total computed size */
/*
* Calculate the new size, see if we should give up yet.
*/
- inode_size = i8count ? sizeof(xfs_dir2_ino8_t) :
- sizeof(xfs_dir2_ino4_t);
- size = XFS_DIR2_SF_HDR_SIZE(i8count) + namelen +
- count * (sizeof(xfs_dir2_sf_off_t) + 1 + inode_size);
+ size = XFS_DIR2_SF_HDR_SIZE(i8count) + /* header */
+ count + /* namelen */
+ count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
+ namelen + /* name */
+ (i8count ? /* inumber */
+ (uint)sizeof(xfs_dir2_ino8_t) * count :
+ (uint)sizeof(xfs_dir2_ino4_t) * count);
if (size > XFS_IFORK_DSIZE(dp))
return size; /* size value is a failure */
}
old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
old_len = item->ri_buf[item->ri_cnt-1].i_len;
- ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0);
+ ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
memcpy(&ptr[old_len], dp, len); /* d, s, l */
item->ri_buf[item->ri_cnt-1].i_len += len;
item->ri_buf[item->ri_cnt-1].i_addr = ptr;