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