Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  linux/fs/filesystems.c
  3  *
  4  *  Copyright (C) 1991, 1992  Linus Torvalds
  5  *
  6  *  table of configured filesystems
  7  */
  8 
  9 #include <linux/syscalls.h>
 10 #include <linux/fs.h>
 11 #include <linux/slab.h>
 12 #include <linux/kmod.h>
 13 #include <linux/init.h>
 14 #include <linux/module.h>
 15 #include <asm/uaccess.h>
 16 
 17 /*
 18  * Handling of filesystem drivers list.
 19  * Rules:
 20  *      Inclusion to/removals from/scanning of list are protected by spinlock.
 21  *      During the unload module must call unregister_filesystem().
 22  *      We can access the fields of list element if:
 23  *              1) spinlock is held or
 24  *              2) we hold the reference to the module.
 25  *      The latter can be guaranteed by call of try_module_get(); if it
 26  *      returned 0 we must skip the element, otherwise we got the reference.
 27  *      Once the reference is obtained we can drop the spinlock.
 28  */
 29 
 30 static struct file_system_type *file_systems;
 31 static DEFINE_RWLOCK(file_systems_lock);
 32 
 33 /* WARNING: This can be used only if we _already_ own a reference */
 34 void get_filesystem(struct file_system_type *fs)
 35 {
 36         __module_get(fs->owner);
 37 }
 38 
 39 void put_filesystem(struct file_system_type *fs)
 40 {
 41         module_put(fs->owner);
 42 }
 43 
 44 static struct file_system_type **find_filesystem(const char *name)
 45 {
 46         struct file_system_type **p;
 47         for (p=&file_systems; *p; p=&(*p)->next)
 48                 if (strcmp((*p)->name,name) == 0)
 49                         break;
 50         return p;
 51 }
 52 
 53 /**
 54  *      register_filesystem - register a new filesystem
 55  *      @fs: the file system structure
 56  *
 57  *      Adds the file system passed to the list of file systems the kernel
 58  *      is aware of for mount and other syscalls. Returns 0 on success,
 59  *      or a negative errno code on an error.
 60  *
 61  *      The &struct file_system_type that is passed is linked into the kernel 
 62  *      structures and must not be freed until the file system has been
 63  *      unregistered.
 64  */
 65  
 66 int register_filesystem(struct file_system_type * fs)
 67 {
 68         int res = 0;
 69         struct file_system_type ** p;
 70 
 71         if (!fs)
 72                 return -EINVAL;
 73         if (fs->next)
 74                 return -EBUSY;
 75         INIT_LIST_HEAD(&fs->fs_supers);
 76         write_lock(&file_systems_lock);
 77         p = find_filesystem(fs->name);
 78         if (*p)
 79                 res = -EBUSY;
 80         else
 81                 *p = fs;
 82         write_unlock(&file_systems_lock);
 83         return res;
 84 }
 85 
 86 EXPORT_SYMBOL(register_filesystem);
 87 
 88 /**
 89  *      unregister_filesystem - unregister a file system
 90  *      @fs: filesystem to unregister
 91  *
 92  *      Remove a file system that was previously successfully registered
 93  *      with the kernel. An error is returned if the file system is not found.
 94  *      Zero is returned on a success.
 95  *      
 96  *      Once this function has returned the &struct file_system_type structure
 97  *      may be freed or reused.
 98  */
 99  
100 int unregister_filesystem(struct file_system_type * fs)
101 {
102         struct file_system_type ** tmp;
103 
104         write_lock(&file_systems_lock);
105         tmp = &file_systems;
106         while (*tmp) {
107                 if (fs == *tmp) {
108                         *tmp = fs->next;
109                         fs->next = NULL;
110                         write_unlock(&file_systems_lock);
111                         return 0;
112                 }
113                 tmp = &(*tmp)->next;
114         }
115         write_unlock(&file_systems_lock);
116         return -EINVAL;
117 }
118 
119 EXPORT_SYMBOL(unregister_filesystem);
120 
121 static int fs_index(const char __user * __name)
122 {
123         struct file_system_type * tmp;
124         char * name;
125         int err, index;
126 
127         name = getname(__name);
128         err = PTR_ERR(name);
129         if (IS_ERR(name))
130                 return err;
131 
132         err = -EINVAL;
133         read_lock(&file_systems_lock);
134         for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
135                 if (strcmp(tmp->name,name) == 0) {
136                         err = index;
137                         break;
138                 }
139         }
140         read_unlock(&file_systems_lock);
141         putname(name);
142         return err;
143 }
144 
145 static int fs_name(unsigned int index, char __user * buf)
146 {
147         struct file_system_type * tmp;
148         int len, res;
149 
150         read_lock(&file_systems_lock);
151         for (tmp = file_systems; tmp; tmp = tmp->next, index--)
152                 if (index <= 0 && try_module_get(tmp->owner))
153                         break;
154         read_unlock(&file_systems_lock);
155         if (!tmp)
156                 return -EINVAL;
157 
158         /* OK, we got the reference, so we can safely block */
159         len = strlen(tmp->name) + 1;
160         res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
161         put_filesystem(tmp);
162         return res;
163 }
164 
165 static int fs_maxindex(void)
166 {
167         struct file_system_type * tmp;
168         int index;
169 
170         read_lock(&file_systems_lock);
171         for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
172                 ;
173         read_unlock(&file_systems_lock);
174         return index;
175 }
176 
177 /*
178  * Whee.. Weird sysv syscall. 
179  */
180 asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
181 {
182         int retval = -EINVAL;
183 
184         switch (option) {
185                 case 1:
186                         retval = fs_index((const char __user *) arg1);
187                         break;
188 
189                 case 2:
190                         retval = fs_name(arg1, (char __user *) arg2);
191                         break;
192 
193                 case 3:
194                         retval = fs_maxindex();
195                         break;
196         }
197         return retval;
198 }
199 
200 int get_filesystem_list(char * buf)
201 {
202         int len = 0;
203         struct file_system_type * tmp;
204 
205         read_lock(&file_systems_lock);
206         tmp = file_systems;
207         while (tmp && len < PAGE_SIZE - 80) {
208                 len += sprintf(buf+len, "%s\t%s\n",
209                         (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
210                         tmp->name);
211                 tmp = tmp->next;
212         }
213         read_unlock(&file_systems_lock);
214         return len;
215 }
216 
217 struct file_system_type *get_fs_type(const char *name)
218 {
219         struct file_system_type *fs;
220 
221         read_lock(&file_systems_lock);
222         fs = *(find_filesystem(name));
223         if (fs && !try_module_get(fs->owner))
224                 fs = NULL;
225         read_unlock(&file_systems_lock);
226         if (!fs && (request_module("%s", name) == 0)) {
227                 read_lock(&file_systems_lock);
228                 fs = *(find_filesystem(name));
229                 if (fs && !try_module_get(fs->owner))
230                         fs = NULL;
231                 read_unlock(&file_systems_lock);
232         }
233         return fs;
234 }
235 
236 EXPORT_SYMBOL(get_fs_type);
237 
  This page was automatically generated by the LXR engine.