bits &= LS3_OBJECT_ATTR_ALL;
- if ((loa->loa_attr_bits & bits) == bits)
+ if ((loa->loa_valid & bits) == bits)
return loa;
ls3_read_attrs(ls3_current()->lc_instance, ls3_current()->lc_object,
bits &= LS3_OBJECT_ATTR_ALL;
- if ((loa->loa_attr_bits & bits) == bits)
+ if ((loa->loa_valid & bits) == bits)
return loa;
errno = 0;
ls3_throw_read_attr_error(bits, rc);
assert(rc == 0);
- assert((loa->loa_attr_bits & bits) == bits);
+ assert((loa->loa_valid & bits) == bits);
return loa;
}
{
struct ls3_object_attrs *loa = ls3_attrs(0);
- return scm_from_ulong(loa->loa_attr_bits);
+ return scm_from_ulong(loa->loa_valid);
}
#define LS3_DEF_ATTR_U(name, member) \
}
LS3_DEF_ATTR_U("atime", atime);
-LS3_DEF_ATTR_U("blocks", blocks); /* 512B blocks */
LS3_DEF_ATTR_U("ctime", ctime);
LS3_DEF_ATTR_U("crtime", crtime);
LS3_DEF_ATTR_U("flags", flags);
LS3_DEF_ATTR_U("mtime", mtime);
LS3_DEF_ATTR_U("nlink", nlink);
LS3_DEF_ATTR_U("projid", projid);
-LS3_DEF_ATTR_U("size", size);
LS3_DEF_ATTR_U("uid", uid);
+SCM_DEFINE(ls3_scm_attr_size, "size", 0, 0, 0, (),
+ "return size of current file")
+{
+ struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SIZE);
+ /* TODO Add an optional argument to control strictness,
+ * laziness, truthiness... */
+
+ return scm_from_uintmax(loa->loa_size);
+}
+
+SCM_DEFINE(ls3_scm_attr_blocks, "blocks", 0, 0, 0, (),
+ "return block count of current file")
+{
+ struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SIZE);
+ /* We use _SIZE for blocks too. */
+
+ return scm_from_uintmax(loa->loa_blocks); /* 512B blocks. */
+}
+
SCM_DEFINE(ls3_scm_file_fid_ref, "file-fid", 0, 0, 0, (), "return FID of current file")
{
struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_FILE_FID);
int rc;
/* TODO Distinguish between missing xattr and other error. */
- if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ if (loa->loa_layout == NULL)
return scm_from_int(0);
/* XXX llapi_layout_*() functions return -1 on error and set errno. */
- assert(loa->loa_layout != NULL);
-
rc = llapi_layout_mirror_count_get(loa->loa_layout, &count);
if (rc < 0)
ls3_throw_read_attr_error(LS3_OBJECT_ATTR_LOV,
int rc;
/* TODO Distinguish between missing xattr and other error. */
- if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ if (loa->loa_layout == NULL)
return scm_from_int(0);
/* XXX llapi_layout_*() functions return -1 on error and set errno. */
- assert(loa->loa_layout != NULL);
-
rc = llapi_layout_get_last_init_comp(loa->loa_layout);
if (rc < 0)
goto out;
int rc;
/* TODO Distinguish between missing xattr and other error. */
- if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ if (loa->loa_layout == NULL)
return SCM_EOL;
- /* XXX llapi_layout_*() functions return -1 on error and set errno. */
- assert(loa->loa_layout != NULL);
ll = loa->loa_layout;
+ /* XXX llapi_layout_*() functions return -1 on error and set errno. */
rc = llapi_layout_comp_use(ll, LLAPI_LAYOUT_COMP_USE_LAST);
if (rc < 0)
goto out;
int rc;
/* TODO Distinguish between missing xattr and other error. */
- if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ if (loa->loa_layout == NULL)
return SCM_EOL;
- /* XXX llapi_layout_*() functions return -1 on error and set errno. */
- assert(loa->loa_layout != NULL);
ll = loa->loa_layout;
+ /* XXX llapi_layout_*() functions return -1 on error and set errno. */
rc = llapi_layout_comp_use(ll, LLAPI_LAYOUT_COMP_USE_LAST);
if (rc < 0)
goto out;
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SELF_FID)
- return 0;
-
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMA, buf, sizeof(buf), &size);
if (rc < 0)
return rc;
loa->loa_lma.lma_compat = ext2fs_le32_to_cpu(lma->lma_compat);
loa->loa_lma.lma_incompat = ext2fs_le32_to_cpu(lma->lma_incompat);
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_SELF_FID;
-
return 0;
}
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_FILTER_FID)
- return 0;
-
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_FID, ff, sizeof(*ff), &size);
if (rc < 0)
return rc;
ff->ff_parent = pfid;
loa->loa_filter_fid_size = size;
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_FILTER_FID;
-
return 0;
}
{
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_FILE_FID)
- return 0;
-
if (li->li_device_is_mdt) {
- rc = ldiskfs_read_attr_self_fid(li, lo, loa);
+ rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SELF_FID, 1);
if (rc < 0)
return rc;
loa->loa_file_fid = *loa_self_fid(loa);
} else if (li->li_device_is_ost) {
- rc = ldiskfs_read_attr_filter_fid(li, lo, loa);
+ rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_FILTER_FID, 1);
if (rc < 0)
return rc;
return -EINVAL;
}
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_FILE_FID;
-
return 0;
}
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LINKS)
- return 0;
-
assert(lipe_list_empty(&loa->loa_links));
/* We use the link xattr plus caching to speed up paths but we
* properly after unlink. This is why we test
* LMAI_ORPHAN. */
- rc = ldiskfs_read_attr_self_fid(li, lo, loa);
+ rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SELF_FID, 1);
if (rc < 0)
return rc;
return rc;
}
out_ok:
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_LINKS;
-
return 0;
}
struct lipe_link_entry *lle;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_PATHS)
- return 0;
-
assert(lipe_list_empty(&loa->loa_paths));
if (li->li_device_is_ost) {
- rc = ldiskfs_read_attr_file_fid(li, lo, loa);
+ rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_FILE_FID, 1);
if (rc < 0)
return rc;
/* Requiring a link xattr before fid2path prevents MDT crashes
* when we pass fids of OI_scrub or other internal files. */
- rc = ldiskfs_read_attr_links(li, lo, loa);
+ rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_LINKS, 1);
if (rc < 0)
return rc;
return rc;
}
out_ok:
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_PATHS;
-
return 0;
}
struct ext2_xattr_handle *handle = NULL;
errcode_t rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_XATTRS)
- return 0;
-
rc = ext2fs_xattrs_open(fs, ino, &handle);
if (rc) {
LS3_ERROR_OBJ(lo, "cannot open xattrs: rc = %ld\n", rc);
goto out_close;
}
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_XATTRS;
out_close:
ext2fs_xattrs_close(&handle);
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV)
- return 0;
-
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LOV, lum, loa->loa_lum_size, &size);
if (rc < 0)
goto out;
rc = -errno;
goto out;
}
-
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_LOV;
out:
return rc;
}
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LMV)
- return 0;
-
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMV,
loa->loa_lmv_buf, loa->loa_lmv_buf_size, &size);
if (rc < 0)
/* TODO Store and check size. */
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_LMV;
-
return 0;
}
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_HSM)
- return 0;
-
assert(sizeof(*hsm) < XATTR_SIZE_MAX);
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_HSM, buf, sizeof(buf), &size);
hus->hus_states = ext2fs_le32_to_cpu(hsm->hsm_flags);
hus->hus_archive_id = ext2fs_le64_to_cpu(hsm->hsm_arch_id);
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_HSM;
-
return 0;
}
int size;
int rc;
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SOM)
- return 0;
-
rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_SOM, som, sizeof(*som), &size);
if (rc < 0)
return rc;
switch (loa->loa_som.lsa_valid) {
case SOM_FL_STRICT:
- loa->loa_size = som->lsa_size;
- loa->loa_blocks = som->lsa_blocks;
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_SIZE;
- /* fallthrough */
case SOM_FL_STALE:
case SOM_FL_LAZY:
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_SOM;
rc = 0;
break;
default:
struct lipe_object *lo,
struct ls3_object_attrs *loa)
{
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SIZE)
- return 0;
+ /* This function is responsible for reading size and blocks
+ * attrs. If the current file is an OST object or not a
+ * regular file then we use the size and blocks values from
+ * the inode. (But this is wrong for striped directories.) If
+ * the current file is an regular MDT inode then we check for
+ * strict or lazy SOM, followed by HSM released, followed by
+ * unstriped. */
- assert(loa->loa_attr_bits & LS3_OBJECT_ATTR_BASE);
+ assert(loa->loa_valid & LS3_OBJECT_ATTR_BASE);
- if (!S_ISREG(loa->loa_mode)) {
+ if (li->li_device_is_ost || !S_ISREG(loa->loa_mode)) {
/* FIXME This is wrong for striped directories. */
- loa->loa_attr_bits |= LS3_OBJECT_ATTR_SIZE;
+use_i_size:
+ loa->loa_size = loa->loa_i_size;
+ loa->loa_blocks = loa->loa_i_blocks;
return 0;
}
- ldiskfs_read_attr_som(li, lo, loa);
+ ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SOM, 1);
- if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SIZE)
+ if (loa->loa_valid & LS3_OBJECT_ATTR_SOM &&
+ loa->loa_som.lsa_valid & (SOM_FL_STRICT | SOM_FL_LAZY)) {
+ loa->loa_size = loa->loa_som.lsa_size;
+ loa->loa_blocks = loa->loa_som.lsa_blocks;
return 0;
+ }
+
+ ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_HSM, 1);
+
+ if (loa->loa_valid & LS3_OBJECT_ATTR_HSM &&
+ loa->loa_hsm_state.hus_states & HS_RELEASED)
+ goto use_i_size;
+
+ ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_LOV, 1);
+
+ if (loa->loa_nodata & LS3_OBJECT_ATTR_LOV)
+ goto use_i_size; /* Striping is not set. */
/* Try stat? */
return -ENODATA;
}
-static bool ls3_need_read_attr(const struct ls3_object_attrs *loa,
- enum ls3_object_attr_bit need_bits,
- enum ls3_object_attr_bit bit)
-{
- return ~loa->loa_attr_bits & need_bits & bit;
-}
-
static const struct {
- unsigned int r_bit;
+ unsigned int r_flag;
int (*r_read)(struct ls3_instance *,
struct lipe_object *,
struct ls3_object_attrs *);
int ls3_read_attrs(struct ls3_instance *li,
struct lipe_object *lo,
struct ls3_object_attrs *loa,
- enum ls3_object_attr_bit need_bits,
+ enum ls3_object_attr_bit need,
bool quit_on_error)
{
int rc = 0;
size_t i;
for (i = 0; i < ARRAY_SIZE(ls3_ldiskfs_attr_readers); i++) {
- if (ls3_need_read_attr(loa, need_bits, ls3_ldiskfs_attr_readers[i].r_bit)) {
- int rc2 = (*ls3_ldiskfs_attr_readers[i].r_read)(li, lo, loa);
- if (rc2 != 0) {
- if (quit_on_error)
- return rc2;
-
- if (rc == 0)
- rc = rc2;
- }
+ unsigned int flag = ls3_ldiskfs_attr_readers[i].r_flag;
+ int rc2;
+
+ if (!(need & flag))
+ continue;
+
+ if (loa->loa_valid & flag)
+ continue;
+
+ if (loa->loa_nodata & flag) {
+ rc2 = -ENODATA;
+ goto skip_read;
+ }
+
+ if (loa->loa_error & flag) {
+ rc2 = -EIO;
+ goto skip_read;
+ }
+
+ rc2 = (*ls3_ldiskfs_attr_readers[i].r_read)(li, lo, loa);
+ switch (rc2) {
+ case 0:
+ loa->loa_valid |= flag;
+ break;
+ case -ENODATA:
+ loa->loa_nodata |= flag;
+ break;
+ default:
+ loa->loa_error |= flag;
+ break;
+ }
+skip_read:
+ if (rc2 != 0) {
+ if (quit_on_error)
+ return rc2;
+
+ if (rc == 0)
+ rc = rc2;
}
}
- assert((need_bits & loa->loa_attr_bits) == need_bits || rc < 0);
+ assert((need & loa->loa_valid) == need || rc < 0);
return rc;
}
loa->loa_mtime = inode_time(inode->i_mtime, inode->i_mtime_extra);
loa->loa_ctime = inode_time(inode->i_ctime, inode->i_ctime_extra);
loa->loa_crtime = inode_time(inode->i_crtime, inode->i_crtime_extra);
- loa->loa_size = EXT2_I_SIZE(inode);
+ loa->loa_i_size = EXT2_I_SIZE(inode);
loa->loa_mode = inode->i_mode; /* __u16 */
loa->loa_uid = inode_uid(*inode);
loa->loa_gid = inode_gid(*inode);
loa->loa_flags = inode->i_flags; /* __u32 */
loa->loa_nlink = inode->i_links_count; /* __u16 */
- loa->loa_blocks = blocks_from_inode(fs, inode);
+ loa->loa_i_blocks = blocks_from_inode(fs, inode);
loa->loa_projid = inode_projid(*inode);
- loa->loa_attr_bits = LS3_OBJECT_ATTR_BASE | LS3_OBJECT_ATTR_PROJID;
+ loa->loa_valid = LS3_OBJECT_ATTR_BASE | LS3_OBJECT_ATTR_PROJID;
}
static int ldiskfs_scan_groups(ext2_inode_scan scan,
rc2 = ls3_read_attrs(li, lo, loa, li->li_required_attrs,
true /* quit on error. */);
if (rc2 != 0) {
- LS3_DEBUG_OBJ(lo, "missing required attrs %#"PRIxMAX"\n",
- (uintmax_t)(li->li_required_attrs & ~loa->loa_attr_bits));
+ LS3_DEBUG_OBJ(lo, "missing required attrs %#"PRIxMAX", have "
+ "valid %#"PRIxMAX", "
+ "nodata %#"PRIxMAX", "
+ "error %#"PRIxMAX"\n",
+ (uintmax_t)(li->li_required_attrs & ~loa->loa_valid),
+ (uintmax_t)(loa->loa_valid),
+ (uintmax_t)(loa->loa_nodata),
+ (uintmax_t)(loa->loa_error));
continue;
}
- assert((loa->loa_attr_bits & li->li_required_attrs) ==
+ assert((loa->loa_valid & li->li_required_attrs) ==
li->li_required_attrs);
/* Requiring fid_is_norm() prevents us from returning