Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/hirofumi/fatfs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/hirofumi/fatfs-2.6:
fat: Fix stat->f_namelen
fat: Fix vfat_lookup()

+22 -10
+1 -1
fs/fat/inode.c
··· 558 558 buf->f_bavail = sbi->free_clusters; 559 559 buf->f_fsid.val[0] = (u32)id; 560 560 buf->f_fsid.val[1] = (u32)(id >> 32); 561 - buf->f_namelen = sbi->options.isvfat ? 260 : 12; 561 + buf->f_namelen = sbi->options.isvfat ? FAT_LFN_LEN : 12; 562 562 563 563 return 0; 564 564 }
+19 -8
fs/fat/namei_vfat.c
··· 502 502 *outlen = utf8s_to_utf16s(name, len, (wchar_t *)outname); 503 503 if (*outlen < 0) 504 504 return *outlen; 505 - else if (*outlen > 255) 505 + else if (*outlen > FAT_LFN_LEN) 506 506 return -ENAMETOOLONG; 507 507 508 508 op = &outname[*outlen * sizeof(wchar_t)]; 509 509 } else { 510 510 if (nls) { 511 511 for (i = 0, ip = name, op = outname, *outlen = 0; 512 - i < len && *outlen <= 255; 512 + i < len && *outlen <= FAT_LFN_LEN; 513 513 *outlen += 1) 514 514 { 515 515 if (escape && (*ip == ':')) { ··· 549 549 return -ENAMETOOLONG; 550 550 } else { 551 551 for (i = 0, ip = name, op = outname, *outlen = 0; 552 - i < len && *outlen <= 255; 552 + i < len && *outlen <= FAT_LFN_LEN; 553 553 i++, *outlen += 1) 554 554 { 555 555 *op++ = *ip++; ··· 701 701 return fat_search_long(dir, qname->name, len, sinfo); 702 702 } 703 703 704 + /* 705 + * (nfsd's) anonymous disconnected dentry? 706 + * NOTE: !IS_ROOT() is not anonymous (I.e. d_splice_alias() did the job). 707 + */ 708 + static int vfat_d_anon_disconn(struct dentry *dentry) 709 + { 710 + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); 711 + } 712 + 704 713 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, 705 714 struct nameidata *nd) 706 715 { ··· 738 729 } 739 730 740 731 alias = d_find_alias(inode); 741 - if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { 732 + if (alias && !vfat_d_anon_disconn(alias)) { 742 733 /* 743 - * This inode has non DCACHE_DISCONNECTED dentry. This 744 - * means, the user did ->lookup() by an another name 745 - * (longname vs 8.3 alias of it) in past. 734 + * This inode has non anonymous-DCACHE_DISCONNECTED 735 + * dentry. This means, the user did ->lookup() by an 736 + * another name (longname vs 8.3 alias of it) in past. 746 737 * 747 738 * Switch to new one for reason of locality if possible. 748 739 */ ··· 752 743 iput(inode); 753 744 unlock_super(sb); 754 745 return alias; 755 - } 746 + } else 747 + dput(alias); 748 + 756 749 out: 757 750 unlock_super(sb); 758 751 dentry->d_op = sb->s_root->d_op;
+2 -1
include/linux/msdos_fs.h
··· 15 15 #define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ 16 16 #define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) 17 17 #define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ 18 + #define MSDOS_LONGNAME 256 /* maximum name length */ 18 19 #define CF_LE_W(v) le16_to_cpu(v) 19 20 #define CF_LE_L(v) le32_to_cpu(v) 20 21 #define CT_LE_W(v) cpu_to_le16(v) ··· 48 47 #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ 49 48 #define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) 50 49 50 + #define FAT_LFN_LEN 255 /* maximum long name length */ 51 51 #define MSDOS_NAME 11 /* maximum name length */ 52 - #define MSDOS_LONGNAME 256 /* maximum name length */ 53 52 #define MSDOS_SLOTS 21 /* max # of slots for short and long names */ 54 53 #define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ 55 54 #define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */