mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
0b3b53be8c
commit
4f1e5ed49c
2 files changed
+116
No files matched your search
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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__ */
|
||||