diff options
author | Steve French <sfrench@us.ibm.com> | 2008-05-20 15:50:46 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-05-20 15:50:46 -0400 |
commit | 0e4bbde94fdc33f5b3d793166b21bf768ca3e098 (patch) | |
tree | 858cc58dcd5b49de3611826cf5e57ae5d54345ed /fs/cifs | |
parent | 89562b777c50d100d1694db7b1b023279839b9ae (diff) |
[CIFS] Enable DFS support for Unix query path info
Final piece for handling DFS in unix_query_path_info, constructing a
fake inode for the junction directory which the submount will cover.
Acked-by: Igor Mammedov <niallain@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-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 | } |