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 | |||
| 36 | Kazeon team for various fixes especially for 2.4 version. | 36 | Kazeon team for various fixes especially for 2.4 version. |
| 37 | Asser Ferno (Change Notify support) | 37 | Asser Ferno (Change Notify support) |
| 38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup | 38 | Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup |
| 39 | Igor Mammedov (DFS support) | ||
| 39 | 40 | ||
| 40 | Test case and Bug Report contributors | 41 | Test case and Bug Report contributors |
| 41 | ------------------------------------- | 42 | ------------------------------------- |
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 @@ | |||
| 1 | Version 1.53 | 1 | Version 1.53 |
| 2 | ------------ | 2 | ------------ |
| 3 | DFS support added (Microsoft Distributed File System client support needed | ||
| 4 | for referrals which enable a hierarchical name space among servers). | ||
| 3 | 5 | ||
| 4 | Version 1.52 | 6 | Version 1.52 |
| 5 | ------------ | 7 | ------------ |
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 @@ | |||
| 1 | Version 1.52 January 3, 2008 | 1 | Version 1.53 May 20, 2008 |
| 2 | 2 | ||
| 3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
| 4 | ================================== | 4 | ================================== |
| @@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in | |||
| 20 | fs/cifs/connect.c and add back in NTLMSSP code if any servers | 20 | fs/cifs/connect.c and add back in NTLMSSP code if any servers |
| 21 | need it | 21 | need it |
| 22 | 22 | ||
| 23 | e) ms-dfs and ms-dfs host name resolution cleanup | 23 | e) fix NTLMv2 signing when two mounts with different users to same |
| 24 | |||
| 25 | f) fix NTLMv2 signing when two mounts with different users to same | ||
| 26 | server. | 24 | server. |
| 27 | 25 | ||
| 28 | g) Directory entry caching relies on a 1 second timer, rather than | 26 | f) Directory entry caching relies on a 1 second timer, rather than |
| 29 | using FindNotify or equivalent. - (started) | 27 | using FindNotify or equivalent. - (started) |
| 30 | 28 | ||
| 31 | h) quota support (needs minor kernel change since quota calls | 29 | g) quota support (needs minor kernel change since quota calls |
| 32 | to make it to network filesystems or deviceless filesystems) | 30 | to make it to network filesystems or deviceless filesystems) |
| 33 | 31 | ||
| 34 | i) investigate sync behavior (including syncpage) and check | 32 | h) investigate sync behavior (including syncpage) and check |
| 35 | for proper behavior of intr/nointr | 33 | for proper behavior of intr/nointr |
| 36 | 34 | ||
| 35 | i) improve support for very old servers (OS/2 and Win9x for example) | ||
| 36 | Including support for changing the time remotely (utimes command). | ||
| 37 | |||
| 37 | j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the | 38 | j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the |
| 38 | extra copy in/out of the socket buffers in some cases. | 39 | extra copy in/out of the socket buffers in some cases. |
| 39 | 40 | ||
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, | |||
| 161 | spin_unlock(&inode->i_lock); | 161 | spin_unlock(&inode->i_lock); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | ||
| 165 | struct super_block *sb) | ||
| 166 | { | ||
| 167 | struct inode *pinode = NULL; | ||
| 168 | |||
| 169 | memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); | ||
| 170 | |||
| 171 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
| 172 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | ||
| 173 | __u64 UniqueId = 0; */ | ||
| 174 | pfnd_dat->LastStatusChange = | ||
| 175 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 176 | pfnd_dat->LastAccessTime = | ||
| 177 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 178 | pfnd_dat->LastModificationTime = | ||
| 179 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 180 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | ||
| 181 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | ||
| 182 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
| 183 | if (sb->s_root) | ||
| 184 | pinode = sb->s_root->d_inode; | ||
| 185 | if (pinode == NULL) | ||
| 186 | return; | ||
| 187 | |||
| 188 | /* fill in default values for the remaining based on root | ||
| 189 | inode since we can not query the server for this inode info */ | ||
| 190 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); | ||
| 191 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); | ||
| 192 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); | ||
| 193 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | ||
| 194 | } | ||
| 195 | |||
| 164 | int cifs_get_inode_info_unix(struct inode **pinode, | 196 | int cifs_get_inode_info_unix(struct inode **pinode, |
| 165 | const unsigned char *full_path, struct super_block *sb, int xid) | 197 | const unsigned char *full_path, struct super_block *sb, int xid) |
| 166 | { | 198 | { |
| 167 | int rc = 0; | 199 | int rc = 0; |
| 168 | FILE_UNIX_BASIC_INFO findData; | 200 | FILE_UNIX_BASIC_INFO find_data; |
| 169 | struct cifsTconInfo *pTcon; | 201 | struct cifsTconInfo *pTcon; |
| 170 | struct inode *inode; | 202 | struct inode *inode; |
| 171 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 203 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 172 | bool is_dfs_referral = false; | 204 | bool is_dfs_referral = false; |
| 205 | struct cifsInodeInfo *cifsInfo; | ||
| 206 | __u64 num_of_bytes; | ||
| 207 | __u64 end_of_file; | ||
| 173 | 208 | ||
| 174 | pTcon = cifs_sb->tcon; | 209 | pTcon = cifs_sb->tcon; |
| 175 | cFYI(1, ("Getting info on %s", full_path)); | 210 | cFYI(1, ("Getting info on %s", full_path)); |
| 176 | 211 | ||
| 177 | try_again_CIFSSMBUnixQPathInfo: | ||
| 178 | /* could have done a find first instead but this returns more info */ | 212 | /* could have done a find first instead but this returns more info */ |
| 179 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, | 213 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, |
| 180 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 214 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 181 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 215 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 182 | /* dump_mem("\nUnixQPathInfo return data", &findData, | ||
| 183 | sizeof(findData)); */ | ||
| 184 | if (rc) { | 216 | if (rc) { |
| 185 | if (rc == -EREMOTE && !is_dfs_referral) { | 217 | if (rc == -EREMOTE && !is_dfs_referral) { |
| 186 | is_dfs_referral = true; | 218 | is_dfs_referral = true; |
| 187 | goto try_again_CIFSSMBUnixQPathInfo; | 219 | cERROR(1, ("DFS ref")); /* BB removeme BB */ |
| 220 | /* for DFS, server does not give us real inode data */ | ||
| 221 | fill_fake_finddataunix(&find_data, sb); | ||
| 222 | rc = 0; | ||
| 188 | } | 223 | } |
| 189 | goto cgiiu_exit; | 224 | } |
| 190 | } else { | 225 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); |
| 191 | struct cifsInodeInfo *cifsInfo; | 226 | end_of_file = le64_to_cpu(find_data.EndOfFile); |
| 192 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | ||
| 193 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); | ||
| 194 | 227 | ||
| 195 | /* get new inode */ | 228 | /* get new inode */ |
| 229 | if (*pinode == NULL) { | ||
| 230 | *pinode = new_inode(sb); | ||
| 196 | if (*pinode == NULL) { | 231 | if (*pinode == NULL) { |
| 197 | *pinode = new_inode(sb); | 232 | rc = -ENOMEM; |
| 198 | if (*pinode == NULL) { | 233 | goto cgiiu_exit; |
| 199 | rc = -ENOMEM; | ||
| 200 | goto cgiiu_exit; | ||
| 201 | } | ||
| 202 | /* Is an i_ino of zero legal? */ | ||
| 203 | /* Are there sanity checks we can use to ensure that | ||
| 204 | the server is really filling in that field? */ | ||
| 205 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | ||
| 206 | (*pinode)->i_ino = | ||
| 207 | (unsigned long)findData.UniqueId; | ||
| 208 | } /* note ino incremented to unique num in new_inode */ | ||
| 209 | if (sb->s_flags & MS_NOATIME) | ||
| 210 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
| 211 | |||
| 212 | insert_inode_hash(*pinode); | ||
| 213 | } | 234 | } |
| 235 | /* Is an i_ino of zero legal? */ | ||
| 236 | /* note ino incremented to unique num in new_inode */ | ||
| 237 | /* Are there sanity checks we can use to ensure that | ||
| 238 | the server is really filling in that field? */ | ||
| 239 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
| 240 | (*pinode)->i_ino = (unsigned long)find_data.UniqueId; | ||
| 214 | 241 | ||
| 215 | inode = *pinode; | 242 | if (sb->s_flags & MS_NOATIME) |
| 216 | cifsInfo = CIFS_I(inode); | 243 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; |
| 217 | 244 | ||
| 218 | cFYI(1, ("Old time %ld", cifsInfo->time)); | 245 | insert_inode_hash(*pinode); |
| 219 | cifsInfo->time = jiffies; | 246 | } |
| 220 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
| 221 | /* this is ok to set on every inode revalidate */ | ||
| 222 | atomic_set(&cifsInfo->inUse, 1); | ||
| 223 | 247 | ||
| 224 | cifs_unix_info_to_inode(inode, &findData, 0); | 248 | inode = *pinode; |
| 249 | cifsInfo = CIFS_I(inode); | ||
| 225 | 250 | ||
| 251 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
| 252 | cifsInfo->time = jiffies; | ||
| 253 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
| 254 | /* this is ok to set on every inode revalidate */ | ||
| 255 | atomic_set(&cifsInfo->inUse, 1); | ||
| 226 | 256 | ||
| 227 | if (num_of_bytes < end_of_file) | 257 | cifs_unix_info_to_inode(inode, &find_data, 0); |
| 228 | cFYI(1, ("allocation size less than end of file")); | ||
| 229 | cFYI(1, ("Size %ld and blocks %llu", | ||
| 230 | (unsigned long) inode->i_size, | ||
| 231 | (unsigned long long)inode->i_blocks)); | ||
| 232 | 258 | ||
| 233 | cifs_set_ops(inode, is_dfs_referral); | 259 | if (num_of_bytes < end_of_file) |
| 234 | } | 260 | cFYI(1, ("allocation size less than end of file")); |
| 261 | cFYI(1, ("Size %ld and blocks %llu", | ||
| 262 | (unsigned long) inode->i_size, | ||
| 263 | (unsigned long long)inode->i_blocks)); | ||
| 264 | |||
| 265 | cifs_set_ops(inode, is_dfs_referral); | ||
| 235 | cgiiu_exit: | 266 | cgiiu_exit: |
| 236 | return rc; | 267 | return rc; |
| 237 | } | 268 | } |
