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:
Gregory Nutt 2015-12-01 14:56:20 -06:00
parent c16648b3fd
commit ad64c033e7
5 changed files with 172 additions and 37 deletions

View File

@ -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

@ -1 +1 @@
Subproject commit 350314f22d2357cf4f67b384c89eaa92715758c3
Subproject commit 0dc110a8fa020ed7c301fe0cdcb836ee8ea939e9

View File

@ -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

View File

@ -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,14 +140,18 @@ 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 */

View File

@ -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
}