source: rtems/cpukit/libfs/src/rfs/rtems-rfs-inode.c @ 5d2ae6e2

4.115
Last change on this file since 5d2ae6e2 was 5d2ae6e2, checked in by Chris Johns <chrisj@…>, on Apr 25, 2014 at 7:30:37 AM

libfs/rfs: Fix the fstime failures for the RFS file system.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS File Systems Inode Routines
5 * @ingroup rtems_rfs
6 *
7 * These functions manage inodes in the RFS file system. An inode is part of a
8 * block that reside after the bitmaps in the group.
9 */
10/*
11 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <inttypes.h>
23#include <string.h>
24
25#include <rtems/rfs/rtems-rfs-block.h>
26#include <rtems/rfs/rtems-rfs-file-system.h>
27#include <rtems/rfs/rtems-rfs-inode.h>
28#include <rtems/rfs/rtems-rfs-dir.h>
29
30int
31rtems_rfs_inode_alloc (rtems_rfs_file_system* fs,
32                       rtems_rfs_bitmap_bit   goal,
33                       rtems_rfs_ino*         ino)
34{
35  rtems_rfs_bitmap_bit bit;
36  int                  rc;
37  rc = rtems_rfs_group_bitmap_alloc (fs, goal, true, &bit);
38  *ino = bit;
39  return rc;
40}
41
42int
43rtems_rfs_inode_free (rtems_rfs_file_system* fs,
44                      rtems_rfs_ino          ino)
45{
46  rtems_rfs_bitmap_bit bit;
47  bit = ino;
48  return rtems_rfs_group_bitmap_free (fs, true, bit);
49}
50
51int
52rtems_rfs_inode_open (rtems_rfs_file_system*  fs,
53                      rtems_rfs_ino           ino,
54                      rtems_rfs_inode_handle* handle,
55                      bool                    load)
56{
57  int group;
58  int gino;
59  int index;
60  int rc;
61
62  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_OPEN))
63    printf ("rtems-rfs: inode-open: ino: %" PRIu32 "\n", ino);
64
65  if (ino == RTEMS_RFS_EMPTY_INO)
66    return EINVAL;
67
68  if ((ino - RTEMS_RFS_ROOT_INO) > rtems_rfs_fs_inodes (fs))
69    return EINVAL;
70
71  handle->ino = ino;
72  handle->node = NULL;
73  handle->loads = 0;
74
75  gino  = ino - RTEMS_RFS_ROOT_INO;
76  group = gino / fs->group_inodes;
77  gino  = gino % fs->group_inodes;
78  index = (gino / fs->inodes_per_block) + RTEMS_RFS_GROUP_INODE_BLOCK;
79
80  handle->offset = gino % fs->inodes_per_block;
81  handle->block  = rtems_rfs_group_block (&fs->groups[group], index);
82
83  rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
84  if ((rc == 0) && load)
85    rc = rtems_rfs_inode_load (fs, handle);
86  return rc;
87}
88
89int
90rtems_rfs_inode_close (rtems_rfs_file_system*  fs,
91                       rtems_rfs_inode_handle* handle)
92{
93  int rc;
94
95  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
96    printf ("rtems-rfs: inode-close: ino: %" PRIu32 "\n", handle->ino);
97
98  rc = rtems_rfs_inode_unload (fs, handle, true);
99
100  if ((rc == 0) && (handle->loads > 0))
101  {
102    if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
103      printf ("rtems-rfs: inode-close: bad loads number: %d\n",
104              handle->loads);
105    rc = EIO;
106  }
107
108  handle->ino = 0;
109  return rc;
110}
111
112int
113rtems_rfs_inode_load (rtems_rfs_file_system*  fs,
114                      rtems_rfs_inode_handle* handle)
115{
116  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_LOAD))
117    printf ("rtems-rfs: inode-load: ino=%" PRIu32 " loads=%i loaded=%s\n",
118            handle->ino, handle->loads,
119            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
120
121  /*
122   * An inode does not move so once loaded no need to do again.
123   */
124
125  if (!rtems_rfs_inode_is_loaded (handle))
126  {
127    int rc;
128
129    rc = rtems_rfs_buffer_handle_request (fs,&handle->buffer,
130                                          handle->block, true);
131    if (rc > 0)
132      return rc;
133
134    handle->node = rtems_rfs_buffer_data (&handle->buffer);
135    handle->node += handle->offset;
136  }
137
138  handle->loads++;
139
140  return 0;
141}
142
143int
144rtems_rfs_inode_unload (rtems_rfs_file_system*  fs,
145                        rtems_rfs_inode_handle* handle,
146                        bool                    update_ctime)
147{
148  int rc = 0;
149
150  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_UNLOAD))
151    printf ("rtems-rfs: inode-unload: ino=%" PRIu32 " loads=%i loaded=%s\n",
152            handle->ino, handle->loads,
153            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
154
155  if (rtems_rfs_inode_is_loaded (handle))
156  {
157    if (handle->loads == 0)
158      return EIO;
159
160    handle->loads--;
161
162    if (handle->loads == 0)
163    {
164      /*
165       * If the buffer is dirty it will be release. Also set the ctime.
166       */
167      if (rtems_rfs_buffer_dirty (&handle->buffer) && update_ctime)
168        rtems_rfs_inode_set_ctime (handle, time (NULL));
169      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
170      handle->node = NULL;
171    }
172  }
173
174  return rc;
175}
176
177int
178rtems_rfs_inode_create (rtems_rfs_file_system*  fs,
179                        rtems_rfs_ino           parent,
180                        const char*             name,
181                        size_t                  length,
182                        uint16_t                mode,
183                        uint16_t                links,
184                        uid_t                   uid,
185                        gid_t                   gid,
186                        rtems_rfs_ino*          ino)
187{
188  rtems_rfs_inode_handle parent_inode;
189  rtems_rfs_inode_handle inode;
190  int                    rc;
191
192  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CREATE))
193  {
194    const char* type = "unknown";
195    int         c;
196    if (RTEMS_RFS_S_ISDIR (mode))
197      type = "dir";
198    else if (RTEMS_RFS_S_ISCHR (mode))
199      type = "char";
200    else if (RTEMS_RFS_S_ISBLK (mode))
201      type = "block";
202    else if (RTEMS_RFS_S_ISREG (mode))
203      type = "file";
204    else if (RTEMS_RFS_S_ISLNK (mode))
205      type = "link";
206    printf("rtems-rfs: inode-create: parent:%" PRIu32 " name:", parent);
207    for (c = 0; c < length; c++)
208      printf ("%c", name[c]);
209    printf (" type:%s mode:%04x (%03o)\n", type, mode, mode & ((1 << 10) - 1));
210  }
211
212  /*
213   * The file type is field within the mode. Check we have a sane mode set.
214   */
215  switch (mode & RTEMS_RFS_S_IFMT)
216  {
217    case RTEMS_RFS_S_IFDIR:
218    case RTEMS_RFS_S_IFCHR:
219    case RTEMS_RFS_S_IFBLK:
220    case RTEMS_RFS_S_IFREG:
221    case RTEMS_RFS_S_IFLNK:
222      break;
223    default:
224      return EINVAL;
225  }
226
227  rc = rtems_rfs_inode_alloc (fs, parent, ino);
228  if (rc > 0)
229    return rc;
230
231  rc = rtems_rfs_inode_open (fs, *ino, &inode, true);
232  if (rc > 0)
233  {
234    rtems_rfs_inode_free (fs, *ino);
235    return rc;
236  }
237
238  rc = rtems_rfs_inode_initialise (&inode, links, mode, uid, gid);
239  if (rc > 0)
240  {
241    rtems_rfs_inode_close (fs, &inode);
242    rtems_rfs_inode_free (fs, *ino);
243    return rc;
244  }
245
246  /*
247   * Only handle the specifics of a directory. Let caller handle the others.
248   *
249   * The inode delete will free the inode.
250   */
251  if (RTEMS_RFS_S_ISDIR (mode))
252  {
253    rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, *ino);
254    if (rc == 0)
255      rc = rtems_rfs_dir_add_entry (fs, &inode, "..", 2, parent);
256    if (rc > 0)
257    {
258      rtems_rfs_inode_delete (fs, &inode);
259      rtems_rfs_inode_close (fs, &inode);
260      return rc;
261    }
262  }
263
264  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
265  if (rc > 0)
266  {
267    rtems_rfs_inode_delete (fs, &inode);
268    rtems_rfs_inode_close (fs, &inode);
269    return rc;
270  }
271
272  rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, *ino);
273  if (rc > 0)
274  {
275    rtems_rfs_inode_delete (fs, &inode);
276    rtems_rfs_inode_close (fs, &inode);
277    rtems_rfs_inode_close (fs, &parent_inode);
278    return rc;
279  }
280
281  /*
282   * If the node is a directory update the parent link count as the
283   * new directory has the '..' link that points to the parent.
284   */
285  if (RTEMS_RFS_S_ISDIR (mode))
286    rtems_rfs_inode_set_links (&parent_inode,
287                               rtems_rfs_inode_get_links (&parent_inode) + 1);
288
289  /*
290   * Update the parent's mtime.
291   */
292  rc = rtems_rfs_inode_time_stamp_now (&parent_inode, true, true);
293  if (rc > 0)
294  {
295    rtems_rfs_inode_delete (fs, &inode);
296    rtems_rfs_inode_close (fs, &inode);
297    return rc;
298  }
299
300  rc = rtems_rfs_inode_close (fs, &parent_inode);
301  if (rc > 0)
302  {
303    rtems_rfs_inode_delete (fs, &inode);
304    rtems_rfs_inode_close (fs, &inode);
305    return rc;
306  }
307
308  rc = rtems_rfs_inode_close (fs, &inode);
309  if (rc > 0)
310  {
311    rtems_rfs_inode_free (fs, *ino);
312    return rc;
313  }
314
315  return 0;
316}
317
318int
319rtems_rfs_inode_delete (rtems_rfs_file_system*  fs,
320                        rtems_rfs_inode_handle* handle)
321{
322  int rc = 0;
323
324  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_DELETE))
325    printf("rtems-rfs: inode-delete: ino:%" PRIu32 " loaded:%s\n",
326           rtems_rfs_inode_ino (handle),
327           rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
328
329  if (rtems_rfs_inode_is_loaded (handle))
330  {
331    rtems_rfs_block_map map;
332
333    /*
334     * Free the ino number.
335     */
336    rc = rtems_rfs_inode_free (fs, handle->ino);
337    if (rc > 0)
338      return rc;
339
340    /*
341     * Free the blocks the inode may have attached.
342     */
343    rc = rtems_rfs_block_map_open (fs, handle, &map);
344    if (rc == 0)
345    {
346      int rrc;
347      rrc = rtems_rfs_block_map_free_all (fs, &map);
348      rc = rtems_rfs_block_map_close (fs, &map);
349      if (rc > 0)
350        rrc = rc;
351      memset (handle->node, 0xff, RTEMS_RFS_INODE_SIZE);
352      rtems_rfs_buffer_mark_dirty (&handle->buffer);
353      /*
354       * Do the release here to avoid the ctime field being set on a
355       * close. Also if there loads is greater then one then other loads
356       * active. Forcing the loads count to 0.
357       */
358      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
359      handle->loads = 0;
360      handle->node = NULL;
361    }
362  }
363  return rc;
364}
365
366int
367rtems_rfs_inode_initialise (rtems_rfs_inode_handle* handle,
368                            uint16_t                links,
369                            uint16_t                mode,
370                            uid_t                   uid,
371                            gid_t                   gid)
372{
373  int b;
374  rtems_rfs_inode_set_links (handle, links);
375  rtems_rfs_inode_set_flags (handle, 0);
376  rtems_rfs_inode_set_mode (handle,  mode);
377  rtems_rfs_inode_set_uid_gid (handle, uid, gid);
378  rtems_rfs_inode_set_block_offset (handle, 0);
379  rtems_rfs_inode_set_block_count (handle, 0);
380  for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
381    rtems_rfs_inode_set_block (handle, b, 0);
382  rtems_rfs_inode_set_last_map_block (handle, 0);
383  rtems_rfs_inode_set_last_data_block (handle, 0);
384  return rtems_rfs_inode_time_stamp_now (handle, true, true);
385}
386
387int
388rtems_rfs_inode_time_stamp_now (rtems_rfs_inode_handle* handle,
389                                bool                    atime,
390                                bool                    mtime)
391{
392  time_t now;
393  if (!rtems_rfs_inode_is_loaded (handle))
394    return ENXIO;
395  now = time (NULL);
396  if (atime)
397    rtems_rfs_inode_set_atime (handle, now);
398  if (mtime)
399    rtems_rfs_inode_set_mtime (handle, now);
400  return 0;
401}
402
403rtems_rfs_pos
404rtems_rfs_inode_get_size (rtems_rfs_file_system*  fs,
405                          rtems_rfs_inode_handle* handle)
406{
407  rtems_rfs_block_size size;
408  size.count = rtems_rfs_inode_get_block_count (handle);
409  size.offset = rtems_rfs_inode_get_block_offset (handle);
410  return rtems_rfs_block_get_size (fs, &size);
411}
Note: See TracBrowser for help on using the repository browser.