• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/inode/fs_inode.c
3  *
4  *   Copyright (C) 2007-2009, 2011-2012, 2016-2017 Gregory Nutt. All rights
5  *     reserved.
6  *   Author: Gregory Nutt <gnutt@nuttx.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name NuttX nor the names of its contributors may be
19  *    used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  ****************************************************************************/
36 
37 /****************************************************************************
38  * Included Files
39  ****************************************************************************/
40 
41 #include "vfs_config.h"
42 
43 #include "assert.h"
44 #include "errno.h"
45 #include "semaphore.h"
46 #include "stdlib.h"
47 #include "fs/fs.h"
48 #include "unistd.h"
49 
50 #include "inode/inode.h"
51 
52 /****************************************************************************
53  * Pre-processor Definitions
54  ****************************************************************************/
55 
56 #define NO_HOLDER ((pid_t)-1)
57 
58 /****************************************************************************
59  * Private Types
60  ****************************************************************************/
61 
62 /* Implements a re-entrant mutex for inode access.  This must be re-entrant
63  * because there can be cycles.  For example, it may be necessary to destroy
64  * a block driver inode on umount() after a removable block device has been
65  * removed.  In that case umount() holds the inode semaphore, but the block
66  * driver may callback to unregister_blockdriver() after the un-mount,
67  * requiring the semaphore again.
68  */
69 
70 struct inode_sem_s
71 {
72   sem_t   sem;     /* The semaphore */
73   pid_t   holder;  /* The current holder of the semaphore */
74   int16_t count;   /* Number of counts held */
75 };
76 
77 /****************************************************************************
78  * Private Data
79  ****************************************************************************/
80 
81 static struct inode_sem_s g_inode_sem;
82 
83 /****************************************************************************
84  * Public Functions
85  ****************************************************************************/
86 
87 /****************************************************************************
88  * Name: inode_initialize
89  *
90  * Description:
91  *   This is called from the OS initialization logic to configure the file
92  *   system.
93  *
94  ****************************************************************************/
95 
inode_initialize(void)96 void inode_initialize(void)
97 {
98   /* Initialize the semaphore to one (to support one-at-a-time access to the
99    * inode tree).
100    */
101 
102   (void)sem_init(&g_inode_sem.sem, 0, 1);
103   g_inode_sem.holder = NO_HOLDER;
104   g_inode_sem.count  = 0;
105 
106   /* Initialize files array (if it is used) */
107 
108 #ifdef CONFIG_HAVE_WEAKFUNCTIONS
109   if (files_initialize != NULL)
110 #endif
111     {
112       files_initialize();
113     }
114 }
115 
116 /****************************************************************************
117  * Name: inode_semtake
118  *
119  * Description:
120  *   Get exclusive access to the in-memory inode tree (g_inode_sem).
121  *
122  ****************************************************************************/
123 
inode_semtake(void)124 void inode_semtake(void)
125 {
126   pid_t me;
127 
128   /* Do we already hold the semaphore? */
129 
130   me = getpid();
131   if (me == g_inode_sem.holder)
132     {
133       /* Yes... just increment the count */
134 
135       g_inode_sem.count++;
136       DEBUGASSERT(g_inode_sem.count > 0);
137     }
138 
139   /* Take the semaphore (perhaps waiting) */
140 
141   else
142     {
143       while (sem_wait(&g_inode_sem.sem) != 0)
144         {
145           /* The only case that an error should occur here is if the wait
146            * was awakened by a signal.
147            */
148 
149           LOS_ASSERT(get_errno() == EINTR);
150         }
151 
152       /* No we hold the semaphore */
153 
154       g_inode_sem.holder = me;
155       g_inode_sem.count  = 1;
156     }
157 }
158 
159 /****************************************************************************
160  * Name: inode_semgive
161  *
162  * Description:
163  *   Relinquish exclusive access to the in-memory inode tree (g_inode_sem).
164  *
165  ****************************************************************************/
166 
inode_semgive(void)167 void inode_semgive(void)
168 {
169   DEBUGASSERT(g_inode_sem.holder == getpid());
170 
171   /* Is this our last count on the semaphore? */
172 
173   if (g_inode_sem.count > 1)
174     {
175       /* No.. just decrement the count */
176 
177       g_inode_sem.count--;
178     }
179 
180   /* Yes.. then we can really release the semaphore */
181 
182   else
183     {
184       g_inode_sem.holder = NO_HOLDER;
185       g_inode_sem.count  = 0;
186       (void)sem_post(&g_inode_sem.sem);
187     }
188 }
189