1 /* BLURB lgpl
2 
3                            Coda File System
4                               Release 5
5 
6           Copyright (c) 1987-1999 Carnegie Mellon University
7                   Additional copyrights listed below
8 
9 This  code  is  distributed "AS IS" without warranty of any kind under
10 the  terms of the  GNU  Library General Public Licence  Version 2,  as
11 shown in the file LICENSE. The technical and financial contributors to
12 Coda are listed in the file CREDITS.
13 
14                         Additional copyrights
15                            none currently
16 
17 #*/
18 
19 /*
20 *
21 *                   RVM  Unmapping
22 *
23 */
24 
25 #include "rvm_private.h"
26 
27 /* global variables */
28 
29 extern log_t    *default_log;           /* default log descriptor ptr */
30 extern char     *rvm_errmsg;            /* internal error message buffer */
31 
32 extern
33 rw_lock_t       region_tree_lock;       /* lock for region tree */
34 extern
35 tree_node_t     *region_tree;           /* root of mapped region tree */
36 /* rvm_unmap */
rvm_unmap(rvm_region)37 rvm_return_t rvm_unmap(rvm_region)
38     rvm_region_t        *rvm_region;    /* region to unmap */
39     {
40     rvm_return_t        retval;
41     region_t            *region;        /* internal region descriptor */
42     seg_t               *seg;           /* internal segment descriptor */
43 
44     if (bad_init()) return RVM_EINIT;
45     if ((retval=bad_region(rvm_region)) != RVM_SUCCESS)
46         return retval;
47 
48     /* find and lock region descriptor */
49     region = find_whole_range(rvm_region->vmaddr,    /* begin region_tree_lock, */
50                               rvm_region->length,w); /* region_lock crit sects */
51     if (region == NULL)
52         return RVM_ENOT_MAPPED;
53 
54     /* check if has uncommitted transactions */
55     if (region->n_uncommit != 0)
56         {
57         retval = RVM_EUNCOMMIT;
58         goto err_exit;
59         }
60 
61     /* be sure whole region specified */
62     if ((region->vmaddr != rvm_region->vmaddr) ||
63         (region->length != rvm_region->length))
64         {
65         retval = RVM_ERANGE;
66         goto err_exit;
67         }
68 
69     /* remove from region tree and unlock tree */
70     if (!tree_delete(&region_tree,(tree_node_t *)region->mem_region,
71                       mem_total_include))
72         assert(rvm_false);              /* couldn't find node */
73     rw_unlock(&region_tree_lock,w);     /* end region_tree_lock crit sect */
74     rw_unlock(&region->region_lock,w);  /* end region_lock crit sect */
75 
76     /* unlink from seg's map_list */
77     seg = region->seg;
78     CRITICAL(seg->seg_lock,             /* begin seg_lock critical section */
79         {
80         (void)move_list_entry(&seg->map_list,NULL,
81                               (list_entry_t *)region);
82 
83         /* if dirty, put on unmapped list; otherwise scrap */
84         if (region->dirty)
85             {
86             make_uname(&region->unmap_ts); /* timestamp unmap */
87             (void)move_list_entry(NULL,&seg->unmap_list,
88                                   (list_entry_t *)region);
89             }
90         else
91             free_region(region);
92         });                             /* end seg_lock critical section */
93 
94     return RVM_SUCCESS;
95 
96 err_exit:
97     rw_unlock(&region->region_lock,w);
98     rw_unlock(&region_tree_lock,w);
99     return retval;
100     }
101