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
register_cvf_format(struct cvf_format * cvf_format)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
unregister_cvf_format(struct cvf_format * cvf_format)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
dec_cvf_format_use_count_by_version(int version)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
detect_cvf(struct super_block * sb,char * force)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