/** * tb_property_parse_dir() - Parses properties from given property block * @block: Property block to parse * @block_len: Number of dword elements in the property block * * This function parses the XDomain properties data block into format that * can be traversed using the helper functions provided by this module. * Upon success returns the parsed directory. In case of error returns * %NULL. The resulting &struct tb_property_dir needs to be released by * calling tb_property_free_dir() when not needed anymore. * * The @block is expected to be root directory.
*/ struct tb_property_dir *tb_property_parse_dir(const u32 *block,
size_t block_len)
{ conststruct tb_property_rootdir_entry *rootdir =
(conststruct tb_property_rootdir_entry *)block;
if (rootdir->magic != TB_PROPERTY_ROOTDIR_MAGIC) return NULL; if (rootdir->length > block_len) return NULL;
/** * tb_property_create_dir() - Creates new property directory * @uuid: UUID used to identify the particular directory * * Creates new, empty property directory. If @uuid is %NULL then the * directory is assumed to be root directory.
*/ struct tb_property_dir *tb_property_create_dir(const uuid_t *uuid)
{ struct tb_property_dir *dir;
dir = kzalloc(sizeof(*dir), GFP_KERNEL); if (!dir) return NULL;
INIT_LIST_HEAD(&dir->properties); if (uuid) {
dir->uuid = kmemdup(uuid, sizeof(*dir->uuid), GFP_KERNEL); if (!dir->uuid) {
kfree(dir); return NULL;
}
}
case TB_PROPERTY_TYPE_DATA:
kfree(property->value.data); break;
case TB_PROPERTY_TYPE_TEXT:
kfree(property->value.text); break;
default: break;
}
kfree(property);
}
/** * tb_property_free_dir() - Release memory allocated for property directory * @dir: Directory to release * * This will release all the memory the directory occupies including all * descendants. It is OK to pass %NULL @dir, then the function does * nothing.
*/ void tb_property_free_dir(struct tb_property_dir *dir)
{ struct tb_property *property, *tmp;
if (dir->uuid)
len += sizeof(*dir->uuid) / 4; else
len += sizeof(struct tb_property_rootdir_entry) / 4;
list_for_each_entry(property, &dir->properties, list) {
len += sizeof(struct tb_property_entry) / 4;
switch (property->type) { case TB_PROPERTY_TYPE_DIRECTORY: if (recurse) {
len += tb_property_dir_length(
property->value.dir, recurse, data_len);
} /* Reserve dword padding after each directory */ if (data_len)
*data_len += 1; break;
case TB_PROPERTY_TYPE_DATA: case TB_PROPERTY_TYPE_TEXT: if (data_len)
*data_len += property->length; break;
case TB_PROPERTY_TYPE_VALUE:
entry->length = property->length;
entry->value = property->value.immediate; break;
default: break;
}
entry++;
}
return dir_end;
}
/** * tb_property_format_dir() - Formats directory to the packed XDomain format * @dir: Directory to format * @block: Property block where the packed data is placed * @block_len: Length of the property block * * This function formats the directory to the packed format that can be * then send over the thunderbolt fabric to receiving host. Returns %0 in * case of success and negative errno on faulure. Passing %NULL in @block * returns number of entries the block takes.
*/
ssize_t tb_property_format_dir(conststruct tb_property_dir *dir, u32 *block,
size_t block_len)
{
ssize_t ret;
ret = __tb_property_format_dir(dir, block, 0, block_len); return ret < 0 ? ret : 0;
}
/** * tb_property_copy_dir() - Take a deep copy of directory * @dir: Directory to copy * * This function takes a deep copy of @dir and returns back the copy. In * case of error returns %NULL. The resulting directory needs to be * released by calling tb_property_free_dir().
*/ struct tb_property_dir *tb_property_copy_dir(conststruct tb_property_dir *dir)
{ struct tb_property *property, *p = NULL; struct tb_property_dir *d;
if (!dir) return NULL;
d = tb_property_create_dir(dir->uuid); if (!d) return NULL;
p = tb_property_alloc(property->key, property->type); if (!p) goto err_free;
p->length = property->length;
switch (property->type) { case TB_PROPERTY_TYPE_DIRECTORY:
p->value.dir = tb_property_copy_dir(property->value.dir); if (!p->value.dir) goto err_free; break;
case TB_PROPERTY_TYPE_DATA:
p->value.data = kmemdup(property->value.data,
property->length * 4,
GFP_KERNEL); if (!p->value.data) goto err_free; break;
case TB_PROPERTY_TYPE_TEXT:
p->value.text = kzalloc(p->length * 4, GFP_KERNEL); if (!p->value.text) goto err_free;
strcpy(p->value.text, property->value.text); break;
case TB_PROPERTY_TYPE_VALUE:
p->value.immediate = property->value.immediate; break;
default: break;
}
list_add_tail(&p->list, &d->properties);
}
return d;
err_free:
kfree(p);
tb_property_free_dir(d);
return NULL;
}
/** * tb_property_add_immediate() - Add immediate property to directory * @parent: Directory to add the property * @key: Key for the property * @value: Immediate value to store with the property
*/ int tb_property_add_immediate(struct tb_property_dir *parent, constchar *key,
u32 value)
{ struct tb_property *property;
if (!tb_property_key_valid(key)) return -EINVAL;
property = tb_property_alloc(key, TB_PROPERTY_TYPE_VALUE); if (!property) return -ENOMEM;
/** * tb_property_add_data() - Adds arbitrary data property to directory * @parent: Directory to add the property * @key: Key for the property * @buf: Data buffer to add * @buflen: Number of bytes in the data buffer * * Function takes a copy of @buf and adds it to the directory.
*/ int tb_property_add_data(struct tb_property_dir *parent, constchar *key, constvoid *buf, size_t buflen)
{ /* Need to pad to dword boundary */
size_t size = round_up(buflen, 4); struct tb_property *property;
if (!tb_property_key_valid(key)) return -EINVAL;
property = tb_property_alloc(key, TB_PROPERTY_TYPE_DATA); if (!property) return -ENOMEM;
/** * tb_property_add_text() - Adds string property to directory * @parent: Directory to add the property * @key: Key for the property * @text: String to add * * Function takes a copy of @text and adds it to the directory.
*/ int tb_property_add_text(struct tb_property_dir *parent, constchar *key, constchar *text)
{ /* Need to pad to dword boundary */
size_t size = round_up(strlen(text) + 1, 4); struct tb_property *property;
if (!tb_property_key_valid(key)) return -EINVAL;
property = tb_property_alloc(key, TB_PROPERTY_TYPE_TEXT); if (!property) return -ENOMEM;
/** * tb_property_add_dir() - Adds a directory to the parent directory * @parent: Directory to add the property * @key: Key for the property * @dir: Directory to add
*/ int tb_property_add_dir(struct tb_property_dir *parent, constchar *key, struct tb_property_dir *dir)
{ struct tb_property *property;
if (!tb_property_key_valid(key)) return -EINVAL;
property = tb_property_alloc(key, TB_PROPERTY_TYPE_DIRECTORY); if (!property) return -ENOMEM;
/** * tb_property_remove() - Removes property from a parent directory * @property: Property to remove * * Note memory for @property is released as well so it is not allowed to * touch the object after call to this function.
*/ void tb_property_remove(struct tb_property *property)
{
list_del(&property->list);
kfree(property);
}
EXPORT_SYMBOL_GPL(tb_property_remove);
/** * tb_property_find() - Find a property from a directory * @dir: Directory where the property is searched * @key: Key to look for * @type: Type of the property * * Finds and returns property from the given directory. Does not recurse * into sub-directories. Returns %NULL if the property was not found.
*/ struct tb_property *tb_property_find(struct tb_property_dir *dir, constchar *key, enum tb_property_type type)
{ struct tb_property *property;
list_for_each_entry(property, &dir->properties, list) { if (property->type == type && !strcmp(property->key, key)) return property;
}
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.