aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r--fs/cifs/link.c97
1 files changed, 53 insertions, 44 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 6baea85d726e..41f657ced7ec 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -50,32 +50,32 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
50 50
51 fromName = build_path_from_dentry(old_file); 51 fromName = build_path_from_dentry(old_file);
52 toName = build_path_from_dentry(direntry); 52 toName = build_path_from_dentry(direntry);
53 if((fromName == NULL) || (toName == NULL)) { 53 if ((fromName == NULL) || (toName == NULL)) {
54 rc = -ENOMEM; 54 rc = -ENOMEM;
55 goto cifs_hl_exit; 55 goto cifs_hl_exit;
56 } 56 }
57 57
58 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) 58 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
59 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, 59 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
60 cifs_sb_target->local_nls, 60 cifs_sb_target->local_nls,
61 cifs_sb_target->mnt_cifs_flags & 61 cifs_sb_target->mnt_cifs_flags &
62 CIFS_MOUNT_MAP_SPECIAL_CHR); 62 CIFS_MOUNT_MAP_SPECIAL_CHR);
63 else { 63 else {
64 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, 64 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
65 cifs_sb_target->local_nls, 65 cifs_sb_target->local_nls,
66 cifs_sb_target->mnt_cifs_flags & 66 cifs_sb_target->mnt_cifs_flags &
67 CIFS_MOUNT_MAP_SPECIAL_CHR); 67 CIFS_MOUNT_MAP_SPECIAL_CHR);
68 if((rc == -EIO) || (rc == -EINVAL)) 68 if ((rc == -EIO) || (rc == -EINVAL))
69 rc = -EOPNOTSUPP; 69 rc = -EOPNOTSUPP;
70 } 70 }
71 71
72 d_drop(direntry); /* force new lookup from server of target */ 72 d_drop(direntry); /* force new lookup from server of target */
73 73
74 /* if source file is cached (oplocked) revalidate will not go to server 74 /* if source file is cached (oplocked) revalidate will not go to server
75 until the file is closed or oplock broken so update nlinks locally */ 75 until the file is closed or oplock broken so update nlinks locally */
76 if(old_file->d_inode) { 76 if (old_file->d_inode) {
77 cifsInode = CIFS_I(old_file->d_inode); 77 cifsInode = CIFS_I(old_file->d_inode);
78 if(rc == 0) { 78 if (rc == 0) {
79 old_file->d_inode->i_nlink++; 79 old_file->d_inode->i_nlink++;
80/* BB should we make this contingent on superblock flag NOATIME? */ 80/* BB should we make this contingent on superblock flag NOATIME? */
81/* old_file->d_inode->i_ctime = CURRENT_TIME;*/ 81/* old_file->d_inode->i_ctime = CURRENT_TIME;*/
@@ -84,14 +84,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
84 to set the parent dir cifs inode time to zero 84 to set the parent dir cifs inode time to zero
85 to force revalidate (faster) for it too? */ 85 to force revalidate (faster) for it too? */
86 } 86 }
87 /* if not oplocked will force revalidate to get info 87 /* if not oplocked will force revalidate to get info
88 on source file from srv */ 88 on source file from srv */
89 cifsInode->time = 0; 89 cifsInode->time = 0;
90 90
91 /* Will update parent dir timestamps from srv within a second. 91 /* Will update parent dir timestamps from srv within a second.
92 Would it really be worth it to set the parent dir (cifs 92 Would it really be worth it to set the parent dir (cifs
93 inode) time field to zero to force revalidate on parent 93 inode) time field to zero to force revalidate on parent
94 directory faster ie 94 directory faster ie
95 CIFS_I(inode)->time = 0; */ 95 CIFS_I(inode)->time = 0; */
96 } 96 }
97 97
@@ -109,7 +109,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
109 int rc = -EACCES; 109 int rc = -EACCES;
110 int xid; 110 int xid;
111 char *full_path = NULL; 111 char *full_path = NULL;
112 char * target_path = ERR_PTR(-ENOMEM); 112 char *target_path = ERR_PTR(-ENOMEM);
113 struct cifs_sb_info *cifs_sb; 113 struct cifs_sb_info *cifs_sb;
114 struct cifsTconInfo *pTcon; 114 struct cifsTconInfo *pTcon;
115 115
@@ -129,7 +129,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
129 goto out; 129 goto out;
130 } 130 }
131 131
132/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ 132 /* BB add read reparse point symlink code and Unix extensions
133 symlink code here BB */
133 if (pTcon->ses->capabilities & CAP_UNIX) 134 if (pTcon->ses->capabilities & CAP_UNIX)
134 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, 135 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
135 target_path, 136 target_path,
@@ -176,7 +177,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
176 177
177 full_path = build_path_from_dentry(direntry); 178 full_path = build_path_from_dentry(direntry);
178 179
179 if(full_path == NULL) { 180 if (full_path == NULL) {
180 FreeXid(xid); 181 FreeXid(xid);
181 return -ENOMEM; 182 return -ENOMEM;
182 } 183 }
@@ -189,15 +190,16 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
189 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 190 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
190 cifs_sb->local_nls); 191 cifs_sb->local_nls);
191 /* else 192 /* else
192 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */ 193 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
194 cifs_sb_target->local_nls); */
193 195
194 if (rc == 0) { 196 if (rc == 0) {
195 if (pTcon->ses->capabilities & CAP_UNIX) 197 if (pTcon->ses->capabilities & CAP_UNIX)
196 rc = cifs_get_inode_info_unix(&newinode, full_path, 198 rc = cifs_get_inode_info_unix(&newinode, full_path,
197 inode->i_sb,xid); 199 inode->i_sb, xid);
198 else 200 else
199 rc = cifs_get_inode_info(&newinode, full_path, NULL, 201 rc = cifs_get_inode_info(&newinode, full_path, NULL,
200 inode->i_sb,xid); 202 inode->i_sb, xid);
201 203
202 if (rc != 0) { 204 if (rc != 0) {
203 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d", 205 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
@@ -226,9 +228,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
226 struct cifs_sb_info *cifs_sb; 228 struct cifs_sb_info *cifs_sb;
227 struct cifsTconInfo *pTcon; 229 struct cifsTconInfo *pTcon;
228 char *full_path = NULL; 230 char *full_path = NULL;
229 char *tmp_path = NULL; 231 char *tmp_path = NULL;
230 char * tmpbuffer; 232 char *tmpbuffer;
231 unsigned char * referrals = NULL; 233 unsigned char *referrals = NULL;
232 int num_referrals = 0; 234 int num_referrals = 0;
233 int len; 235 int len;
234 __u16 fid; 236 __u16 fid;
@@ -237,13 +239,13 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
237 cifs_sb = CIFS_SB(inode->i_sb); 239 cifs_sb = CIFS_SB(inode->i_sb);
238 pTcon = cifs_sb->tcon; 240 pTcon = cifs_sb->tcon;
239 241
240/* BB would it be safe against deadlock to grab this sem 242/* BB would it be safe against deadlock to grab this sem
241 even though rename itself grabs the sem and calls lookup? */ 243 even though rename itself grabs the sem and calls lookup? */
242/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ 244/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
243 full_path = build_path_from_dentry(direntry); 245 full_path = build_path_from_dentry(direntry);
244/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ 246/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
245 247
246 if(full_path == NULL) { 248 if (full_path == NULL) {
247 FreeXid(xid); 249 FreeXid(xid);
248 return -ENOMEM; 250 return -ENOMEM;
249 } 251 }
@@ -251,70 +253,77 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
251 cFYI(1, 253 cFYI(1,
252 ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", 254 ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
253 full_path, inode, pBuffer, buflen)); 255 full_path, inode, pBuffer, buflen));
254 if(buflen > PATH_MAX) 256 if (buflen > PATH_MAX)
255 len = PATH_MAX; 257 len = PATH_MAX;
256 else 258 else
257 len = buflen; 259 len = buflen;
258 tmpbuffer = kmalloc(len,GFP_KERNEL); 260 tmpbuffer = kmalloc(len, GFP_KERNEL);
259 if(tmpbuffer == NULL) { 261 if (tmpbuffer == NULL) {
260 kfree(full_path); 262 kfree(full_path);
261 FreeXid(xid); 263 FreeXid(xid);
262 return -ENOMEM; 264 return -ENOMEM;
263 } 265 }
264 266
265/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ 267/* BB add read reparse point symlink code and
268 Unix extensions symlink code here BB */
266 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) 269 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
267 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, 270 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
268 tmpbuffer, 271 tmpbuffer,
269 len - 1, 272 len - 1,
270 cifs_sb->local_nls); 273 cifs_sb->local_nls);
271 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 274 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
272 cERROR(1,("SFU style symlinks not implemented yet")); 275 cERROR(1, ("SFU style symlinks not implemented yet"));
273 /* add open and read as in fs/cifs/inode.c */ 276 /* add open and read as in fs/cifs/inode.c */
274 277
275 } else { 278 } else {
276 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, 279 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
277 OPEN_REPARSE_POINT,&fid, &oplock, NULL, 280 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
278 cifs_sb->local_nls, 281 cifs_sb->local_nls,
279 cifs_sb->mnt_cifs_flags & 282 cifs_sb->mnt_cifs_flags &
280 CIFS_MOUNT_MAP_SPECIAL_CHR); 283 CIFS_MOUNT_MAP_SPECIAL_CHR);
281 if(!rc) { 284 if (!rc) {
282 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, 285 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
283 tmpbuffer, 286 tmpbuffer,
284 len - 1, 287 len - 1,
285 fid, 288 fid,
286 cifs_sb->local_nls); 289 cifs_sb->local_nls);
287 if(CIFSSMBClose(xid, pTcon, fid)) { 290 if (CIFSSMBClose(xid, pTcon, fid)) {
288 cFYI(1,("Error closing junction point (open for ioctl)")); 291 cFYI(1,("Error closing junction point (open for ioctl)"));
289 } 292 }
290 if(rc == -EIO) { 293 if (rc == -EIO) {
291 /* Query if DFS Junction */ 294 /* Query if DFS Junction */
292 tmp_path = 295 tmp_path =
293 kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, 296 kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
294 GFP_KERNEL); 297 GFP_KERNEL);
295 if (tmp_path) { 298 if (tmp_path) {
296 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); 299 strncpy(tmp_path, pTcon->treeName,
297 strncat(tmp_path, full_path, MAX_PATHCONF); 300 MAX_TREE_SIZE);
298 rc = get_dfs_path(xid, pTcon->ses, tmp_path, 301 strncat(tmp_path, full_path,
302 MAX_PATHCONF);
303 rc = get_dfs_path(xid, pTcon->ses,
304 tmp_path,
299 cifs_sb->local_nls, 305 cifs_sb->local_nls,
300 &num_referrals, &referrals, 306 &num_referrals, &referrals,
301 cifs_sb->mnt_cifs_flags & 307 cifs_sb->mnt_cifs_flags &
302 CIFS_MOUNT_MAP_SPECIAL_CHR); 308 CIFS_MOUNT_MAP_SPECIAL_CHR);
303 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); 309 cFYI(1, ("Get DFS for %s rc = %d ",
304 if((num_referrals == 0) && (rc == 0)) 310 tmp_path, rc));
311 if ((num_referrals == 0) && (rc == 0))
305 rc = -EACCES; 312 rc = -EACCES;
306 else { 313 else {
307 cFYI(1,("num referral: %d",num_referrals)); 314 cFYI(1, ("num referral: %d",
308 if(referrals) { 315 num_referrals));
309 cFYI(1,("referral string: %s",referrals)); 316 if (referrals) {
310 strncpy(tmpbuffer, referrals, len-1); 317 cFYI(1,("referral string: %s", referrals));
318 strncpy(tmpbuffer, referrals, len-1);
311 } 319 }
312 } 320 }
313 kfree(referrals); 321 kfree(referrals);
314 kfree(tmp_path); 322 kfree(tmp_path);
315} 323}
316 /* BB add code like else decode referrals then memcpy to 324 /* BB add code like else decode referrals
317 tmpbuffer and free referrals string array BB */ 325 then memcpy to tmpbuffer and free referrals
326 string array BB */
318 } 327 }
319 } 328 }
320 } 329 }