diff options
| -rw-r--r-- | fs/cifs/AUTHORS | 1 | ||||
| -rw-r--r-- | fs/cifs/CHANGES | 2 | ||||
| -rw-r--r-- | fs/cifs/TODO | 15 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 117 | 
4 files changed, 85 insertions, 50 deletions
| diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 8848e4dfa026..9c136d7803d9 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -36,6 +36,7 @@ Miklos Szeredi  Kazeon team for various fixes especially for 2.4 version.  Asser Ferno (Change Notify support)  Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup +Igor Mammedov (DFS support)  Test case and Bug Report contributors  ------------------------------------- diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 502a4c2b8414..28e3d5c5fcac 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,5 +1,7 @@  Version 1.53  ------------ +DFS support added (Microsoft Distributed File System client support needed +for referrals which enable a hierarchical name space among servers).  Version 1.52  ------------ diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 92c9feac440f..5aff46c61e52 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -Version 1.52 January 3, 2008 +Version 1.53 May 20, 2008  A Partial List of Missing Features  ================================== @@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in  fs/cifs/connect.c and add back in NTLMSSP code if any servers  need it -e) ms-dfs and ms-dfs host name resolution cleanup - -f) fix NTLMv2 signing when two mounts with different users to same +e) fix NTLMv2 signing when two mounts with different users to same  server. -g) Directory entry caching relies on a 1 second timer, rather than  +f) Directory entry caching relies on a 1 second timer, rather than   using FindNotify or equivalent.  - (started) -h) quota support (needs minor kernel change since quota calls +g) quota support (needs minor kernel change since quota calls  to make it to network filesystems or deviceless filesystems) -i) investigate sync behavior (including syncpage) and check   +h) investigate sync behavior (including syncpage) and check    for proper behavior of intr/nointr +i) improve support for very old servers (OS/2 and Win9x for example) +Including support for changing the time remotely (utimes command). +  j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the  extra copy in/out of the socket buffers in some cases. diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9d9b56a9c08e..422d4e219fa4 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -161,77 +161,108 @@ static void cifs_unix_info_to_inode(struct inode *inode,  	spin_unlock(&inode->i_lock);  } +static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, +			       struct super_block *sb) +{ +	struct inode *pinode = NULL; + +	memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); + +/*	__le64 pfnd_dat->EndOfFile = cpu_to_le64(0); +	__le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); +	__u64 UniqueId = 0;  */ +	pfnd_dat->LastStatusChange = +		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); +	pfnd_dat->LastAccessTime = +		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); +	pfnd_dat->LastModificationTime = +		cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); +	pfnd_dat->Type = cpu_to_le32(UNIX_DIR); +	pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); +	pfnd_dat->Nlinks = cpu_to_le64(2); +	if (sb->s_root) +		pinode = sb->s_root->d_inode; +	if (pinode == NULL) +		return; + +	/* fill in default values for the remaining based on root +	   inode since we can not query the server for this inode info */ +	pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); +	pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); +	pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); +	pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); +} +  int cifs_get_inode_info_unix(struct inode **pinode,  	const unsigned char *full_path, struct super_block *sb, int xid)  {  	int rc = 0; -	FILE_UNIX_BASIC_INFO findData; +	FILE_UNIX_BASIC_INFO find_data;  	struct cifsTconInfo *pTcon;  	struct inode *inode;  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);  	bool is_dfs_referral = false; +	struct cifsInodeInfo *cifsInfo; +	__u64 num_of_bytes; +	__u64 end_of_file;  	pTcon = cifs_sb->tcon;  	cFYI(1, ("Getting info on %s", full_path)); -try_again_CIFSSMBUnixQPathInfo:  	/* could have done a find first instead but this returns more info */ -	rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, +	rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,  				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &  					CIFS_MOUNT_MAP_SPECIAL_CHR); -/*	dump_mem("\nUnixQPathInfo return data", &findData, -		 sizeof(findData)); */  	if (rc) {  		if (rc == -EREMOTE && !is_dfs_referral) {  			is_dfs_referral = true; -			goto try_again_CIFSSMBUnixQPathInfo; +			cERROR(1, ("DFS ref")); /* BB removeme BB */ +			/* for DFS, server does not give us real inode data */ +			fill_fake_finddataunix(&find_data, sb); +			rc = 0;  		} -		goto cgiiu_exit; -	} else { -		struct cifsInodeInfo *cifsInfo; -		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); -		__u64 end_of_file = le64_to_cpu(findData.EndOfFile); +	} +	num_of_bytes = le64_to_cpu(find_data.NumOfBytes); +	end_of_file = le64_to_cpu(find_data.EndOfFile); -		/* get new inode */ +	/* get new inode */ +	if (*pinode == NULL) { +		*pinode = new_inode(sb);  		if (*pinode == NULL) { -			*pinode = new_inode(sb); -			if (*pinode == NULL) { -				rc = -ENOMEM; -				goto cgiiu_exit; -			} -			/* 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 */ -			if (sb->s_flags & MS_NOATIME) -				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; - -			insert_inode_hash(*pinode); +			rc = -ENOMEM; +		goto cgiiu_exit;  		} +		/* Is an i_ino of zero legal? */ +		/* note ino incremented to unique num in new_inode */ +		/* 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)find_data.UniqueId; -		inode = *pinode; -		cifsInfo = CIFS_I(inode); +		if (sb->s_flags & MS_NOATIME) +			(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; -		cFYI(1, ("Old time %ld", cifsInfo->time)); -		cifsInfo->time = jiffies; -		cFYI(1, ("New time %ld", cifsInfo->time)); -		/* this is ok to set on every inode revalidate */ -		atomic_set(&cifsInfo->inUse, 1); +		insert_inode_hash(*pinode); +	} -		cifs_unix_info_to_inode(inode, &findData, 0); +	inode = *pinode; +	cifsInfo = CIFS_I(inode); +	cFYI(1, ("Old time %ld", cifsInfo->time)); +	cifsInfo->time = jiffies; +	cFYI(1, ("New time %ld", cifsInfo->time)); +	/* this is ok to set on every inode revalidate */ +	atomic_set(&cifsInfo->inUse, 1); -		if (num_of_bytes < end_of_file) -			cFYI(1, ("allocation size less than end of file")); -		cFYI(1, ("Size %ld and blocks %llu", -			(unsigned long) inode->i_size, -			(unsigned long long)inode->i_blocks)); +	cifs_unix_info_to_inode(inode, &find_data, 0); -		cifs_set_ops(inode, is_dfs_referral); -	} +	if (num_of_bytes < end_of_file) +		cFYI(1, ("allocation size less than end of file")); +	cFYI(1, ("Size %ld and blocks %llu", +		(unsigned long) inode->i_size, +		(unsigned long long)inode->i_blocks)); + +	cifs_set_ops(inode, is_dfs_referral);  cgiiu_exit:  	return rc;  } |