diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 003666eaec449008b61721dd645b26f4423c45ce..744e961847263f17da8058bb06736daf967178c0 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -439,11 +439,19 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 {
 	dir_entry *realdent;
 	dir_slot *slotptr = (dir_slot *)retdent;
-	__u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+	__u8 *buflimit = cluster + ((curclust == 0) ?
+					LINEAR_PREFETCH_SIZE :
+					(mydata->clust_size * SECTOR_SIZE)
+				   );
 	__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
 	int idx = 0;
 
-	while ((__u8 *)slotptr < nextclust) {
+	if (counter > VFAT_MAXSEQ) {
+		debug("Error: VFAT name is too long\n");
+		return -1;
+	}
+
+	while ((__u8 *)slotptr < buflimit) {
 		if (counter == 0)
 			break;
 		if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
@@ -452,10 +460,11 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 		counter--;
 	}
 
-	if ((__u8 *)slotptr >= nextclust) {
+	if ((__u8 *)slotptr >= buflimit) {
 		dir_slot *slotptr2;
 
-		slotptr--;
+		if (curclust == 0)
+			return -1;
 		curclust = get_fatent(mydata, curclust);
 		if (CHECK_CLUST(curclust, mydata->fatsize)) {
 			debug("curclust: 0x%x\n", curclust);
@@ -470,14 +479,19 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
 		}
 
 		slotptr2 = (dir_slot *)get_vfatname_block;
-		while (slotptr2->id > 0x01)
+		while (counter > 0) {
+			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
+			    & 0xff) != counter)
+				return -1;
 			slotptr2++;
+			counter--;
+		}
 
 		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr2 + 1;
-		while ((__u8 *)slotptr2 >= get_vfatname_block) {
-			slot2str(slotptr2, l_name, &idx);
+		realdent = (dir_entry *)slotptr2;
+		while ((__u8 *)slotptr2 > get_vfatname_block) {
 			slotptr2--;
+			slot2str(slotptr2, l_name, &idx);
 		}
 	} else {
 		/* Save the real directory entry */
@@ -549,7 +563,7 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
 		dentptr = (dir_entry *)get_dentfromdir_block;
 
 		for (i = 0; i < DIRENTSPERCLUST; i++) {
-			char s_name[14], l_name[256];
+			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
 			l_name[0] = '\0';
 			if (dentptr->name[0] == DELETED_FLAG) {
@@ -841,7 +855,11 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
 		debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
 			cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-		if (disk_read(cursect, mydata->clust_size, do_fat_read_block) < 0) {
+		if (disk_read(cursect,
+				(mydata->fatsize == 32) ?
+				(mydata->clust_size) :
+				LINEAR_PREFETCH_SIZE,
+				do_fat_read_block) < 0) {
 			debug("Error: reading rootdir block\n");
 			return -1;
 		}
@@ -849,9 +867,13 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
 		dentptr = (dir_entry *) do_fat_read_block;
 
 		for (i = 0; i < DIRENTSPERBLOCK; i++) {
-			char s_name[14], l_name[256];
+			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
 			l_name[0] = '\0';
+			if (dentptr->name[0] == DELETED_FLAG) {
+				dentptr++;
+				continue;
+			}
 			if ((dentptr->attr & ATTR_VOLUME)) {
 #ifdef CONFIG_SUPPORT_VFAT
 				if ((dentptr->attr & ATTR_VFAT) &&
@@ -859,7 +881,10 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
 					prevcksum =
 						((dir_slot *)dentptr)->alias_checksum;
 
-					get_vfatname(mydata, 0,
+					get_vfatname(mydata,
+						     (mydata->fatsize == 32) ?
+						     root_cluster :
+						     0,
 						     do_fat_read_block,
 						     dentptr, l_name);
 
diff --git a/include/fat.h b/include/fat.h
index de48afd730654630f7e7fc803a2ca017feb575a0..afb2116e8e6de29a54db6bac1bc2781ae76d1af8 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -30,6 +30,10 @@
 #include <asm/byteorder.h>
 
 #define CONFIG_SUPPORT_VFAT
+/* Maximum Long File Name length supported here is 128 UTF-16 code units */
+#define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
+#define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
+#define LINEAR_PREFETCH_SIZE	(SECTOR_SIZE*2) /* Prefetch buffer size */
 
 #define SECTOR_SIZE FS_BLOCK_SIZE