xen/hypfs: add support for id-based dynamic directories

Add some helpers to hypfs.c to support dynamic directories with a
numerical id as name.

The dynamic directory is based on a template specified by the user
allowing to use specific access functions and having a predefined
set of entries in the directory.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Juergen Gross authored and Jan Beulich committed 2021-01-22 12:14:07 +01:00
1 parent 0b3b53be8c
commit 4f1e5ed49c
2 files changed
+116

No files matched your search

+98
View File
@@ -365,6 +365,104 @@ unsigned int hypfs_getsize(const struct hypfs_entry *entry)
return entry->size;
}
/*
* Fill the direntry for a dynamically generated entry. Especially the
* generated name needs to be kept in sync with hypfs_gen_dyndir_id_entry().
*/
int hypfs_read_dyndir_id_entry(const struct hypfs_entry_dir *template,
unsigned int id, bool is_last,
XEN_GUEST_HANDLE_PARAM(void) *uaddr)
{
struct xen_hypfs_dirlistentry direntry;
char name[HYPFS_DYNDIR_ID_NAMELEN];
unsigned int e_namelen, e_len;
e_namelen = snprintf(name, sizeof(name), template->e.name, id);
e_len = DIRENTRY_SIZE(e_namelen);
direntry.e.pad = 0;
direntry.e.type = template->e.type;
direntry.e.encoding = template->e.encoding;
direntry.e.content_len = template->e.funcs->getsize(&template->e);
direntry.e.max_write_len = template->e.max_size;
direntry.off_next = is_last ? 0 : e_len;
if ( copy_to_guest(*uaddr, &direntry, 1) )
return -EFAULT;
if ( copy_to_guest_offset(*uaddr, DIRENTRY_NAME_OFF, name,
e_namelen + 1) )
return -EFAULT;
guest_handle_add_offset(*uaddr, e_len);
return 0;
}
static const struct hypfs_entry *hypfs_dyndir_enter(
const struct hypfs_entry *entry)
{
const struct hypfs_dyndir_id *data;
data = hypfs_get_dyndata();
/* Use template with original enter function. */
return data->template->e.funcs->enter(&data->template->e);
}
static struct hypfs_entry *hypfs_dyndir_findentry(
const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len)
{
const struct hypfs_dyndir_id *data;
data = hypfs_get_dyndata();
/* Use template with original findentry function. */
return data->template->e.funcs->findentry(data->template, name, name_len);
}
static int hypfs_read_dyndir(const struct hypfs_entry *entry,
XEN_GUEST_HANDLE_PARAM(void) uaddr)
{
const struct hypfs_dyndir_id *data;
data = hypfs_get_dyndata();
/* Use template with original read function. */
return data->template->e.funcs->read(&data->template->e, uaddr);
}
/*
* Fill dyndata with a dynamically generated entry based on a template
* and a numerical id.
* Needs to be kept in sync with hypfs_read_dyndir_id_entry() regarding the
* name generated.
*/
struct hypfs_entry *hypfs_gen_dyndir_id_entry(
const struct hypfs_entry_dir *template, unsigned int id, void *data)
{
struct hypfs_dyndir_id *dyndata;
dyndata = hypfs_get_dyndata();
dyndata->template = template;
dyndata->id = id;
dyndata->data = data;
snprintf(dyndata->name, sizeof(dyndata->name), template->e.name, id);
dyndata->dir = *template;
dyndata->dir.e.name = dyndata->name;
dyndata->dir.e.funcs = &dyndata->funcs;
dyndata->funcs = *template->e.funcs;
dyndata->funcs.enter = hypfs_dyndir_enter;
dyndata->funcs.findentry = hypfs_dyndir_findentry;
dyndata->funcs.read = hypfs_read_dyndir;
return &dyndata->dir.e;
}
unsigned int hypfs_dynid_entry_size(const struct hypfs_entry *template,
unsigned int id)
{
return DIRENTRY_SIZE(snprintf(NULL, 0, template->name, id));
}
int hypfs_read_dir(const struct hypfs_entry *entry,
XEN_GUEST_HANDLE_PARAM(void) uaddr)
{
+18
View File
@@ -76,6 +76,17 @@ struct hypfs_entry_dir {
struct list_head dirlist;
};
struct hypfs_dyndir_id {
struct hypfs_entry_dir dir; /* Modified copy of template. */
struct hypfs_funcs funcs; /* Dynamic functions. */
const struct hypfs_entry_dir *template; /* Template used. */
#define HYPFS_DYNDIR_ID_NAMELEN 12
char name[HYPFS_DYNDIR_ID_NAMELEN]; /* Name of hypfs entry. */
unsigned int id; /* Numerical id. */
void *data; /* Data associated with id. */
};
#define HYPFS_DIR_INIT_FUNC(var, nam, fn) \
struct hypfs_entry_dir __read_mostly var = { \
.e.type = XEN_HYPFS_TYPE_DIR, \
@@ -186,6 +197,13 @@ void *hypfs_alloc_dyndata(unsigned long size);
#define hypfs_alloc_dyndata(type) ((type *)hypfs_alloc_dyndata(sizeof(type)))
void *hypfs_get_dyndata(void);
void hypfs_free_dyndata(void);
int hypfs_read_dyndir_id_entry(const struct hypfs_entry_dir *template,
unsigned int id, bool is_last,
XEN_GUEST_HANDLE_PARAM(void) *uaddr);
struct hypfs_entry *hypfs_gen_dyndir_id_entry(
const struct hypfs_entry_dir *template, unsigned int id, void *data);
unsigned int hypfs_dynid_entry_size(const struct hypfs_entry *template,
unsigned int id);
#endif
#endif /* __XEN_HYPFS_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.