source: rtems/cpukit/libcsupport/src/unmount.c @ 9c30d6a9

4.104.114.84.95
Last change on this file since 9c30d6a9 was 9c30d6a9, checked in by Joel Sherrill <joel.sherrill@…>, on 10/25/01 at 17:41:07

2001-10-25 Jennifer Averett <jennifer@…>

  • libc/unmount.c: Primarily restructuring and clean up to address procedures which did not do what their name implied. Also addressed problem situation where unmount fails and the filesystem was inconsistent. The mounted filesystem could have been left hanging.
  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 *  unmount() - Unmount a File System
3 *
4 *  This routine is not defined in the POSIX 1003.1b standard but
5 *  in some form is supported on most UNIX and POSIX systems.  This
6 *  routine is necessary to mount instantiations of a file system
7 *  into the file system name space.
8 *
9 *  COPYRIGHT (c) 1989-1999.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.OARcorp.com/rtems/license.html.
15 *
16 *  $Id$
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <chain.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <errno.h>
29#include <stdlib.h>
30#include <string.h>
31#include <assert.h>
32
33#include <rtems/libio_.h>
34
35/*
36 *  Data structures and routines private to mount/unmount pair.
37 */
38
39extern Chain_Control                    rtems_filesystem_mount_table_control;
40
41int search_mt_for_mount_point(
42  rtems_filesystem_location_info_t *location_of_mount_point
43);
44
45rtems_boolean rtems_filesystem_nodes_equal(
46  const rtems_filesystem_location_info_t   *loc1,
47  const rtems_filesystem_location_info_t   *loc2
48){
49  return ( loc1->node_access == loc2->node_access );
50}
51
52
53/*
54 *  file_systems_below_this_mountpoint
55 *
56 *  This routine will run through the entries that currently exist in the
57 *  mount table chain. For each entry in the mount table chain it will
58 *  compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
59 *  mount table file system root nodes matches the new file system root node
60 *  this indicates that we are trying to mount a file system that has already
61 *  been mounted. This is not a permitted operation. temp_loc is set to
62 *  the root node of the file system being unmounted.
63 */
64
65rtems_boolean file_systems_below_this_mountpoint(
66  const char                            *path,
67  rtems_filesystem_location_info_t      *fs_root_loc,
68  rtems_filesystem_mount_table_entry_t  *fs_to_unmount
69)
70{
71  Chain_Node                           *the_node;
72  rtems_filesystem_mount_table_entry_t *the_mount_entry;
73
74  /*
75   * Search the mount table for any mount entries referencing this
76   * mount entry.
77   */
78
79  for ( the_node = rtems_filesystem_mount_table_control.first;
80        !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
81        the_node = the_node->next ) {
82     the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
83     if (the_mount_entry->mt_point_node.mt_entry  == fs_root_loc->mt_entry ) {
84        return TRUE;
85     }
86  }
87
88  return FALSE;
89}
90
91/*
92 *  unmount
93 *
94 *  This routine will attempt to unmount the file system that has been
95 *  is mounted a path.  If the operation is successful, 0 will
96 *  be returned to the calling routine.  Otherwise, 1 will be returned.
97 */
98
99int unmount(
100  const char *path
101)
102{
103  rtems_filesystem_location_info_t      loc;
104  rtems_filesystem_location_info_t     *fs_root_loc;
105  rtems_filesystem_location_info_t     *fs_mount_loc;
106  rtems_filesystem_mount_table_entry_t *mt_entry;
107
108  /*
109   *  Get
110   *    The root node of the mounted filesytem.
111   *    The node for the directory that the fileystem is mounted on.
112   *    The mount entry that is being refered to.
113   */
114
115  if ( rtems_filesystem_evaluate_path( path, 0x0, &loc, TRUE ) )
116    return -1;
117
118  mt_entry     = loc.mt_entry;
119  fs_mount_loc = &mt_entry->mt_point_node;
120  fs_root_loc  = &mt_entry->mt_fs_root;
121       
122  /*
123   * Verify this is the root node for the file system to be unmounted.
124   */
125
126  if ( !rtems_filesystem_nodes_equal( fs_root_loc, &loc) ){
127    rtems_filesystem_freenode( &loc );
128    set_errno_and_return_minus_one( EACCES );
129  }
130
131  /*
132   * Free the loc node and just use the nodes from the mt_entry .
133   */
134
135  rtems_filesystem_freenode( &loc );
136
137  /*
138   * Verify Unmount is supported by both filesystems.
139   */
140
141  if ( !fs_mount_loc->ops->unmount_h )
142    set_errno_and_return_minus_one( ENOTSUP );
143
144  if ( !fs_root_loc->ops->fsunmount_me_h )
145    set_errno_and_return_minus_one( ENOTSUP );
146
147
148  /*
149   *  Verify the current node is not in this filesystem.
150   *  XXX - Joel I have a question here wasn't code added
151   *        that made the current node thread based instead
152   *        of system based?  I thought it was but it doesn't
153   *        look like it in this version.
154   */
155
156  if ( rtems_filesystem_current.mt_entry == mt_entry )
157    set_errno_and_return_minus_one( EBUSY );
158
159  /*
160   *  Verify there are no file systems below the path specified
161   */
162
163  if ( file_systems_below_this_mountpoint( path, fs_root_loc, mt_entry ) != 0 )
164    set_errno_and_return_minus_one( EBUSY );
165
166  /*
167   *  Run the file descriptor table to determine if there are any file
168   *  descriptors that are currently active and reference nodes in the
169   *  file system that we are trying to unmount
170   */
171
172  if ( rtems_libio_is_open_files_in_fs( mt_entry ) == 1 )
173    set_errno_and_return_minus_one( EBUSY );
174 
175  /*
176   * Allow the file system being unmounted on to do its cleanup.
177   * If it fails it will set the errno to the approprate value
178   * and the fileystem will not be modified.
179   */
180
181  if (( fs_mount_loc->ops->unmount_h )( mt_entry ) != 0 )
182    return -1;
183
184  /*
185   *  Allow the mounted filesystem to unmark the use of the root node.
186   *
187   *  Run the unmount function for the subordinate file system.
188   *
189   *  If we fail to unmount the filesystem remount it on the base filesystems
190   *  directory node.
191   *
192   *  NOTE:  Fatal error is called in a case which should never happen
193   *         This was response was questionable but the best we could
194   *         come up with.
195   */
196
197  if ((fs_root_loc->ops->fsunmount_me_h )( mt_entry ) != 0){
198    if (( fs_mount_loc->ops->mount_h )( mt_entry ) != 0 )
199      rtems_fatal_error_occurred( 0 );
200    return -1;
201  }
202
203  /*
204   *  Extract the mount table entry from the chain
205   */
206
207  Chain_Extract( ( Chain_Node * ) mt_entry );
208
209  /*
210   *  Free the memory node that was allocated in mount
211   *  Free the memory associated with the extracted mount table entry.
212   */
213
214  rtems_filesystem_freenode( fs_mount_loc );
215  free( mt_entry );
216
217  return 0;
218}
219
220
Note: See TracBrowser for help on using the repository browser.