hypfs_write_locked
};
static DEFINE_PER_CPU(enum hypfs_lock_state, hypfs_locked);
+static DEFINE_PER_CPU(struct hypfs_dyndata *, hypfs_dyndata);
static DEFINE_PER_CPU(const struct hypfs_entry *, hypfs_last_node_entered);
node_exit(*last);
}
+#undef hypfs_alloc_dyndata
+void *hypfs_alloc_dyndata(unsigned long size)
+{
+ unsigned int cpu = smp_processor_id();
+ struct hypfs_dyndata **dyndata = &per_cpu(hypfs_dyndata, cpu);
+
+ ASSERT(per_cpu(hypfs_locked, cpu) != hypfs_unlocked);
+ ASSERT(*dyndata == NULL);
+
+ *dyndata = xzalloc_bytes(size);
+
+ return *dyndata;
+}
+
+void *hypfs_get_dyndata(void)
+{
+ struct hypfs_dyndata *dyndata = this_cpu(hypfs_dyndata);
+
+ ASSERT(dyndata);
+
+ return dyndata;
+}
+
+void hypfs_free_dyndata(void)
+{
+ struct hypfs_dyndata **dyndata = &this_cpu(hypfs_dyndata);
+
+ XFREE(*dyndata);
+}
+
static int add_entry(struct hypfs_entry_dir *parent, struct hypfs_entry *new)
{
int ret = -ENOENT;
return ret;
}
+void hypfs_add_dyndir(struct hypfs_entry_dir *parent,
+ struct hypfs_entry_dir *template)
+{
+ /*
+ * As the template is only a placeholder for possibly multiple dynamically
+ * generated directories, the link up to its parent can be static, while
+ * the "real" children of the parent are to be found via the parent's
+ * findentry function only.
+ */
+ template->e.parent = &parent->e;
+}
+
int hypfs_add_leaf(struct hypfs_entry_dir *parent,
struct hypfs_entry_leaf *leaf, bool nofault)
{
struct list_head dirlist;
};
-#define HYPFS_DIR_INIT(var, nam) \
+#define HYPFS_DIR_INIT_FUNC(var, nam, fn) \
struct hypfs_entry_dir __read_mostly var = { \
.e.type = XEN_HYPFS_TYPE_DIR, \
.e.encoding = XEN_HYPFS_ENC_PLAIN, \
.e.size = 0, \
.e.max_size = 0, \
.e.list = LIST_HEAD_INIT(var.e.list), \
- .e.funcs = &hypfs_dir_funcs, \
+ .e.funcs = (fn), \
.dirlist = LIST_HEAD_INIT(var.dirlist), \
}
-#define HYPFS_VARSIZE_INIT(var, typ, nam, msz) \
- struct hypfs_entry_leaf __read_mostly var = { \
- .e.type = (typ), \
- .e.encoding = XEN_HYPFS_ENC_PLAIN, \
- .e.name = (nam), \
- .e.max_size = (msz), \
- .e.funcs = &hypfs_leaf_ro_funcs, \
+#define HYPFS_DIR_INIT(var, nam) \
+ HYPFS_DIR_INIT_FUNC(var, nam, &hypfs_dir_funcs)
+
+#define HYPFS_VARSIZE_INIT(var, typ, nam, msz, fn) \
+ struct hypfs_entry_leaf __read_mostly var = { \
+ .e.type = (typ), \
+ .e.encoding = XEN_HYPFS_ENC_PLAIN, \
+ .e.name = (nam), \
+ .e.max_size = (msz), \
+ .e.funcs = (fn), \
}
/* Content and size need to be set via hypfs_string_set_reference(). */
#define HYPFS_STRING_INIT(var, nam) \
- HYPFS_VARSIZE_INIT(var, XEN_HYPFS_TYPE_STRING, nam, 0)
+ HYPFS_VARSIZE_INIT(var, XEN_HYPFS_TYPE_STRING, nam, 0, &hypfs_leaf_ro_funcs)
/*
* Set content and size of a XEN_HYPFS_TYPE_STRING node. The node will point
int hypfs_add_dir(struct hypfs_entry_dir *parent,
struct hypfs_entry_dir *dir, bool nofault);
+void hypfs_add_dyndir(struct hypfs_entry_dir *parent,
+ struct hypfs_entry_dir *template);
int hypfs_add_leaf(struct hypfs_entry_dir *parent,
struct hypfs_entry_leaf *leaf, bool nofault);
const struct hypfs_entry *hypfs_node_enter(const struct hypfs_entry *entry);
struct hypfs_entry *hypfs_dir_findentry(const struct hypfs_entry_dir *dir,
const char *name,
unsigned int name_len);
+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);
#endif
#endif /* __XEN_HYPFS_H__ */