aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-05-20 15:50:46 -0400
committerSteve French <sfrench@us.ibm.com>2008-05-20 15:50:46 -0400
commit0e4bbde94fdc33f5b3d793166b21bf768ca3e098 (patch)
tree858cc58dcd5b49de3611826cf5e57ae5d54345ed
parent89562b777c50d100d1694db7b1b023279839b9ae (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>
-rw-r--r--fs/cifs/AUTHORS1
-rw-r--r--fs/cifs/CHANGES2
-rw-r--r--fs/cifs/TODO15
-rw-r--r--fs/cifs/inode.c117
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
36Kazeon team for various fixes especially for 2.4 version. 36Kazeon team for various fixes especially for 2.4 version.
37Asser Ferno (Change Notify support) 37Asser Ferno (Change Notify support)
38Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup 38Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
39Igor Mammedov (DFS support)
39 40
40Test case and Bug Report contributors 41Test 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 @@
1Version 1.53 1Version 1.53
2------------ 2------------
3DFS support added (Microsoft Distributed File System client support needed
4for referrals which enable a hierarchical name space among servers).
3 5
4Version 1.52 6Version 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 @@
1Version 1.52 January 3, 2008 1Version 1.53 May 20, 2008
2 2
3A Partial List of Missing Features 3A Partial List of Missing Features
4================================== 4==================================
@@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in
20fs/cifs/connect.c and add back in NTLMSSP code if any servers 20fs/cifs/connect.c and add back in NTLMSSP code if any servers
21need it 21need it
22 22
23e) ms-dfs and ms-dfs host name resolution cleanup 23e) fix NTLMv2 signing when two mounts with different users to same
24
25f) fix NTLMv2 signing when two mounts with different users to same
26server. 24server.
27 25
28g) Directory entry caching relies on a 1 second timer, rather than 26f) Directory entry caching relies on a 1 second timer, rather than
29using FindNotify or equivalent. - (started) 27using FindNotify or equivalent. - (started)
30 28
31h) quota support (needs minor kernel change since quota calls 29g) quota support (needs minor kernel change since quota calls
32to make it to network filesystems or deviceless filesystems) 30to make it to network filesystems or deviceless filesystems)
33 31
34i) investigate sync behavior (including syncpage) and check 32h) investigate sync behavior (including syncpage) and check
35for proper behavior of intr/nointr 33for proper behavior of intr/nointr
36 34
35i) improve support for very old servers (OS/2 and Win9x for example)
36Including support for changing the time remotely (utimes command).
37
37j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the 38j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
38extra copy in/out of the socket buffers in some cases. 39extra 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
164static 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
164int cifs_get_inode_info_unix(struct inode **pinode, 196int 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
177try_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);
235cgiiu_exit: 266cgiiu_exit:
236 return rc; 267 return rc;
237} 268}