s/procfs: The procfs file system can now be configured so that it supports a runtime registration of procfs entries with CONFIG_FS_PROCFS_REGISTER=y
This commit is contained in:
parent
c16648b3fd
commit
ad64c033e7
@ -11189,3 +11189,9 @@
|
||||
* net/: Remove CONFIG_NET_PINGADDRCONF. This was a uIP way of assigning
|
||||
IP addresses, but is not standard and not a appropriate feature in
|
||||
general (2015-12-01).
|
||||
* fs/procfs: The procfs file system can now be configured so that it
|
||||
supports a runtime registration of procfs entries with
|
||||
CONFIG_FS_PROCFS_REGISTER=y (2015-12-01).
|
||||
* arch/arm/src/stm32/stm32_ccm_procfs.c: Is no longer a part of the
|
||||
'base' procfs entries and can now only be supported via run time
|
||||
registration with CONFIG_FS_PROCFS_REGISTER=y (2015-12-01).
|
||||
|
2
arch
2
arch
@ -1 +1 @@
|
||||
Subproject commit 350314f22d2357cf4f67b384c89eaa92715758c3
|
||||
Subproject commit 0dc110a8fa020ed7c301fe0cdcb836ee8ea939e9
|
@ -15,6 +15,13 @@ config FS_PROCFS
|
||||
|
||||
if FS_PROCFS
|
||||
|
||||
config FS_PROCFS_REGISTER
|
||||
bool "Run-time registration"
|
||||
default n
|
||||
---help---
|
||||
Support run-time registration of the new entries in the procfs file
|
||||
system.
|
||||
|
||||
menu "Exclude individual procfs entries"
|
||||
|
||||
config FS_PROCFS_EXCLUDE_PROCESS
|
||||
@ -59,10 +66,5 @@ config FS_PROCFS_EXCLUDE_SMARTFS
|
||||
depends on FS_SMARTFS
|
||||
default n
|
||||
|
||||
config FS_PROCFS_EXCLUDE_CCM
|
||||
bool "Exclude CCM memory usage"
|
||||
depends on STM32_CCM_PROCFS
|
||||
default n
|
||||
|
||||
endmenu #
|
||||
endif # FS_PROCFS
|
||||
|
@ -104,7 +104,11 @@ extern const struct procfs_operations ccm_procfsoperations;
|
||||
****************************************************************************/
|
||||
/* Table of all known / pre-registered procfs handlers / participants. */
|
||||
|
||||
static const struct procfs_entry_s g_procfsentries[] =
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
static const struct procfs_entry_s g_base_entries[] =
|
||||
#else
|
||||
static const struct procfs_entry_s g_procfs_entries[] =
|
||||
#endif
|
||||
{
|
||||
#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
|
||||
{ "[0-9]*/**", &proc_operations },
|
||||
@ -136,15 +140,19 @@ static const struct procfs_entry_s g_procfsentries[] =
|
||||
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
|
||||
{ "uptime", &uptime_operations },
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STM32_CCM_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CCM)
|
||||
{ "ccm", &ccm_procfsoperations },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const uint8_t g_procfsentrycount = sizeof(g_procfsentries) /
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
static const uint8_t g_base_entrycount = sizeof(g_base_entries) /
|
||||
sizeof(struct procfs_entry_s);
|
||||
|
||||
static FAR struct procfs_entry_s *g_procfs_entries;
|
||||
static uint8_t g_procfs_entrycount;
|
||||
#else
|
||||
static const uint8_t g_procfs_entrycount = sizeof(g_procfs_entries) /
|
||||
sizeof(struct procfs_entry_s);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -186,6 +194,14 @@ static int procfs_statfs(FAR struct inode *mountpt,
|
||||
static int procfs_stat(FAR struct inode *mountpt,
|
||||
FAR const char *relpath, FAR struct stat *buf);
|
||||
|
||||
/* Initialization */
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
int procfs_initialize(void);
|
||||
#else
|
||||
# define procfs_initialize()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
@ -301,25 +317,25 @@ static int procfs_open(FAR struct file *filep, FAR const char *relpath,
|
||||
|
||||
/* Perform the stat based on the procfs_entry operations */
|
||||
|
||||
for (x = 0; x < g_procfsentrycount; x++)
|
||||
for (x = 0; x < g_procfs_entrycount; x++)
|
||||
{
|
||||
/* Test if the path matches this entry's specification */
|
||||
|
||||
if (match(g_procfsentries[x].pathpattern, relpath))
|
||||
if (match(g_procfs_entries[x].pathpattern, relpath))
|
||||
{
|
||||
/* Match found! Stat using this procfs entry */
|
||||
|
||||
DEBUGASSERT(g_procfsentries[x].ops &&
|
||||
g_procfsentries[x].ops->open);
|
||||
DEBUGASSERT(g_procfs_entries[x].ops &&
|
||||
g_procfs_entries[x].ops->open);
|
||||
|
||||
ret = g_procfsentries[x].ops->open(filep, relpath, oflags, mode);
|
||||
ret = g_procfs_entries[x].ops->open(filep, relpath, oflags, mode);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
DEBUGASSERT(filep->f_priv);
|
||||
|
||||
((struct procfs_file_s *) filep->f_priv)->procfsentry =
|
||||
&g_procfsentries[x];
|
||||
&g_procfs_entries[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -506,19 +522,19 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
|
||||
/* Search the static array of procfs_entries */
|
||||
|
||||
for (x = 0; x < g_procfsentrycount; x++)
|
||||
for (x = 0; x < g_procfs_entrycount; x++)
|
||||
{
|
||||
/* Test if the path matches this entry's specification */
|
||||
|
||||
if (match(g_procfsentries[x].pathpattern, relpath))
|
||||
if (match(g_procfs_entries[x].pathpattern, relpath))
|
||||
{
|
||||
/* Match found! Call the handler's opendir routine. If successful,
|
||||
* this opendir routine will create an entry derived from struct
|
||||
* procfs_dir_priv_s as dir->u.procfs.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(g_procfsentries[x].ops && g_procfsentries[x].ops->opendir);
|
||||
ret = g_procfsentries[x].ops->opendir(relpath, dir);
|
||||
DEBUGASSERT(g_procfs_entries[x].ops && g_procfs_entries[x].ops->opendir);
|
||||
ret = g_procfs_entries[x].ops->opendir(relpath, dir);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -527,7 +543,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
/* Set the procfs_entry handler */
|
||||
|
||||
dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs;
|
||||
dirpriv->procfsentry = &g_procfsentries[x];
|
||||
dirpriv->procfsentry = &g_procfs_entries[x];
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -535,7 +551,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
|
||||
/* Test for a sub-string match (e.g. "ls /proc/fs") */
|
||||
|
||||
else if (strncmp(g_procfsentries[x].pathpattern, relpath, len) == 0)
|
||||
else if (strncmp(g_procfs_entries[x].pathpattern, relpath, len) == 0)
|
||||
{
|
||||
FAR struct procfs_level1_s *level1;
|
||||
|
||||
@ -635,9 +651,9 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
* directory name.
|
||||
*/
|
||||
|
||||
while (index < priv->nentries + g_procfsentrycount)
|
||||
while (index < priv->nentries + g_procfs_entrycount)
|
||||
{
|
||||
name = g_procfsentries[index - priv->nentries].pathpattern;
|
||||
name = g_procfs_entries[index - priv->nentries].pathpattern;
|
||||
while (*name != '/' && *name != '\0')
|
||||
{
|
||||
if (*name == '*' || *name == '[' || *name == '?')
|
||||
@ -665,7 +681,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
* fs/nxffs
|
||||
*/
|
||||
|
||||
name = g_procfsentries[index - priv->nentries].pathpattern;
|
||||
name = g_procfs_entries[index - priv->nentries].pathpattern;
|
||||
if (!level0->lastlen || (strncmp(name, level0->lastread,
|
||||
level0->lastlen) != 0))
|
||||
{
|
||||
@ -686,7 +702,7 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
|
||||
/* Test if we are at the end of the directory */
|
||||
|
||||
if (index >= priv->nentries + g_procfsentrycount)
|
||||
if (index >= priv->nentries + g_procfs_entrycount)
|
||||
{
|
||||
/* We signal the end of the directory by returning the special
|
||||
* error -ENOENT
|
||||
@ -763,13 +779,13 @@ static int procfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
* subdirectory are listed in order in the procfs_entry array.
|
||||
*/
|
||||
|
||||
if (strncmp(g_procfsentries[level1->base.index].pathpattern,
|
||||
g_procfsentries[level1->firstindex].pathpattern,
|
||||
if (strncmp(g_procfs_entries[level1->base.index].pathpattern,
|
||||
g_procfs_entries[level1->firstindex].pathpattern,
|
||||
level1->subdirlen) == 0)
|
||||
{
|
||||
/* This entry matches. Report the subdir entry */
|
||||
|
||||
name = &g_procfsentries[level1->base.index].pathpattern[
|
||||
name = &g_procfs_entries[level1->base.index].pathpattern[
|
||||
level1->subdirlen + 1];
|
||||
level1->lastlen = strcspn(name, "/");
|
||||
level1->lastread = name;
|
||||
@ -859,6 +875,9 @@ static int procfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
|
||||
static int procfs_bind(FAR struct inode *blkdriver, const void *data,
|
||||
void **handle)
|
||||
{
|
||||
/* Make sure that we are properly initialized */
|
||||
|
||||
procfs_initialize();
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -933,23 +952,23 @@ static int procfs_stat(struct inode *mountpt, const char *relpath,
|
||||
|
||||
/* Perform the stat based on the procfs_entry operations */
|
||||
|
||||
for (x = 0; x < g_procfsentrycount; x++)
|
||||
for (x = 0; x < g_procfs_entrycount; x++)
|
||||
{
|
||||
/* Test if the path matches this entry's specification */
|
||||
|
||||
if (match(g_procfsentries[x].pathpattern, relpath))
|
||||
if (match(g_procfs_entries[x].pathpattern, relpath))
|
||||
{
|
||||
/* Match found! Stat using this procfs entry */
|
||||
|
||||
DEBUGASSERT(g_procfsentries[x].ops &&
|
||||
g_procfsentries[x].ops->stat);
|
||||
DEBUGASSERT(g_procfs_entries[x].ops &&
|
||||
g_procfs_entries[x].ops->stat);
|
||||
|
||||
return g_procfsentries[x].ops->stat(relpath, buf);
|
||||
return g_procfs_entries[x].ops->stat(relpath, buf);
|
||||
}
|
||||
|
||||
/* Test for an internal subdirectory stat */
|
||||
|
||||
else if (strncmp(g_procfsentries[x].pathpattern, relpath, len) == 0)
|
||||
else if (strncmp(g_procfs_entries[x].pathpattern, relpath, len) == 0)
|
||||
{
|
||||
/* It's an internal subdirectory */
|
||||
|
||||
@ -968,8 +987,98 @@ static int procfs_stat(struct inode *mountpt, const char *relpath,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: procfs_initialize
|
||||
*
|
||||
* Description:
|
||||
* Configure the initial set of entries in the procfs file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
int procfs_initialize(void)
|
||||
{
|
||||
/* Are we already initialized? */
|
||||
|
||||
if (g_procfs_entries == NULL)
|
||||
{
|
||||
/* No.. allocate a modifyable list of entries */
|
||||
|
||||
g_procfs_entries = (FAR struct procfs_entry_s *)
|
||||
kmm_malloc(sizeof(g_base_entries));
|
||||
|
||||
if (g_procfs_entries == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* And copy the fixed entries into the allocated array */
|
||||
|
||||
memcpy(g_procfs_entries, g_base_entries, sizeof(g_base_entries));
|
||||
g_procfs_entrycount = g_base_entrycount;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: procfs_register
|
||||
*
|
||||
* Description:
|
||||
* Add a new entry to the procfs file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* entry - Describes the entry to be registered.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
int procfs_register(FAR const struct procfs_file_s *entry)
|
||||
{
|
||||
FAR struct procfs_entry_s *newtable;
|
||||
unsigned int newcount;
|
||||
size_t newsize;
|
||||
int ret;
|
||||
|
||||
/* Make sure that we are properly initialized */
|
||||
|
||||
procfs_initialize();
|
||||
|
||||
/* realloc the procfs entries */
|
||||
|
||||
newcount = g_procfs_entrycount + 1;
|
||||
newsize = newcount * sizeof(struct procfs_entry_s);
|
||||
|
||||
sched_lock();
|
||||
newtable = (FAR struct procfs_entry_s *)realloc(g_procfs_entries, newsize);
|
||||
if (newtable == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&newtable[g_procfs_entrycount], entry, sizeof(struct procfs_entry_s));
|
||||
g_procfs_entrycount = newcount;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */
|
||||
|
@ -180,6 +180,24 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen,
|
||||
FAR char *dest, size_t destlen,
|
||||
off_t *offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: procfs_register
|
||||
*
|
||||
* Description:
|
||||
* Add a new entry to the procfs file system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* entry - Describes the entry to be registered.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS_REGISTER
|
||||
int procfs_register(FAR const struct procfs_file_s *entry);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user