The initial SYLOG device logic was valiant but yet still not enough

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4998 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo
2012-08-02 17:09:25 +00:00
parent 757383d819
commit 30e820d861
14 changed files with 664 additions and 206 deletions
+6 -1
View File
@@ -3109,5 +3109,10 @@
SYSLOG device that can redirect debug output to any character device or file. SYSLOG device that can redirect debug output to any character device or file.
So you can log debug output to a file or you can put the console on /dev/ttyS0 So you can log debug output to a file or you can put the console on /dev/ttyS0
and the debug output on /dev/ttyS1. and the debug output on /dev/ttyS1.
* arch/arm/src/lpc43xxl/lpc43_spifi.c: Correct an addressing error in the LPC43
SPIFI MTD driver
* drivers/syslog/syslog.c and fs/fs_syslog.c: Moved the generic syslog logic
from drivers/syslog to fs/ where is belongs. Especially after realizing that
the syslog logic is going to have to some internal FS operations in order
to realize a totally thread-independent SYSLOG interface.
+1 -1
View File
@@ -563,7 +563,7 @@ static FAR uint8_t *lpc43_cacheread(struct lpc43_dev_s *priv, off_t sector)
/* Read the new erase block into the cache */ /* Read the new erase block into the cache */
/* Get the SPIFI address corresponding to the new erase block */ /* Get the SPIFI address corresponding to the new erase block */
src = SPIFI_BASE + ((off_t)blkno << SPIFI_BLKSHIFT); src = SPIFI_BASE + (blkno << SPIFI_BLKSHIFT);
/* Read the entire erase block from FLASH */ /* Read the entire erase block from FLASH */
+82 -6
View File
@@ -1,8 +1,8 @@
############################################################################ ############################################################################
# sim/nsh/defconfig # sim/nsh/defconfig
# #
# Copyright (C) 2008-2011 Gregory Nutt. All rights reserved. # Copyright (C) 2008-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <spudmonkey@racsa.co.cr> # Author: Gregory Nutt <gnutt@nuttx.org>
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
@@ -81,9 +81,15 @@ CONFIG_ARCH_BOARD_SIM=y
# CONFIG_TASK_NAME_SIZE - Spcifies that maximum size of a # CONFIG_TASK_NAME_SIZE - Spcifies that maximum size of a
# task name to save in the TCB. Useful if scheduler # task name to save in the TCB. Useful if scheduler
# instrumentation is selected. Set to zero to disable. # instrumentation is selected. Set to zero to disable.
# CONFIG_JULIAN_TIME - Enables Julian time conversions
# CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY - # CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY -
# Used to initialize the internal time logic. # Used to initialize the internal time logic.
# CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions.
# You would only need this if you are concerned about accurate
# time conversions in the past or in the distant future.
# CONFIG_JULIAN_TIME - Enables Julian time conversions. You
# would only need this if you are concerned about accurate
# time conversion in the distand past. You must also define
# CONFIG_GREGORIAN_TIME in order to use Julian time.
# CONFIG_DEV_CONSOLE - Set if architecture-specific logic # CONFIG_DEV_CONSOLE - Set if architecture-specific logic
# provides /dev/console. Enables stdout, stderr, stdin. # provides /dev/console. Enables stdout, stderr, stdin.
# CONFIG_DEV_LOWCONSOLE - Use the simple, low-level serial console # CONFIG_DEV_LOWCONSOLE - Use the simple, low-level serial console
@@ -116,12 +122,33 @@ CONFIG_ARCH_BOARD_SIM=y
# and stderr. # and stderr.
# CONFIG_SDCLONE_DISABLE. Disable cloning of all socket # CONFIG_SDCLONE_DISABLE. Disable cloning of all socket
# desciptors by task_create() when a new task is started. If # desciptors by task_create() when a new task is started. If
# set, all sockets will appear to be closed in the new task. # set, all sockets will appear to be closed in the new task.# CONFIG_SCHED_WORKQUEUE. Create a dedicated "worker" thread to
# handle delayed processing from interrupt handlers. This feature
# is required for some drivers but, if there are not complaints,
# can be safely disabled. The worker thread also performs
# garbage collection -- completing any delayed memory deallocations
# from interrupt handlers. If the worker thread is disabled,
# then that clean will be performed by the IDLE thread instead
# (which runs at the lowest of priority and may not be appropriate
# if memory reclamation is of high priority). If CONFIG_SCHED_WORKQUEUE
# is enabled, then the following options can also be used:
# CONFIG_SCHED_WORKPRIORITY - The execution priority of the worker
# thread. Default: 50
# CONFIG_SCHED_WORKPERIOD - How often the worker thread checks for
# work in units of microseconds. Default: 50*1000 (50 MS).
# CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
# thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
# CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
# the worker thread. Default: 4
# CONFIG_SCHED_WAITPID - Enable the waitpid() API
# CONFIG_SCHED_ATEXIT - Enable the atexit() API
# CONFIG_SCHED_ONEXIT - Enable the on_exit() API
# #
#CONFIG_APPS_DIR= #CONFIG_APPS_DIR=
CONFIG_DEBUG=y CONFIG_DEBUG=n
CONFIG_DEBUG_VERBOSE=y CONFIG_DEBUG_VERBOSE=n
CONFIG_DEBUG_SYMBOLS=n CONFIG_DEBUG_SYMBOLS=n
CONFIG_HAVE_CXX=n CONFIG_HAVE_CXX=n
CONFIG_HAVE_CXXINITIALIZE=n CONFIG_HAVE_CXXINITIALIZE=n
CONFIG_MM_REGIONS=1 CONFIG_MM_REGIONS=1
@@ -142,6 +169,55 @@ CONFIG_SEM_NNESTPRIO=0
CONFIG_FDCLONE_DISABLE=n CONFIG_FDCLONE_DISABLE=n
CONFIG_FDCLONE_STDIO=n CONFIG_FDCLONE_STDIO=n
CONFIG_SDCLONE_DISABLE=y CONFIG_SDCLONE_DISABLE=y
CONFIG_SCHED_WORKQUEUE=n
CONFIG_SCHED_WORKPRIORITY=192
CONFIG_SCHED_WORKPERIOD=(50*1000)
CONFIG_SCHED_WORKSTACKSIZE=1024
CONFIG_SIG_SIGWORK=4
CONFIG_SCHED_WAITPID=n
CONFIG_SCHED_ATEXIT=n
CONFIG_SCHED_ONEXIT=n
#
# System Logging
#
# CONFIG_SYSLOG - Enables the System Logging feature.
# CONFIG_SYSLOG_DEVPATH - The full path to the system logging device
# CONFIG_SYSLOG_CHAR - Enable the generic character device for the SYSLOG.
# The full path to the SYSLOG device is provided by CONFIG_SYSLOG_DEVPATH.
# A valid character device must exist at this path. It will by opened
# by syslog_initialize.
#
# CONFIG_RAMLOG - Enables the RAM logging feature
# CONFIG_RAMLOG_CONSOLE - Use the RAM logging device as a system console.
# If this feature is enabled (along with CONFIG_DEV_CONSOLE), then all
# console output will be re-directed to a circular buffer in RAM. This
# is useful, for example, if the only console is a Telnet console. Then
# in that case, console output from non-Telnet threads will go to the
# circular buffer and can be viewed using the NSH 'dmesg' command.
# CONFIG_RAMLOG_SYSLOG - Use the RAM logging device for the syslogging
# interface. If this feature is enabled (along with CONFIG_SYSLOG),
# then all debug output (only) will be re-directed to the circular
# buffer in RAM. This RAM log can be view from NSH using the 'dmesg'
# command.
# CONFIG_RAMLOG_NPOLLWAITERS - The number of threads than can be waiting
# for this driver on poll(). Default: 4
#
# If CONFIG_RAMLOG_CONSOLE or CONFIG_RAMLOG_SYSLOG is selected, then the
# following may also be provided:
#
# CONFIG_RAMLOG_CONSOLE_BUFSIZE - Size of the console RAM log. Default: 1024
#
CONFIG_SYSLOG=n
CONFIG_SYSLOG_DEVPATH="/dev/syslog"
CONFIG_SYSLOG_CHAR=n
CONFIG_RAMLOG=n
CONFIG_RAMLOG_CONSOLE=n
CONFIG_RAMLOG_SYSLOG=y
#CONFIG_RAMLOG_NPOLLWAITERS
#CONFIG_RAMLOG_CONSOLE_BUFSIZE
# #
# The following can be used to disable categories of # The following can be used to disable categories of
+73
View File
@@ -0,0 +1,73 @@
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
comment "System Logging"
config RAMLOG
bool "RAM log device support"
default n
---help---
This is a driver that was intended to support debugging output,
aka syslogging, when the normal serial output is not available.
For example, if you are using a telnet or USB serial console,
the debug output will get lost. However, the RAMLOG device should
be usable even if system logging is disabled.
This driver is similar to a pipe in that it saves the debugging
output in a FIFO in RAM. It differs from a pipe in numerous
details as needed to support logging.
if RAMLOG
config RAMLOG_SYSLOG
bool "Use RAMLOG for SYSLOG"
default n
depends on SYSLOG
---help---
Use the RAM logging device for the syslogging interface. If this feature
is enabled (along with SYSLOG), then all debug output (only) will be re-directed
to the circular buffer in RAM. This RAM log can be view from NSH using the
'dmesg'command.
Do not enable more than one SYSLOG device.
config RAMLOG_CONSOLE
bool "Use RAMLOG for /dev/console"
default n
depends on DEV_CONSOLE
---help---
Use the RAM logging device as a system console. If this feature is enabled (along
with DEV_CONSOLE), then all console output will be re-directed to a circular
buffer in RAM. This is useful, for example, if the only console is a Telnet
console. Then in that case, console output from non-Telnet threads will go to
the circular buffer and can be viewed using the NSH 'dmesg' command.
config RAMLOG_CONSOLE_BUFSIZE
int "RAMLOG buffer size"
default 1024
depends on RAMLOG_SYSLOG || RAMLOG_CONSOLE
---help---
Size of the console RAM log. Default: 1024
config RAMLOG_CRLF
bool "RAMLOG CR/LF"
default n
---help---
Pre-pend a carriage return before every linefeed that goes into the RAM log.
config RAMLOG_NONBLOCKING
bool "RAMLOG non-block reads"
default y
---help---
Reading from the RAMLOG will never block if the RAMLOG is empty. If the RAMLOG
is empty, then zero is returned (usually interpreted as end-of-file).
config RAMLOG_NPOLLWAITERS
int "RAMLOG number of poll waiters"
default 4
depends on !DISABLE_POLL
---help---
The maximum number of threads that may be waiting on the poll method.
endif
+4 -3
View File
@@ -38,9 +38,10 @@
ifeq ($(CONFIG_SYSLOG),y) ifeq ($(CONFIG_SYSLOG),y)
ifeq ($(CONFIG_SYSLOG_CHAR),y) # If no special loggin devices are implemented, then the default SYSLOG
CSRCS += syslog.c # logic at fs/fs_syslog.c will be used
endif
# (Add other SYSLOG drivers here)
ifeq ($(CONFIG_RAMLOG),y) ifeq ($(CONFIG_RAMLOG),y)
CSRCS += ramlog.c CSRCS += ramlog.c
+11 -1
View File
@@ -7,7 +7,17 @@ debug output and, therefore, the syslogging interfaces are defined in the
header file include/debug.h. header file include/debug.h.
By default, all system log output goes to console (/dev/console). But that By default, all system log output goes to console (/dev/console). But that
behavior can be changed by the drivers in this directory. behavior can be changed by the defining CONFIG_SYSLOG in the NuttX
configuration. In that, case all low-level debug output will go through
syslog_putc().
One version of syslog_putc() is defined in fs/fs_syslog.c; that version is
used when CONFIG_SYSLOG_CHAR is defined. That version of syslog_putc()
just integrates with the file system to re-direct debug output to a
character device or to a file.
If CONFIG_SYSLOG_CHAR is not defined, then other custom SYSLOG drivers
can be used. Those custom SYSLOG drivers reside in this directory.
ramlog.c ramlog.c
-------- --------
-177
View File
@@ -1,177 +0,0 @@
/****************************************************************************
* drivers/syslog/syslog.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <nuttx/syslog.h>
#if defined(CONFIG_SYSLOG) && defined(CONFIG_SYSLOG_CHAR)
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct syslog_dev_s
{
int fd; /* File descriptor of the opened SYSLOG character device */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/* This is the device structure for the console or syslogging function. It
* must be statically initialized because the RAMLOG syslog_putc function
* could be called before the driver initialization logic executes.
*/
static struct syslog_dev_s g_sysdev = { -1 };
static const uint8_t g_syscrlf[2] = { '\r', '\n' };
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: syslog_initialize
*
* Description:
* Initialize to use the character device at CONFIG_SYSLOG_DEVPATH as the
* SYSLOG.
*
****************************************************************************/
int syslog_initialize(void)
{
/* Has the device been opened yet */
if (g_sysdev.fd < 0)
{
/* No, try to open the device now: write-only, try to create it if
* it doesn't exist (it might be a file), if it is a file that already
* exists, then append new log data to the file.
*/
g_sysdev.fd = open(CONFIG_SYSLOG_DEVPATH, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (g_sysdev.fd < 0)
{
return -get_errno();
}
}
/* The SYSLOG device is open and ready for writing. */
return OK;
}
/****************************************************************************
* Name: syslog_putc
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
* interfaces are lib_rawprintf() and lib_lowprinf(). The difference is
* the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses
* a lower level interface that works from interrupt handlers. This
* function is a a low-level interface used to implement lib_lowprintf().
*
****************************************************************************/
int syslog_putc(int ch)
{
ssize_t nbytes;
int ret;
/* Try to initialize the device. We do this repeatedly because the log
* device might be something that was not ready the first time that
* syslog_intialize() was called (such as a USB serial device or a file
* in an NFS mounted file system.
*/
ret = syslog_initialize();
if (ret < 0)
{
return ret;
}
/* Ignore carriage returns */
if (ch == '\r')
{
return ch;
}
/* Pre-pend a newline with a carriage return */
if (ch == '\n')
{
nbytes = write(g_sysdev.fd, g_syscrlf, 2);
}
else
{
nbytes = write(g_sysdev.fd, &ch, 1);
}
if (nbytes < 0)
{
return nbytes;
}
return ch;
}
#endif /* CONFIG_SYSLOG && CONFIG_SYSLOG_CHAR */
+30 -1
View File
@@ -9,4 +9,33 @@ source fs/fat/Kconfig
source fs/mmap/Kconfig source fs/mmap/Kconfig
source fs/nfs/Kconfig source fs/nfs/Kconfig
source fs/nxffs/Kconfig source fs/nxffs/Kconfig
source fs/romfs/Kconfig source fs/romfs/Kconfig
comment "System Logging"
config SYSLOG
bool "System logging"
default n
---help---
Enables generic system logging features.
config SYSLOG_DEVPATH
string "System log device"
default "/dev/syslog"
depends on SYSLOG
---help---
The full path to the system logging device. For the RAMLOG SYSLOG device,
this is normally "/dev/ramlog". For character SYSLOG devices, it should be
some other existing character device (or file) supported by the configuration
(such as "/dev/ttyS1")/
config SYSLOG_CHAR
bool "System log character device support"
default y
depends on SYSLOG
---help---
Enable the generic character device for the SYSLOG. The full path to the
SYSLOG device is provided by SYSLOG_DEVPATH. A valid character device (or
file) must exist at this path. It will by opened by syslog_initialize.
Do not enable more than one SYSLOG device.
+9 -1
View File
@@ -1,7 +1,7 @@
############################################################################ ############################################################################
# fs/Makefile # fs/Makefile
# #
# Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. # Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org> # Author: Gregory Nutt <gnutt@nuttx.org>
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,14 @@ ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c CSRCS += fs_fdopen.c
endif endif
# System logging to a character device (or file)
ifeq ($(CONFIG_SYSLOG),y)
ifeq ($(CONFIG_SYSLOG_CHAR),y)
CSRCS += fs_syslog.c
endif
endif
# Additional files required is mount-able file systems are supported # Additional files required is mount-able file systems are supported
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
+5
View File
@@ -351,6 +351,7 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2)
goto errout_with_inode; goto errout_with_inode;
} }
} }
_files_semgive(list); _files_semgive(list);
return OK; return OK;
@@ -361,9 +362,11 @@ errout_with_inode:
filep2->f_oflags = 0; filep2->f_oflags = 0;
filep2->f_pos = 0; filep2->f_pos = 0;
filep2->f_inode = NULL; filep2->f_inode = NULL;
errout_with_ret: errout_with_ret:
err = -ret; err = -ret;
_files_semgive(list); _files_semgive(list);
errout: errout:
set_errno(err); set_errno(err);
return ERROR; return ERROR;
@@ -398,8 +401,10 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd)
return i; return i;
} }
} }
_files_semgive(list); _files_semgive(list);
} }
return ERROR; return ERROR;
} }
+16 -12
View File
@@ -79,14 +79,14 @@ int inode_checkflags(FAR struct inode *inode, int oflags)
int open(const char *path, int oflags, ...) int open(const char *path, int oflags, ...)
{ {
struct filelist *list; FAR struct filelist *list;
FAR struct inode *inode; FAR struct inode *inode;
const char *relpath = NULL; FAR const char *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) #if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
mode_t mode = 0666; mode_t mode = 0666;
#endif #endif
int ret; int ret;
int fd; int fd;
/* Get the thread-specific file list */ /* Get the thread-specific file list */
@@ -118,9 +118,9 @@ int open(const char *path, int oflags, ...)
inode = inode_find(path, &relpath); inode = inode_find(path, &relpath);
if (!inode) if (!inode)
{ {
/* "O_CREAT is not set and the named file does not exist. Or, /* "O_CREAT is not set and the named file does not exist. Or, a
* a directory component in pathname does not exist or is a * directory component in pathname does not exist or is a dangling
* dangling symbolic link." * symbolic link."
*/ */
ret = ENOENT; ret = ENOENT;
@@ -131,7 +131,11 @@ int open(const char *path, int oflags, ...)
* specifically exclude block drivers. * specifically exclude block drivers.
*/ */
#ifndef CONFIG_DISABLE_MOUNTPOINT
if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
#else
if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
#endif
{ {
ret = ENXIO; ret = ENXIO;
goto errout_with_inode; goto errout_with_inode;
@@ -155,9 +159,9 @@ int open(const char *path, int oflags, ...)
goto errout_with_inode; goto errout_with_inode;
} }
/* Perform the driver open operation. NOTE that the open method may /* Perform the driver open operation. NOTE that the open method may be
* be called many times. The driver/mountpoint logic should handled this * called many times. The driver/mountpoint logic should handled this
* becuase it may also be closed that many times. * because it may also be closed that many times.
*/ */
ret = OK; ret = OK;
+421
View File
@@ -0,0 +1,421 @@
/****************************************************************************
* fs/syslog.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include <nuttx/syslog.h>
#include "fs_internal.h"
#if defined(CONFIG_SYSLOG) && defined(CONFIG_SYSLOG_CHAR)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Open the device/file write-only, try to create (file) it if it doesn't
* exist, if the file that already exists, then append the new log data to
* end of the file.
*/
#define SYSLOG_OFLAGS (O_WRONLY | O_CREAT | O_APPEND)
/****************************************************************************
* Private Types
****************************************************************************/
/* This enumeration represents the state of the SYSLOG device interface */
enum syslog_state_e
{
SYSLOG_UNINITIALIZED = 0, /* SYSLOG has not been initialized */
SYSLOG_BUSY, /* SYSLOG is not available for this thread */
SYSLOG_REOPEN, /* SYSLOG open failed... try again later */
SYSLOG_FAILURE, /* SYSLOG open failed... don't try again */
SYSLOG_OPENED, /* SYSLOG device is open and ready to use */
};
/* This structure contains all SYSLOGing state information */
struct syslog_dev_s
{
uint8_t sl_state; /* See enum syslog_state_e */
sem_t sl_sem; /* Enforces mutually exclusive access */
struct file sl_file; /* The syslog file structure */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/* This is the device structure for the console or syslogging function. */
static struct syslog_dev_s g_sysdev;
static const uint8_t g_syscrlf[2] = { '\r', '\n' };
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: syslog_write
*
* Description:
* Write to the syslog device
*
****************************************************************************/
static inline ssize_t syslog_write(FAR const void *buf, size_t nbytes)
{
FAR struct inode *inode;
/* Let the driver perform the write */
inode = g_sysdev.sl_file.f_inode;
return inode->u.i_ops->write(&g_sysdev.sl_file, buf, nbytes);
}
/****************************************************************************
* Name: syslog_flush
*
* Description:
* Flush any buffer data in the file system to media.
*
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
static inline void syslog_flush(void)
{
FAR struct inode *inode = g_sysdev.sl_file.f_inode;
/* Is this a mountpoint? Does it support the sync method? */
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops->sync)
{
/* Yes... synchronize to the stream */
(void)inode->u.i_mops->sync(&g_sysdev.sl_file);
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: syslog_initialize
*
* Description:
* Initialize to use the character device (or file) at
* CONFIG_SYSLOG_DEVPATH as the SYSLOG sink.
*
* NOTE that this implementation excludes using a network connection as
* SYSLOG device. That would be a good extension.
*
****************************************************************************/
int syslog_initialize(void)
{
FAR struct inode *inode;
FAR const char *relpath = NULL;
int ret;
/* At this point, the only expected states are SYSLOG_UNINITIALIZED or
* SYSLOG_REOPEN.. Not SYSLOG_BUSY, SYSLOG_FAILURE, SYSLOG_OPENED.
*/
DEBUGASSERT(g_sysdev.sl_state == SYSLOG_UNINITIALIZED ||
g_sysdev.sl_state == SYSLOG_REOPEN);
g_sysdev.sl_state = SYSLOG_BUSY;
/* Try to open the device.
*
* Note that we cannot just call open. The syslog device must work on all
* threads. Open returns a file descriptor that is valid only for the
* task that opened the device (and its pthread children). Instead, we
* essentially re-implement the guts of open() here so that we can get to
* the thread-independent structures of the inode.
*/
/* Get an inode for this file/device */
inode = inode_find(CONFIG_SYSLOG_DEVPATH, &relpath);
if (!inode)
{
/* The inode was not found. In this case, we will attempt to re-open
* the device repeatedly. The assumption is that the device path is
* value but that the driver has not yet been registered.
*/
g_sysdev.sl_state = SYSLOG_REOPEN;
return -ENOENT;
}
/* Verify that the inode is valid and either a character driver or a
* mountpoint.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)))
#else
if (!INODE_IS_DRIVER(inode))
#endif
{
ret = ENXIO;
goto errout_with_inode;
}
/* Make sure that the "entity" at this inode supports write access */
if (!inode->u.i_ops || !inode->u.i_ops->write)
{
return -EACCES;
goto errout_with_inode;
}
/* Initialize the file structure */
g_sysdev.sl_file.f_oflags = SYSLOG_OFLAGS;
g_sysdev.sl_file.f_pos = 0;
g_sysdev.sl_file.f_inode = inode;
/* Perform the low-level open operation. */
ret = OK;
if (inode->u.i_ops->open)
{
/* Is the inode a mountpoint? */
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* Yes. Open the device write-only, try to create it if it
* doesn't exist, if the file that already exists, then append the
* new log data to end of the file.
*/
ret = inode->u.i_mops->open(&g_sysdev.sl_file, relpath,
SYSLOG_OFLAGS, 0666);
}
/* No... then it must be a character driver in the NuttX psuedo-
* file system.
*/
else
#endif
{
ret = inode->u.i_ops->open(&g_sysdev.sl_file);
}
}
/* Was the file/device successfully opened? */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* The SYSLOG device is open and ready for writing. */
sem_init(&g_sysdev.sl_sem, 0, 1);
g_sysdev.sl_state = SYSLOG_OPENED;
return OK;
errout_with_inode:
g_sysdev.sl_state = SYSLOG_FAILURE;
inode_release(inode);
return ret;
}
/****************************************************************************
* Name: syslog_putc
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
* interfaces are lib_rawprintf() and lib_lowprinf(). The difference is
* the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses
* a lower level interface that works from interrupt handlers. This
* function is a a low-level interface used to implement lib_lowprintf().
*
****************************************************************************/
int syslog_putc(int ch)
{
ssize_t nbytes;
int ret;
/* Ignore any output:
*
* (1) Before the SYSLOG device has been initialized. This could happen
* from debug output that occurs early in the boot sequence before
* syslog_initialize() is called (SYSLOG_UNINITIALIZED_.
* (2) While the device is being initialized. The case could happen if
* debug output is generated while syslog_initialize() executes
* (SYSLOG_BUSY).
* (2) While we are generating SYSLOG output. The case could happen if
* debug output is generated while syslog_putc() executes (also
* SYSLOG_BUSY).
*/
if (g_sysdev.sl_state == SYSLOG_UNINITIALIZED ||
g_sysdev.sl_state == SYSLOG_BUSY)
{
return -EAGAIN;
}
/* If an irrecoverable failure occurred, then don't bother to try again
* (ever)
*/
if (g_sysdev.sl_state == SYSLOG_FAILURE)
{
return -ENXIO;
}
/* syslog_initialize() is called as soon as enough of the operating system
* is in place to support the open operation... but it is possible that the
* SYSLOG device is not yet registered at that time. In this case, we
* know that the system is sufficiently initialized to support an attempt
* to re-open the SYSLOG device.
*
* NOTE that the scheduler is locked. That is because we do not have fully
* initialized semaphore capability until the SYSLOG device is successfully
* initialized
*/
sched_lock();
if (g_sysdev.sl_state == SYSLOG_REOPEN)
{
/* Try again to initialize the device. We may do this repeatedly
* because the log device might be something that was not ready the
* first time that syslog_intialize() was called (such as a USB
* serial device that has not yet been connected or a file in
* an NFS mounted file system that has not yet been mounted).
*/
ret = syslog_initialize();
if (ret < 0)
{
sched_unlock();
return ret;
}
}
sched_unlock();
DEBUGASSERT(g_sysdev.sl_state == SYSLOG_OPENED);
/* Ignore carriage returns */
if (ch == '\r')
{
return ch;
}
/* The syslog device is ready for writing and we have something of
* value to write.
*/
ret = sem_wait(&g_sysdev.sl_sem);
if (ret < 0)
{
return -get_errno();
}
/* Pre-pend a newline with a carriage return. Setting sl_state to
* SYSLOG_BUSY will suppress any recursive debug logic generated by
* the syslog_write call.
*/
g_sysdev.sl_state == SYSLOG_BUSY;
if (ch == '\n')
{
/* Write the CR-LF sequence */
nbytes = syslog_write(g_syscrlf, 2);
/* Synchronize the file when each CR-LF is encountered (i.e.,
* implements line buffering always).
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (nbytes > 0)
{
syslog_flush();
}
#endif
}
else
{
/* Write the non-newline character (and don't flush) */
nbytes = syslog_write(&ch, 1);
}
g_sysdev.sl_state == SYSLOG_OPENED;
sem_post(&g_sysdev.sl_sem);
/* Check if the write was successful */
if (nbytes < 0)
{
return nbytes;
}
return ch;
}
#endif /* CONFIG_SYSLOG && CONFIG_SYSLOG_CHAR */
+1 -1
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* fs/fs_write.c * fs/fs_write.c
* *
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
+5 -2
View File
@@ -97,8 +97,11 @@ extern "C" {
* Name: syslog_initialize * Name: syslog_initialize
* *
* Description: * Description:
* Initialize to use the character device at CONFIG_SYSLOG_DEVPATH as the * Initialize to use the character device (or file) at
* SYSLOG. * CONFIG_SYSLOG_DEVPATH as the SYSLOG sink.
*
* NOTE that this implementation excludes using a network connection as
* SYSLOG device. That would be a good extension.
* *
****************************************************************************/ ****************************************************************************/