bk://cifs.bkbits.net/linux-2.5cifs
cifs.adm@bkbits.net|ChangeSet|20041108184149|55252 cifs.adm

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/11/07 19:40:43-06:00 sfrench@smft41.(none) 
#   [CIFS] Add cifs serverino mount parm to allow use of inode numbers reported from
#   the server (rather than generated by the client).  Some apps require inode
#   numbers to persist or inode numbers of hardlinked files to match and 
#   this requires trusting the servers inode number.
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
#   
#   
# 
# fs/cifs/inode.c
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +22 -0
#   Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client)
# 
# fs/cifs/file.c
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +29 -9
#   Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client)
# 
# fs/cifs/fcntl.c
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +1 -1
#   fix whitespace
# 
# fs/cifs/connect.c
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +7 -0
#   Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client)
# 
# fs/cifs/cifspdu.h
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +34 -0
#   new trans2 findfirst info levels
# 
# fs/cifs/cifsfs.h
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +1 -1
#   update cifs version to 1.24
# 
# fs/cifs/cifs_fs_sb.h
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +2 -1
#   Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client)
# 
# fs/cifs/CHANGES
#   2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +6 -0
#   Update cifs change log for cifs version 1.24
# 
# ChangeSet
#   2004/10/21 22:36:00-05:00 sfrench@smft41.(none) 
#   [CIFS] treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them
#   
#   Signed-off-by:  Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/inode.c
#   2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +4 -4
#   treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them
# 
# fs/cifs/file.c
#   2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +5 -6
#   treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them
# 
# fs/cifs/README
#   2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +4 -0
#   Update readme for missing cifs mount options
# 
# fs/cifs/CHANGES
#   2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +2 -1
#   update cifs change log
# 
# ChangeSet
#   2004/10/19 17:59:37-05:00 sfrench@smft41.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into smft41.(none):/home/sfrench/linux-2.5cifs
# 
# fs/cifs/CHANGES
#   2004/10/19 17:59:29-05:00 sfrench@smft41.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/19 17:56:53-05:00 sfrench@smft41.(none) 
#   [CIFS] ignore guest mount option do not log warning on it
#   
#   Signed-off-by:  Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/connect.c
#   2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +2 -0
#   ignore guest mount option do not log warning on it
# 
# fs/cifs/cifspdu.h
#   2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +2 -0
#   missing defines for a few info levels
# 
# fs/cifs/cifsfs.h
#   2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +1 -1
#   Update change log for version 1.23 of cifs vfs 
# 
# fs/cifs/CHANGES
#   2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +6 -0
#   Update change log for version 1.23 of cifs vfs 
# 
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/CHANGES	2004-11-09 00:24:22 -08:00
@@ -1,3 +1,16 @@
+Version 1.24
+------------
+Optionally allow using server side inode numbers, rather than client generated
+ones by specifying mount option "serverino" - this is required for some apps
+to work which double check hardlinked files and have persistent inode numbers.
+
+Version 1.23
+------------
+Multiple bigendian fixes. On little endian systems (for reconnect after
+network failure) fix tcp session reconnect code so we do not try first
+to reconnect on reverse of port 445. Treat reparse points (NTFS junctions)
+as directories rather than symlinks because we can do follow link on them.
+
 Version 1.22
 ------------
 Add config option to enable XATTR (extended attribute) support, mapping
diff -Nru a/fs/cifs/README b/fs/cifs/README
--- a/fs/cifs/README	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/README	2004-11-09 00:24:22 -08:00
@@ -266,6 +266,10 @@
 		If you do not trust the servers in your network (your mount
 		targets) it is recommended that you specify this option for
 		greater security.
+  exec		Permit execution of binaries on the mount.
+  noexec	Do not permit execution of binaries on the mount.
+  dev		Recognize block devices on the remote mount.
+  nodev		Do not recognize devices on the remote mount.
   suid          Allow remote files on this mountpoint with suid enabled to 
 		be executed (default for mounts when executed as root,
 		nosuid is default for user mounts).
diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
--- a/fs/cifs/cifs_fs_sb.h	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/cifs_fs_sb.h	2004-11-09 00:24:22 -08:00
@@ -18,8 +18,9 @@
 #ifndef _CIFS_FS_SB_H
 #define _CIFS_FS_SB_H
 
-#define CIFS_MOUNT_NO_PERM	1 /* do not do client vfs_perm check */
+#define CIFS_MOUNT_NO_PERM      1 /* do not do client vfs_perm check */
 #define CIFS_MOUNT_SET_UID      2 /* set current->euid in create etc. */
+#define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/cifsfs.h	2004-11-09 00:24:22 -08:00
@@ -90,5 +90,5 @@
 			 size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION   "1.20"
+#define CIFS_VERSION   "1.24"
 #endif				/* _CIFSFS_H */
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/cifspdu.h	2004-11-09 00:24:22 -08:00
@@ -1351,6 +1351,8 @@
 #define SMB_QUERY_CIFS_UNIX_INFO    0x200
 #define SMB_QUERY_LABEL_INFO        0x3ea
 #define SMB_QUERY_FS_QUOTA_INFO     0x3ee
+#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
+#define SMB_QUERY_OBJECTID_INFO     0x3f0
 
 typedef struct smb_com_transaction2_qfsi_req {
 	struct smb_hdr hdr;	/* wct = 14+ */
@@ -1693,6 +1695,40 @@
 	__le32 FileNameLength;
 	char FileName[1];
 } FILE_DIRECTORY_INFO;   /* level 257 FF response data area */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
+	__le32 EaSize; /* length of the xattrs */
+	char FileName[1];
+} FILE_FULL_DIRECTORY_INFO;   /* level 258 FF response data area */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
+	__le32 EaSize; /* length of the xattrs */
+	__u8   ShortNameLength;
+	__u8   Reserved;
+	__u8   ShortName[12];
+	char FileName[1];
+} FILE_BOTH_DIRECTORY_INFO;   /* level 260 FF response data area */
+
 
 struct gea {
 	unsigned char name_len;
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/connect.c	2004-11-09 00:24:22 -08:00
@@ -69,6 +69,7 @@
 	unsigned intr:1;
 	unsigned setuids:1;
 	unsigned noperm:1;
+	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -742,6 +743,8 @@
 			/* ignore */
 		} else if (strnicmp(data, "version", 3) == 0) {
 			/* ignore */
+		} else if (strnicmp(data, "guest",5) == 0) {
+			/* ignore */
 		} else if (strnicmp(data, "rw", 2) == 0) {
 			vol->rw = TRUE;
 		} else if ((strnicmp(data, "suid", 4) == 0) ||
@@ -780,6 +783,10 @@
 			vol->intr = 0;
 		} else if (strnicmp(data, "intr", 4) == 0) {
 			vol->intr = 1;
+		} else if (strnicmp(data, "serverino",7) == 0) {
+			vol->server_ino = 1;
+		} else if (strnicmp(data, "noserverino",9) == 0) {
+			vol->server_ino = 0;
 		} else if (strnicmp(data, "noac", 4) == 0) {
 			printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
 		} else
@@ -1393,6 +1400,8 @@
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
 		if(volume_info.setuids)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+		if(volume_info.server_ino)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
 
 		tcon =
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
diff -Nru a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
--- a/fs/cifs/fcntl.c	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/fcntl.c	2004-11-09 00:24:22 -08:00
@@ -37,7 +37,7 @@
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
-    __u16 netfid;
+	__u16 netfid;
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/file.c	2004-11-09 00:24:22 -08:00
@@ -1376,23 +1376,22 @@
 	cFYI(0,
 	     ("CIFS FFIRST: Attributes came in as 0x%x",
 	      attr));
-	if (attr & ATTR_REPARSE) {
-		*pobject_type = DT_LNK;
-		/* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
-		tmp_inode->i_mode |= S_IFLNK;
-	} else if (attr & ATTR_DIRECTORY) {
+	if (attr & ATTR_DIRECTORY) {
 		*pobject_type = DT_DIR;
 		/* override default perms since we do not lock dirs */
 		if(atomic_read(&cifsInfo->inUse) == 0) {
 			tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
 		}
 		tmp_inode->i_mode |= S_IFDIR;
+/* we no longer mark these because we could not follow them */
+/*        } else if (attr & ATTR_REPARSE) {
+                *pobject_type = DT_LNK;
+                tmp_inode->i_mode |= S_IFLNK;*/
 	} else {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
 		if(attr & ATTR_READONLY)
 			tmp_inode->i_mode &= ~(S_IWUGO);
-
 	}/* could add code here - to validate if device or weird share type? */
 
 	/* can not fill in nlink here as in qpathinfo version and Unx search */
@@ -1516,13 +1515,16 @@
 	}
 }
 
-static void
+/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Might check in the future if inode number changed so we can rehash inode */
+static int
 construct_dentry(struct qstr *qstring, struct file *file,
 		 struct inode **ptmp_inode, struct dentry **pnew_dentry)
 {
 	struct dentry *tmp_dentry;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
+	int rc = 0;
 
 	cFYI(1, ("For %s ", qstring->name));
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1537,29 +1539,30 @@
 		if(*ptmp_inode == NULL) {
 	                *ptmp_inode = new_inode(file->f_dentry->d_sb);
 			if(*ptmp_inode == NULL)
-				return;
+				return rc;
+			rc = 1;
 			d_instantiate(tmp_dentry, *ptmp_inode);
-			insert_inode_hash(*ptmp_inode);
 		}
 	} else {
 		tmp_dentry = d_alloc(file->f_dentry, qstring);
 		if(tmp_dentry == NULL) {
 			cERROR(1,("Failed allocating dentry"));
 			*ptmp_inode = NULL;
-			return;
+			return rc;
 		}
 			
 		*ptmp_inode = new_inode(file->f_dentry->d_sb);
 		tmp_dentry->d_op = &cifs_dentry_ops;
 		if(*ptmp_inode == NULL)
-			return;
+			return rc;
+		rc = 1;
 		d_instantiate(tmp_dentry, *ptmp_inode);
 		d_rehash(tmp_dentry);
-		insert_inode_hash(*ptmp_inode);
 	}
 
 	tmp_dentry->d_time = jiffies;
 	*pnew_dentry = tmp_dentry;
+	return rc; 
 }
 
 static void reset_resume_key(struct file * dir_file, 
@@ -1609,11 +1612,19 @@
 	pqstring->name = pfindData->FileName;
 	/* pqstring->len is already set by caller */
 
-	construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+	rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
 	if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
 		return -ENOMEM;
 	}
 	fill_in_inode(tmp_inode, pfindData, &object_type);
+	if(rc) {
+		/* We have no reliable way to get inode numbers
+		from servers w/o Unix extensions yet so we can not set
+		i_ino from pfindData yet */
+
+		/* new inode created, let us hash it */
+		insert_inode_hash(tmp_inode);
+	} /* else if inode number changed do we rehash it? */
 	rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
 		tmp_inode->i_ino, object_type);
 	if(rc) {
@@ -1637,11 +1648,19 @@
 	pqstring->name = pUnixFindData->FileName;
 	pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
 
-	construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
+	rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
 	if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
 		return -ENOMEM;
-	}
+	} 
+	if(rc) {
+		struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
 
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+			tmp_inode->i_ino = 
+				(unsigned long)pUnixFindData->UniqueId;
+		}
+		insert_inode_hash(tmp_inode);
+	} /* else if i_ino has changed should we rehash it? */
 	unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
 	rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
 		file->f_pos, tmp_inode->i_ino, object_type);
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	2004-11-09 00:24:22 -08:00
+++ b/fs/cifs/inode.c	2004-11-09 00:24:22 -08:00
@@ -85,6 +85,13 @@
 			*pinode = new_inode(sb);
 			if(*pinode == NULL) 
 				return -ENOMEM;
+			/* Is an i_ino of zero legal? */
+			/* Are there sanity checks we can use to ensure that
+			the server is really filling in that field? */
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+				(*pinode)->i_ino = 
+					(unsigned long)findData.UniqueId;
+			} /* note ino incremented to unique num in new_inode */
 			insert_inode_hash(*pinode);
 		}
 			
@@ -244,6 +251,21 @@
 			*pinode = new_inode(sb);
 			if(*pinode == NULL)
 				return -ENOMEM;
+			/* Is an i_ino of zero legal? */
+			/* Are there sanity checks we can use to ensure that
+			the server is really filling in that field? */
+
+			/* We can not use the IndexNumber from either
+			Windows or Samba as it is frequently set to zero */
+			/* There may be higher info levels that work but
+			Are there Windows server or network appliances
+			for which IndexNumber field is not guaranteed unique? */
+		
+			/* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+				(*pinode)->i_ino = 
+					(unsigned long)pfindData->IndexNumber;
+			} */ /*NB: ino incremented to unique num in new_inode*/
+
 			insert_inode_hash(*pinode);
 		}
 		inode = *pinode;
@@ -273,10 +295,10 @@
 			/* new inode, can safely set these fields */
 			inode->i_mode = cifs_sb->mnt_file_mode;
 
-		if (attr & ATTR_REPARSE) {
-	/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
-			inode->i_mode |= S_IFLNK;
-		} else if (attr & ATTR_DIRECTORY) {
+/*		if (attr & ATTR_REPARSE)  */
+/* 		We no longer handle these as symlinks because we could not */
+/* 		follow them due to the absolute path with drive letter */
+		if (attr & ATTR_DIRECTORY) {
 	/* override default perms since we do not do byte range locking on dirs */
 			inode->i_mode = cifs_sb->mnt_dir_mode;
 			inode->i_mode |= S_IFDIR;
