/* getxattr */ int index, infix_len; struct qstr name;
/* listxattr */ struct dentry *dentry;
};
staticint erofs_init_inode_xattrs(struct inode *inode)
{ struct erofs_inode *const vi = EROFS_I(inode); struct erofs_xattr_iter it; unsignedint i; struct erofs_xattr_ibody_header *ih; struct super_block *sb = inode->i_sb; int ret = 0;
/* the most case is that xattrs of this inode are initialized. */ if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) { /* *pairedwithsmp_mb()attheendofthefunctiontoensure *fieldswillonlybeobservedafterthebitisset.
*/
smp_mb(); return0;
}
if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_XATTR_BIT, TASK_KILLABLE)) return -ERESTARTSYS;
/* someone has initialized xattrs for us? */ if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) goto out_unlock;
/* *bypassallxattroperationsif->xattr_isizeisnotgreaterthan *sizeof(structerofs_xattr_ibody_header),indetail: *1)itisnotenoughtocontainerofs_xattr_ibody_headerthen *->xattr_isizeshouldbe0(itmeansnoxattr); *2)itisjusttocontainerofs_xattr_ibody_header,whichison-disk *undefinedrightnow(maybeuselaterwithsomenewsbfeature).
*/ if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) {
erofs_err(sb, "xattr_isize %d of nid %llu is not supported yet",
vi->xattr_isize, vi->nid);
ret = -EOPNOTSUPP; goto out_unlock;
} elseif (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { if (vi->xattr_isize) {
erofs_err(sb, "bogus xattr ibody @ nid %llu", vi->nid);
DBG_BUGON(1);
ret = -EFSCORRUPTED; goto out_unlock; /* xattr ondisk layout error */
}
ret = -ENODATA; goto out_unlock;
}
it.buf = __EROFS_BUF_INITIALIZER;
ret = erofs_init_metabuf(&it.buf, sb, erofs_inode_in_metabox(inode)); if (ret) goto out_unlock;
it.pos = erofs_iloc(inode) + vi->inode_isize;
/* read in shared xattr array (non-atomic, see kmalloc below) */
it.kaddr = erofs_bread(&it.buf, it.pos, true); if (IS_ERR(it.kaddr)) {
ret = PTR_ERR(it.kaddr); goto out_unlock;
}
ih = it.kaddr;
vi->xattr_name_filter = le32_to_cpu(ih->h_name_filter);
vi->xattr_shared_count = ih->h_shared_count;
vi->xattr_shared_xattrs = kmalloc_array(vi->xattr_shared_count, sizeof(uint), GFP_KERNEL); if (!vi->xattr_shared_xattrs) {
erofs_put_metabuf(&it.buf);
ret = -ENOMEM; goto out_unlock;
}
/* should also match the infix for long name prefixes */ if (entry.e_name_index & EROFS_XATTR_LONG_PREFIX) { struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_xattr_prefix_item *pf = sbi->xattr_prefixes +
(entry.e_name_index & EROFS_XATTR_LONG_PREFIX_MASK);
if (pf >= sbi->xattr_prefixes + sbi->xattr_prefix_count) return -ENODATA;
if (getxattr)
ret = erofs_getxattr_foreach(it); else
ret = erofs_listxattr_foreach(it); if ((getxattr && ret != -ENODATA) || (!getxattr && ret)) break;
ret = erofs_init_metabuf(&it->buf, sb,
erofs_sb_has_shared_ea_in_metabox(sbi)); if (ret) return ret;
while (i < vi->xattr_shared_count) {
it->pos = erofs_pos(sb, sbi->xattr_blkaddr) +
vi->xattr_shared_xattrs[i++] * sizeof(__le32);
it->kaddr = erofs_bread(&it->buf, it->pos, true); if (IS_ERR(it->kaddr)) return PTR_ERR(it->kaddr);
if (getxattr)
ret = erofs_getxattr_foreach(it); else
ret = erofs_listxattr_foreach(it); if ((getxattr && ret != -ENODATA) || (!getxattr && ret)) break;
} return i ? ret : -ENODATA;
}
int erofs_getxattr(struct inode *inode, int index, constchar *name, void *buffer, size_t buffer_size)
{ int ret; unsignedint hashbit; struct erofs_xattr_iter it; struct erofs_inode *vi = EROFS_I(inode); struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
if (!name) return -EINVAL;
ret = erofs_init_inode_xattrs(inode); if (ret) return ret;
/* reserved flag is non-zero if there's any change of on-disk format */ if (erofs_sb_has_xattr_filter(sbi) && !sbi->xattr_filter_reserved) {
hashbit = xxh32(name, strlen(name),
EROFS_XATTR_FILTER_SEED + index);
hashbit &= EROFS_XATTR_FILTER_BITS - 1; if (vi->xattr_name_filter & (1U << hashbit)) return -ENODATA;
}
ret = erofs_xattr_iter_inline(&it, inode, true); if (ret == -ENODATA)
ret = erofs_xattr_iter_shared(&it, inode, true);
erofs_put_metabuf(&it.buf); return ret ? ret : it.buffer_ofs;
}
ret = erofs_xattr_iter_inline(&it, inode, false); if (!ret || ret == -ENODATA)
ret = erofs_xattr_iter_shared(&it, inode, false); if (ret == -ENODATA)
ret = 0;
erofs_put_metabuf(&it.buf); return ret ? ret : it.buffer_ofs;
}
if (sbi->xattr_prefixes) { for (i = 0; i < sbi->xattr_prefix_count; i++)
kfree(sbi->xattr_prefixes[i].prefix);
kfree(sbi->xattr_prefixes);
sbi->xattr_prefixes = NULL;
}
}
int erofs_xattr_prefixes_init(struct super_block *sb)
{ struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2; struct erofs_xattr_prefix_item *pfs; int ret = 0, i, len; bool plain = erofs_sb_has_plain_xattr_pfx(sbi);
if (!sbi->xattr_prefix_count) return0;
pfs = kcalloc(sbi->xattr_prefix_count, sizeof(*pfs), GFP_KERNEL); if (!pfs) return -ENOMEM;
if (!plain) { if (erofs_sb_has_metabox(sbi))
(void)erofs_init_metabuf(&buf, sb, true); elseif (sbi->packed_inode)
buf.mapping = sbi->packed_inode->i_mapping; else
plain = true;
} if (plain)
(void)erofs_init_metabuf(&buf, sb, false);
for (i = 0; i < sbi->xattr_prefix_count; i++) { void *ptr = erofs_read_metadata(sb, &buf, &pos, &len);
if (IS_ERR(ptr)) {
ret = PTR_ERR(ptr); break;
} elseif (len < sizeof(*pfs->prefix) ||
len > EROFS_NAME_LEN + sizeof(*pfs->prefix)) {
kfree(ptr);
ret = -EFSCORRUPTED; break;
}
pfs[i].prefix = ptr;
pfs[i].infix_len = len - sizeof(struct erofs_xattr_long_prefix);
}
erofs_put_metabuf(&buf);
sbi->xattr_prefixes = pfs; if (ret)
erofs_xattr_prefixes_cleanup(sb); return ret;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.10Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.