File: /usr/src/linux/fs/fat/cvf.c

1     /* 
2      * CVF extensions for fat-based filesystems
3      *
4      * written 1997,1998 by Frank Gockel <gockel@sent13.uni-duisburg.de>
5      *
6      * please do not remove the next line, dmsdos needs it for verifying patches
7      * CVF-FAT-VERSION-ID: 1.2.0
8      *
9      */
10      
11     #include<linux/sched.h>
12     #include<linux/fs.h>
13     #include<linux/msdos_fs.h>
14     #include<linux/msdos_fs_sb.h>
15     #include<linux/string.h>
16     #include<linux/fat_cvf.h>
17     #include<linux/config.h>
18     #ifdef CONFIG_KMOD
19     #include<linux/kmod.h>
20     #endif
21     
22     #define MAX_CVF_FORMATS 3
23     
24     struct buffer_head *default_fat_bread(struct super_block *,int);
25     struct buffer_head *default_fat_getblk(struct super_block *, int);
26     void default_fat_brelse(struct super_block *, struct buffer_head *);
27     void default_fat_mark_buffer_dirty (struct super_block *, struct buffer_head *);
28     void default_fat_set_uptodate (struct super_block *, struct buffer_head *,int);
29     int default_fat_is_uptodate(struct super_block *, struct buffer_head *);
30     int default_fat_access(struct super_block *sb,int nr,int new_value);
31     void default_fat_ll_rw_block (struct super_block *sb, int opr, int nbreq,
32     			      struct buffer_head *bh[32]);
33     int default_fat_bmap(struct inode *inode,int block);
34     ssize_t default_fat_file_write(struct file *filp, const char *buf,
35     			       size_t count, loff_t *ppos);
36     
37     struct cvf_format default_cvf = {
38     	cvf_version: 		0,	/* version - who cares? */	
39     	cvf_version_text: 	"plain",
40     	flags:			0,	/* flags - who cares? */
41     	cvf_bread:		default_fat_bread,
42     	cvf_getblk:		default_fat_getblk,
43     	cvf_brelse:		default_fat_brelse,
44     	cvf_mark_buffer_dirty:	default_fat_mark_buffer_dirty,
45     	cvf_set_uptodate:	default_fat_set_uptodate,
46     	cvf_is_uptodate:	default_fat_is_uptodate,
47     	cvf_ll_rw_block:	default_fat_ll_rw_block,
48     	fat_access:		default_fat_access,
49     	cvf_bmap:		default_fat_bmap,
50     	cvf_file_read:		generic_file_read,
51     	cvf_file_write:		default_fat_file_write,
52     };
53     
54     struct cvf_format *cvf_formats[MAX_CVF_FORMATS];
55     int cvf_format_use_count[MAX_CVF_FORMATS];
56     
57     int register_cvf_format(struct cvf_format*cvf_format)
58     { int i,j;
59     
60       for(i=0;i<MAX_CVF_FORMATS;++i)
61       { if(cvf_formats[i]==NULL)
62         { /* free slot found, now check version */
63           for(j=0;j<MAX_CVF_FORMATS;++j)
64           { if(cvf_formats[j])
65             { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version)
66               { printk("register_cvf_format: version %d already registered\n",
67                        cvf_format->cvf_version);
68                 return -1;
69               }
70             }
71           }
72           cvf_formats[i]=cvf_format;
73           cvf_format_use_count[i]=0;
74           printk("CVF format %s (version id %d) successfully registered.\n",
75                  cvf_format->cvf_version_text,cvf_format->cvf_version);
76           return 0;
77         }
78       }
79       
80       printk("register_cvf_format: too many formats\n");
81       return -1;
82     }
83     
84     int unregister_cvf_format(struct cvf_format*cvf_format)
85     { int i;
86     
87       for(i=0;i<MAX_CVF_FORMATS;++i)
88       { if(cvf_formats[i])
89         { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version)
90           { if(cvf_format_use_count[i])
91             { printk("unregister_cvf_format: format %d in use, cannot remove!\n",
92               cvf_formats[i]->cvf_version);
93               return -1;
94             }
95           
96             printk("CVF format %s (version id %d) successfully unregistered.\n",
97             cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version);
98             cvf_formats[i]=NULL;
99             return 0;
100           }
101         }
102       }
103       
104       printk("unregister_cvf_format: format %d is not registered\n",
105              cvf_format->cvf_version);
106       return -1;
107     }
108     
109     void dec_cvf_format_use_count_by_version(int version)
110     { int i;
111     
112       for(i=0;i<MAX_CVF_FORMATS;++i)
113       { if(cvf_formats[i])
114         { if(cvf_formats[i]->cvf_version==version)
115           { --cvf_format_use_count[i];
116             if(cvf_format_use_count[i]<0)
117             { cvf_format_use_count[i]=0;
118               printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n");
119             }
120             return;
121           }
122         }
123       }
124       
125       printk("dec_cvf_format_use_count_by_version: version %d not found ???\n",
126              version);
127     }
128     
129     int detect_cvf(struct super_block*sb,char*force)
130     { int i;
131       int found=0;
132       int found_i=-1;
133     
134       if(force)
135         if(strcmp(force,"autoload")==0)
136         {
137     #ifdef CONFIG_KMOD
138           request_module("cvf_autoload");
139           force=NULL;
140     #else
141           printk("cannot autoload CVF modules: kmod support is not compiled into kernel\n");
142           return -1;
143     #endif
144         }
145         
146     #ifdef CONFIG_KMOD
147       if(force)
148         if(*force)
149           request_module(force);
150     #endif
151     
152       if(force)
153       { if(*force)
154         { for(i=0;i<MAX_CVF_FORMATS;++i)
155           { if(cvf_formats[i])
156             { if(!strcmp(cvf_formats[i]->cvf_version_text,force))
157                 return i;
158             }
159           }
160           printk("CVF format %s unknown (module not loaded?)\n",force);
161           return -1;
162         }
163       }
164     
165       for(i=0;i<MAX_CVF_FORMATS;++i)
166       { if(cvf_formats[i])
167         { if(cvf_formats[i]->detect_cvf(sb))
168           { ++found;
169             found_i=i;
170           }
171         }
172       }
173       
174       if(found==1)return found_i;
175       if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); 
176       return -1;
177     }
178