[CIFS] Readdir fixes to allow search to start at arbitrary position
in directory

Also includes first part of fix to compensate for servers which forget
to return . and .. as well as updates to changelog and cifs readme.

Signed-off-by: Steve French <sfrench@us.ibm.com>
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 7b8591a..41c022e 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -590,6 +590,13 @@
 	first_entry_in_buffer = 
 		cifsFile->srch_inf.index_of_last_entry - 
 			cifsFile->srch_inf.entries_in_buffer;
+
+	/* if first entry in buf is zero then is first buffer
+	in search response data which means it is likely . and ..
+	will be in this buffer, although some servers do not return
+	. and .. for the root of a drive and for those we need
+	to start two entries earlier */
+
 /*	dump_cifs_file_struct(file, "In fce ");*/
 	if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
 	     is_dir_changed(file)) || 
@@ -632,23 +639,14 @@
 		char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 
 			smbCalcSize((struct smb_hdr *)
 				cifsFile->srch_inf.ntwrk_buf_start);
+
+		current_entry = cifsFile->srch_inf.srch_entries_start;
 		first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
 					- cifsFile->srch_inf.entries_in_buffer;
 		pos_in_buf = index_to_find - first_entry_in_buffer;
 		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 
-		current_entry = cifsFile->srch_inf.srch_entries_start;
 		for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
 			/* go entry by entry figuring out which is first */
-			/* if( . or ..)
-				skip */
-			rc = cifs_entry_is_dot(current_entry,cifsFile);
-			if(rc == 1) /* is . or .. so skip */ {
-				cFYI(1,("Entry is .")); /* BB removeme BB */
-				/* continue; */
-			} else if (rc == 2 ) {
-				cFYI(1,("Entry is ..")); /* BB removeme BB */
-				/* continue; */
-			}
 			current_entry = nxt_dir_entry(current_entry,end_of_smb);
 		}
 		if((current_entry == NULL) && (i < pos_in_buf)) {
@@ -768,6 +766,11 @@
 	if(file->f_dentry == NULL)
 		return -ENOENT;
 
+	rc = cifs_entry_is_dot(pfindEntry,cifsF);
+	/* skip . and .. since we added them first */
+	if(rc != 0) 
+		return 0;
+
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 
 	qstring.name = scratch_buf;
@@ -896,22 +899,22 @@
 
 	switch ((int) file->f_pos) {
 	case 0:
-		/*if (filldir(direntry, ".", 1, file->f_pos,
+		if (filldir(direntry, ".", 1, file->f_pos,
 		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("Filldir for current dir failed "));
+			cERROR(1, ("Filldir for current dir failed"));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
+		file->f_pos++;
 	case 1:
-		/* if (filldir(direntry, "..", 2, file->f_pos,
+		if (filldir(direntry, "..", 2, file->f_pos,
 		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
 			cERROR(1, ("Filldir for parent dir failed "));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
-	case 2:
+		file->f_pos++;
+	default:
 		/* 1) If search is active, 
 			is in current search buffer? 
 			if it before then restart search
@@ -925,7 +928,6 @@
 				return rc;
 			}
 		}
-	default:
 		if(file->private_data == NULL) {
 			rc = -EINVAL;
 			FreeXid(xid);
@@ -945,8 +947,6 @@
 		kfree(cifsFile->search_resume_name);
 		cifsFile->search_resume_name = NULL; */
 
-		/* BB account for . and .. in f_pos as special case */
-
 		rc = find_cifs_entry(xid,pTcon, file,
 				&current_entry,&num_to_fill);
 		if(rc) {
@@ -975,7 +975,8 @@
 					  num_to_fill, i));
 				break;
 			}
-
+			/* if buggy server returns . and .. late do
+			we want to check for that here? */
 			rc = cifs_filldir(current_entry, file, 
 					filldir, direntry,tmp_buf);
 			file->f_pos++;