aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fat
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/dir.c52
-rw-r--r--fs/fat/fatent.c9
-rw-r--r--fs/fat/file.c204
-rw-r--r--fs/fat/inode.c38
4 files changed, 165 insertions, 138 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 72cbcd61bd95..486725ee99ae 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -124,8 +124,8 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
124 * but ignore that right now. 124 * but ignore that right now.
125 * Ahem... Stack smashing in ring 0 isn't fun. Fixed. 125 * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
126 */ 126 */
127static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, 127static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
128 struct nls_table *nls) 128 int uni_xlate, struct nls_table *nls)
129{ 129{
130 wchar_t *ip, ec; 130 wchar_t *ip, ec;
131 unsigned char *op, nc; 131 unsigned char *op, nc;
@@ -135,10 +135,11 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
135 ip = uni; 135 ip = uni;
136 op = ascii; 136 op = ascii;
137 137
138 while (*ip) { 138 while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) {
139 ec = *ip++; 139 ec = *ip++;
140 if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { 140 if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) {
141 op += charlen; 141 op += charlen;
142 len -= charlen;
142 } else { 143 } else {
143 if (uni_xlate == 1) { 144 if (uni_xlate == 1) {
144 *op = ':'; 145 *op = ':';
@@ -149,16 +150,19 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
149 ec >>= 4; 150 ec >>= 4;
150 } 151 }
151 op += 5; 152 op += 5;
153 len -= 5;
152 } else { 154 } else {
153 *op++ = '?'; 155 *op++ = '?';
156 len--;
154 } 157 }
155 } 158 }
156 /* We have some slack there, so it's OK */
157 if (op>ascii+256) {
158 op = ascii + 256;
159 break;
160 }
161 } 159 }
160
161 if (unlikely(*ip)) {
162 printk(KERN_WARNING "FAT: filename was truncated while "
163 "converting.");
164 }
165
162 *op = 0; 166 *op = 0;
163 return (op - ascii); 167 return (op - ascii);
164} 168}
@@ -243,7 +247,7 @@ static int fat_parse_long(struct inode *dir, loff_t *pos,
243 unsigned char id, slot, slots, alias_checksum; 247 unsigned char id, slot, slots, alias_checksum;
244 248
245 if (!*unicode) { 249 if (!*unicode) {
246 *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); 250 *unicode = __getname();
247 if (!*unicode) { 251 if (!*unicode) {
248 brelse(*bh); 252 brelse(*bh);
249 return -ENOMEM; 253 return -ENOMEM;
@@ -311,9 +315,11 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
311 struct nls_table *nls_io = sbi->nls_io; 315 struct nls_table *nls_io = sbi->nls_io;
312 struct nls_table *nls_disk = sbi->nls_disk; 316 struct nls_table *nls_disk = sbi->nls_disk;
313 wchar_t bufuname[14]; 317 wchar_t bufuname[14];
314 unsigned char xlate_len, nr_slots; 318 unsigned char nr_slots;
319 int xlate_len;
315 wchar_t *unicode = NULL; 320 wchar_t *unicode = NULL;
316 unsigned char work[MSDOS_NAME], bufname[260]; /* 256 + 4 */ 321 unsigned char work[MSDOS_NAME];
322 unsigned char *bufname = NULL;
317 int uni_xlate = sbi->options.unicode_xlate; 323 int uni_xlate = sbi->options.unicode_xlate;
318 int utf8 = sbi->options.utf8; 324 int utf8 = sbi->options.utf8;
319 int anycase = (sbi->options.name_check != 's'); 325 int anycase = (sbi->options.name_check != 's');
@@ -321,6 +327,10 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
321 loff_t cpos = 0; 327 loff_t cpos = 0;
322 int chl, i, j, last_u, err; 328 int chl, i, j, last_u, err;
323 329
330 bufname = __getname();
331 if (!bufname)
332 return -ENOMEM;
333
324 err = -ENOENT; 334 err = -ENOENT;
325 while(1) { 335 while(1) {
326 if (fat_get_entry(inode, &cpos, &bh, &de) == -1) 336 if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
@@ -386,8 +396,8 @@ parse_record:
386 396
387 bufuname[last_u] = 0x0000; 397 bufuname[last_u] = 0x0000;
388 xlate_len = utf8 398 xlate_len = utf8
389 ?utf8_wcstombs(bufname, bufuname, sizeof(bufname)) 399 ?utf8_wcstombs(bufname, bufuname, PATH_MAX)
390 :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); 400 :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io);
391 if (xlate_len == name_len) 401 if (xlate_len == name_len)
392 if ((!anycase && !memcmp(name, bufname, xlate_len)) || 402 if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
393 (anycase && !nls_strnicmp(nls_io, name, bufname, 403 (anycase && !nls_strnicmp(nls_io, name, bufname,
@@ -396,8 +406,8 @@ parse_record:
396 406
397 if (nr_slots) { 407 if (nr_slots) {
398 xlate_len = utf8 408 xlate_len = utf8
399 ?utf8_wcstombs(bufname, unicode, sizeof(bufname)) 409 ?utf8_wcstombs(bufname, unicode, PATH_MAX)
400 :uni16_to_x8(bufname, unicode, uni_xlate, nls_io); 410 :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io);
401 if (xlate_len != name_len) 411 if (xlate_len != name_len)
402 continue; 412 continue;
403 if ((!anycase && !memcmp(name, bufname, xlate_len)) || 413 if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
@@ -416,8 +426,10 @@ Found:
416 sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); 426 sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
417 err = 0; 427 err = 0;
418EODir: 428EODir:
429 if (bufname)
430 __putname(bufname);
419 if (unicode) 431 if (unicode)
420 free_page((unsigned long)unicode); 432 __putname(unicode);
421 433
422 return err; 434 return err;
423} 435}
@@ -598,7 +610,7 @@ parse_record:
598 if (isvfat) { 610 if (isvfat) {
599 bufuname[j] = 0x0000; 611 bufuname[j] = 0x0000;
600 i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname)) 612 i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))
601 : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); 613 : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io);
602 } 614 }
603 615
604 fill_name = bufname; 616 fill_name = bufname;
@@ -607,10 +619,10 @@ parse_record:
607 /* convert the unicode long name. 261 is maximum size 619 /* convert the unicode long name. 261 is maximum size
608 * of unicode buffer. (13 * slots + nul) */ 620 * of unicode buffer. (13 * slots + nul) */
609 void *longname = unicode + 261; 621 void *longname = unicode + 261;
610 int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0])); 622 int buf_size = PATH_MAX - (261 * sizeof(unicode[0]));
611 int long_len = utf8 623 int long_len = utf8
612 ? utf8_wcstombs(longname, unicode, buf_size) 624 ? utf8_wcstombs(longname, unicode, buf_size)
613 : uni16_to_x8(longname, unicode, uni_xlate, nls_io); 625 : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io);
614 626
615 if (!both) { 627 if (!both) {
616 fill_name = longname; 628 fill_name = longname;
@@ -640,7 +652,7 @@ EODir:
640FillFailed: 652FillFailed:
641 brelse(bh); 653 brelse(bh);
642 if (unicode) 654 if (unicode)
643 free_page((unsigned long)unicode); 655 __putname(unicode);
644out: 656out:
645 unlock_kernel(); 657 unlock_kernel();
646 return ret; 658 return ret;
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 5fb366992b73..13ab763cc510 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -450,7 +450,8 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
450 BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */ 450 BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */
451 451
452 lock_fat(sbi); 452 lock_fat(sbi);
453 if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) { 453 if (sbi->free_clusters != -1 && sbi->free_clus_valid &&
454 sbi->free_clusters < nr_cluster) {
454 unlock_fat(sbi); 455 unlock_fat(sbi);
455 return -ENOSPC; 456 return -ENOSPC;
456 } 457 }
@@ -504,6 +505,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
504 505
505 /* Couldn't allocate the free entries */ 506 /* Couldn't allocate the free entries */
506 sbi->free_clusters = 0; 507 sbi->free_clusters = 0;
508 sbi->free_clus_valid = 1;
507 sb->s_dirt = 1; 509 sb->s_dirt = 1;
508 err = -ENOSPC; 510 err = -ENOSPC;
509 511
@@ -583,8 +585,6 @@ error:
583 brelse(bhs[i]); 585 brelse(bhs[i]);
584 unlock_fat(sbi); 586 unlock_fat(sbi);
585 587
586 fat_clusters_flush(sb);
587
588 return err; 588 return err;
589} 589}
590 590
@@ -615,7 +615,7 @@ int fat_count_free_clusters(struct super_block *sb)
615 int err = 0, free; 615 int err = 0, free;
616 616
617 lock_fat(sbi); 617 lock_fat(sbi);
618 if (sbi->free_clusters != -1) 618 if (sbi->free_clusters != -1 && sbi->free_clus_valid)
619 goto out; 619 goto out;
620 620
621 reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits; 621 reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
@@ -643,6 +643,7 @@ int fat_count_free_clusters(struct super_block *sb)
643 } while (fat_ent_next(sbi, &fatent)); 643 } while (fat_ent_next(sbi, &fatent));
644 } 644 }
645 sbi->free_clusters = free; 645 sbi->free_clusters = free;
646 sbi->free_clus_valid = 1;
646 sb->s_dirt = 1; 647 sb->s_dirt = 1;
647 fatent_brelse(&fatent); 648 fatent_brelse(&fatent);
648out: 649out:
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 2a3bed967041..d604bb132422 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -157,104 +157,6 @@ out:
157 return err; 157 return err;
158} 158}
159 159
160static int check_mode(const struct msdos_sb_info *sbi, mode_t mode)
161{
162 mode_t req = mode & ~S_IFMT;
163
164 /*
165 * Of the r and x bits, all (subject to umask) must be present. Of the
166 * w bits, either all (subject to umask) or none must be present.
167 */
168
169 if (S_ISREG(mode)) {
170 req &= ~sbi->options.fs_fmask;
171
172 if ((req & (S_IRUGO | S_IXUGO)) !=
173 ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask))
174 return -EPERM;
175
176 if ((req & S_IWUGO) != 0 &&
177 (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask))
178 return -EPERM;
179 } else if (S_ISDIR(mode)) {
180 req &= ~sbi->options.fs_dmask;
181
182 if ((req & (S_IRUGO | S_IXUGO)) !=
183 ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask))
184 return -EPERM;
185
186 if ((req & S_IWUGO) != 0 &&
187 (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask))
188 return -EPERM;
189 } else {
190 return -EPERM;
191 }
192
193 return 0;
194}
195
196int fat_notify_change(struct dentry *dentry, struct iattr *attr)
197{
198 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
199 struct inode *inode = dentry->d_inode;
200 int mask, error = 0;
201
202 lock_kernel();
203
204 /*
205 * Expand the file. Since inode_setattr() updates ->i_size
206 * before calling the ->truncate(), but FAT needs to fill the
207 * hole before it.
208 */
209 if (attr->ia_valid & ATTR_SIZE) {
210 if (attr->ia_size > inode->i_size) {
211 error = fat_cont_expand(inode, attr->ia_size);
212 if (error || attr->ia_valid == ATTR_SIZE)
213 goto out;
214 attr->ia_valid &= ~ATTR_SIZE;
215 }
216 }
217
218 error = inode_change_ok(inode, attr);
219 if (error) {
220 if (sbi->options.quiet)
221 error = 0;
222 goto out;
223 }
224 if (((attr->ia_valid & ATTR_UID) &&
225 (attr->ia_uid != sbi->options.fs_uid)) ||
226 ((attr->ia_valid & ATTR_GID) &&
227 (attr->ia_gid != sbi->options.fs_gid)))
228 error = -EPERM;
229
230 if (error) {
231 if (sbi->options.quiet)
232 error = 0;
233 goto out;
234 }
235
236 if (attr->ia_valid & ATTR_MODE) {
237 error = check_mode(sbi, attr->ia_mode);
238 if (error != 0 && !sbi->options.quiet)
239 goto out;
240 }
241
242 error = inode_setattr(inode, attr);
243 if (error)
244 goto out;
245
246 if (S_ISDIR(inode->i_mode))
247 mask = sbi->options.fs_dmask;
248 else
249 mask = sbi->options.fs_fmask;
250 inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
251out:
252 unlock_kernel();
253 return error;
254}
255
256EXPORT_SYMBOL_GPL(fat_notify_change);
257
258/* Free all clusters after the skip'th cluster. */ 160/* Free all clusters after the skip'th cluster. */
259static int fat_free(struct inode *inode, int skip) 161static int fat_free(struct inode *inode, int skip)
260{ 162{
@@ -355,8 +257,112 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
355} 257}
356EXPORT_SYMBOL_GPL(fat_getattr); 258EXPORT_SYMBOL_GPL(fat_getattr);
357 259
260static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode,
261 mode_t mode)
262{
263 mode_t mask, req = mode & ~S_IFMT;
264
265 if (S_ISREG(mode))
266 mask = sbi->options.fs_fmask;
267 else
268 mask = sbi->options.fs_dmask;
269
270 /*
271 * Of the r and x bits, all (subject to umask) must be present. Of the
272 * w bits, either all (subject to umask) or none must be present.
273 */
274 req &= ~mask;
275 if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
276 return -EPERM;
277 if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask)))
278 return -EPERM;
279
280 return 0;
281}
282
283static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
284{
285 mode_t allow_utime = sbi->options.allow_utime;
286
287 if (current->fsuid != inode->i_uid) {
288 if (in_group_p(inode->i_gid))
289 allow_utime >>= 3;
290 if (allow_utime & MAY_WRITE)
291 return 1;
292 }
293
294 /* use a default check */
295 return 0;
296}
297
298int fat_setattr(struct dentry *dentry, struct iattr *attr)
299{
300 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
301 struct inode *inode = dentry->d_inode;
302 int mask, error = 0;
303 unsigned int ia_valid;
304
305 lock_kernel();
306
307 /*
308 * Expand the file. Since inode_setattr() updates ->i_size
309 * before calling the ->truncate(), but FAT needs to fill the
310 * hole before it.
311 */
312 if (attr->ia_valid & ATTR_SIZE) {
313 if (attr->ia_size > inode->i_size) {
314 error = fat_cont_expand(inode, attr->ia_size);
315 if (error || attr->ia_valid == ATTR_SIZE)
316 goto out;
317 attr->ia_valid &= ~ATTR_SIZE;
318 }
319 }
320
321 /* Check for setting the inode time. */
322 ia_valid = attr->ia_valid;
323 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
324 if (fat_allow_set_time(sbi, inode))
325 attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET);
326 }
327
328 error = inode_change_ok(inode, attr);
329 attr->ia_valid = ia_valid;
330 if (error) {
331 if (sbi->options.quiet)
332 error = 0;
333 goto out;
334 }
335 if (((attr->ia_valid & ATTR_UID) &&
336 (attr->ia_uid != sbi->options.fs_uid)) ||
337 ((attr->ia_valid & ATTR_GID) &&
338 (attr->ia_gid != sbi->options.fs_gid)) ||
339 ((attr->ia_valid & ATTR_MODE) &&
340 fat_check_mode(sbi, inode, attr->ia_mode) < 0))
341 error = -EPERM;
342
343 if (error) {
344 if (sbi->options.quiet)
345 error = 0;
346 goto out;
347 }
348
349 error = inode_setattr(inode, attr);
350 if (error)
351 goto out;
352
353 if (S_ISDIR(inode->i_mode))
354 mask = sbi->options.fs_dmask;
355 else
356 mask = sbi->options.fs_fmask;
357 inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
358out:
359 unlock_kernel();
360 return error;
361}
362EXPORT_SYMBOL_GPL(fat_setattr);
363
358const struct inode_operations fat_file_inode_operations = { 364const struct inode_operations fat_file_inode_operations = {
359 .truncate = fat_truncate, 365 .truncate = fat_truncate,
360 .setattr = fat_notify_change, 366 .setattr = fat_setattr,
361 .getattr = fat_getattr, 367 .getattr = fat_getattr,
362}; 368};
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 53f3cf62b7c1..5f522a55b596 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -433,11 +433,8 @@ EXPORT_SYMBOL_GPL(fat_build_inode);
433static void fat_delete_inode(struct inode *inode) 433static void fat_delete_inode(struct inode *inode)
434{ 434{
435 truncate_inode_pages(&inode->i_data, 0); 435 truncate_inode_pages(&inode->i_data, 0);
436 436 inode->i_size = 0;
437 if (!is_bad_inode(inode)) { 437 fat_truncate(inode);
438 inode->i_size = 0;
439 fat_truncate(inode);
440 }
441 clear_inode(inode); 438 clear_inode(inode);
442} 439}
443 440
@@ -445,8 +442,6 @@ static void fat_clear_inode(struct inode *inode)
445{ 442{
446 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); 443 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
447 444
448 if (is_bad_inode(inode))
449 return;
450 lock_kernel(); 445 lock_kernel();
451 spin_lock(&sbi->inode_hash_lock); 446 spin_lock(&sbi->inode_hash_lock);
452 fat_cache_inval_inode(inode); 447 fat_cache_inval_inode(inode);
@@ -542,7 +537,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
542 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); 537 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
543 538
544 /* If the count of free cluster is still unknown, counts it here. */ 539 /* If the count of free cluster is still unknown, counts it here. */
545 if (sbi->free_clusters == -1) { 540 if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {
546 int err = fat_count_free_clusters(dentry->d_sb); 541 int err = fat_count_free_clusters(dentry->d_sb);
547 if (err) 542 if (err)
548 return err; 543 return err;
@@ -790,6 +785,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
790 seq_printf(m, ",gid=%u", opts->fs_gid); 785 seq_printf(m, ",gid=%u", opts->fs_gid);
791 seq_printf(m, ",fmask=%04o", opts->fs_fmask); 786 seq_printf(m, ",fmask=%04o", opts->fs_fmask);
792 seq_printf(m, ",dmask=%04o", opts->fs_dmask); 787 seq_printf(m, ",dmask=%04o", opts->fs_dmask);
788 if (opts->allow_utime)
789 seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
793 if (sbi->nls_disk) 790 if (sbi->nls_disk)
794 seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); 791 seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
795 if (isvfat) { 792 if (isvfat) {
@@ -845,9 +842,9 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
845 842
846enum { 843enum {
847 Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, 844 Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
848 Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase, 845 Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
849 Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, 846 Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
850 Opt_dots, Opt_nodots, 847 Opt_immutable, Opt_dots, Opt_nodots,
851 Opt_charset, Opt_shortname_lower, Opt_shortname_win95, 848 Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
852 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, 849 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
853 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, 850 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
@@ -866,6 +863,7 @@ static match_table_t fat_tokens = {
866 {Opt_umask, "umask=%o"}, 863 {Opt_umask, "umask=%o"},
867 {Opt_dmask, "dmask=%o"}, 864 {Opt_dmask, "dmask=%o"},
868 {Opt_fmask, "fmask=%o"}, 865 {Opt_fmask, "fmask=%o"},
866 {Opt_allow_utime, "allow_utime=%o"},
869 {Opt_codepage, "codepage=%u"}, 867 {Opt_codepage, "codepage=%u"},
870 {Opt_usefree, "usefree"}, 868 {Opt_usefree, "usefree"},
871 {Opt_nocase, "nocase"}, 869 {Opt_nocase, "nocase"},
@@ -937,6 +935,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
937 opts->fs_uid = current->uid; 935 opts->fs_uid = current->uid;
938 opts->fs_gid = current->gid; 936 opts->fs_gid = current->gid;
939 opts->fs_fmask = opts->fs_dmask = current->fs->umask; 937 opts->fs_fmask = opts->fs_dmask = current->fs->umask;
938 opts->allow_utime = -1;
940 opts->codepage = fat_default_codepage; 939 opts->codepage = fat_default_codepage;
941 opts->iocharset = fat_default_iocharset; 940 opts->iocharset = fat_default_iocharset;
942 if (is_vfat) 941 if (is_vfat)
@@ -1024,6 +1023,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
1024 return 0; 1023 return 0;
1025 opts->fs_fmask = option; 1024 opts->fs_fmask = option;
1026 break; 1025 break;
1026 case Opt_allow_utime:
1027 if (match_octal(&args[0], &option))
1028 return 0;
1029 opts->allow_utime = option & (S_IWGRP | S_IWOTH);
1030 break;
1027 case Opt_codepage: 1031 case Opt_codepage:
1028 if (match_int(&args[0], &option)) 1032 if (match_int(&args[0], &option))
1029 return 0; 1033 return 0;
@@ -1106,6 +1110,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
1106 " for FAT filesystems, filesystem will be case sensitive!\n"); 1110 " for FAT filesystems, filesystem will be case sensitive!\n");
1107 } 1111 }
1108 1112
1113 /* If user doesn't specify allow_utime, it's initialized from dmask. */
1114 if (opts->allow_utime == (unsigned short)-1)
1115 opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
1109 if (opts->unicode_xlate) 1116 if (opts->unicode_xlate)
1110 opts->utf8 = 0; 1117 opts->utf8 = 0;
1111 1118
@@ -1208,7 +1215,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
1208 */ 1215 */
1209 1216
1210 media = b->media; 1217 media = b->media;
1211 if (!FAT_VALID_MEDIA(media)) { 1218 if (!fat_valid_media(media)) {
1212 if (!silent) 1219 if (!silent)
1213 printk(KERN_ERR "FAT: invalid media value (0x%02x)\n", 1220 printk(KERN_ERR "FAT: invalid media value (0x%02x)\n",
1214 media); 1221 media);
@@ -1219,7 +1226,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
1219 le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); 1226 le16_to_cpu(get_unaligned((__le16 *)&b->sector_size));
1220 if (!is_power_of_2(logical_sector_size) 1227 if (!is_power_of_2(logical_sector_size)
1221 || (logical_sector_size < 512) 1228 || (logical_sector_size < 512)
1222 || (PAGE_CACHE_SIZE < logical_sector_size)) { 1229 || (logical_sector_size > 4096)) {
1223 if (!silent) 1230 if (!silent)
1224 printk(KERN_ERR "FAT: bogus logical sector size %u\n", 1231 printk(KERN_ERR "FAT: bogus logical sector size %u\n",
1225 logical_sector_size); 1232 logical_sector_size);
@@ -1267,6 +1274,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
1267 sbi->fat_length = le16_to_cpu(b->fat_length); 1274 sbi->fat_length = le16_to_cpu(b->fat_length);
1268 sbi->root_cluster = 0; 1275 sbi->root_cluster = 0;
1269 sbi->free_clusters = -1; /* Don't know yet */ 1276 sbi->free_clusters = -1; /* Don't know yet */
1277 sbi->free_clus_valid = 0;
1270 sbi->prev_free = FAT_START_ENT; 1278 sbi->prev_free = FAT_START_ENT;
1271 1279
1272 if (!sbi->fat_length && b->fat32_length) { 1280 if (!sbi->fat_length && b->fat32_length) {
@@ -1302,8 +1310,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
1302 sbi->fsinfo_sector); 1310 sbi->fsinfo_sector);
1303 } else { 1311 } else {
1304 if (sbi->options.usefree) 1312 if (sbi->options.usefree)
1305 sbi->free_clusters = 1313 sbi->free_clus_valid = 1;
1306 le32_to_cpu(fsinfo->free_clusters); 1314 sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters);
1307 sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); 1315 sbi->prev_free = le32_to_cpu(fsinfo->next_cluster);
1308 } 1316 }
1309 1317