aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/link.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-09-29 19:51:11 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-06 12:12:44 -0400
commit7ffec372458d163492e56e663a1b3a2d7be0a0a2 (patch)
treee404e3d1000ff41e9b27d0ecb4d6a47187e110d7 /fs/cifs/link.c
parentf3983c2133e9bea9c8b4f690737d15e3e9b02491 (diff)
cifs: add refcounted and timestamped container for holding tcons
Eventually, we'll need to track the use of tcons on a per-sb basis, so that we know when it's ok to tear them down. Begin this conversion by adding a new "tcon_link" struct and accessors that get it. For now, the core data structures are untouched -- cifs_sb still just points to a single tcon and the pointers are just cast to deal with the accessor functions. A later patch will flesh this out. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r--fs/cifs/link.c87
1 files changed, 58 insertions, 29 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 66db2d61fa43..b38fe6704ad2 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -249,7 +249,8 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
249 int rc; 249 int rc;
250 int oplock = 0; 250 int oplock = 0;
251 __u16 netfid = 0; 251 __u16 netfid = 0;
252 struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); 252 struct tcon_link *tlink;
253 struct cifsTconInfo *pTcon;
253 u8 *buf; 254 u8 *buf;
254 char *pbuf; 255 char *pbuf;
255 unsigned int bytes_read = 0; 256 unsigned int bytes_read = 0;
@@ -261,23 +262,30 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
261 /* it's not a symlink */ 262 /* it's not a symlink */
262 return 0; 263 return 0;
263 264
265 tlink = cifs_sb_tlink(cifs_sb);
266 if (IS_ERR(tlink))
267 return PTR_ERR(tlink);
268 pTcon = tlink_tcon(tlink);
269
264 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, 270 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
265 CREATE_NOT_DIR, &netfid, &oplock, &file_info, 271 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
266 cifs_sb->local_nls, 272 cifs_sb->local_nls,
267 cifs_sb->mnt_cifs_flags & 273 cifs_sb->mnt_cifs_flags &
268 CIFS_MOUNT_MAP_SPECIAL_CHR); 274 CIFS_MOUNT_MAP_SPECIAL_CHR);
269 if (rc != 0) 275 if (rc != 0)
270 return rc; 276 goto out;
271 277
272 if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) { 278 if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
273 CIFSSMBClose(xid, pTcon, netfid); 279 CIFSSMBClose(xid, pTcon, netfid);
274 /* it's not a symlink */ 280 /* it's not a symlink */
275 return 0; 281 goto out;
276 } 282 }
277 283
278 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 284 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
279 if (!buf) 285 if (!buf) {
280 return -ENOMEM; 286 rc = -ENOMEM;
287 goto out;
288 }
281 pbuf = buf; 289 pbuf = buf;
282 290
283 rc = CIFSSMBRead(xid, pTcon, netfid, 291 rc = CIFSSMBRead(xid, pTcon, netfid,
@@ -287,23 +295,28 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
287 CIFSSMBClose(xid, pTcon, netfid); 295 CIFSSMBClose(xid, pTcon, netfid);
288 if (rc != 0) { 296 if (rc != 0) {
289 kfree(buf); 297 kfree(buf);
290 return rc; 298 goto out;
291 } 299 }
292 300
293 rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); 301 rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
294 kfree(buf); 302 kfree(buf);
295 if (rc == -EINVAL) 303 if (rc == -EINVAL) {
296 /* it's not a symlink */ 304 /* it's not a symlink */
297 return 0; 305 rc = 0;
306 goto out;
307 }
308
298 if (rc != 0) 309 if (rc != 0)
299 return rc; 310 goto out;
300 311
301 /* it is a symlink */ 312 /* it is a symlink */
302 fattr->cf_eof = link_len; 313 fattr->cf_eof = link_len;
303 fattr->cf_mode &= ~S_IFMT; 314 fattr->cf_mode &= ~S_IFMT;
304 fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; 315 fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
305 fattr->cf_dtype = DT_LNK; 316 fattr->cf_dtype = DT_LNK;
306 return 0; 317out:
318 cifs_put_tlink(tlink);
319 return rc;
307} 320}
308 321
309int 322int
@@ -314,17 +327,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
314 int xid; 327 int xid;
315 char *fromName = NULL; 328 char *fromName = NULL;
316 char *toName = NULL; 329 char *toName = NULL;
317 struct cifs_sb_info *cifs_sb_target; 330 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
331 struct tcon_link *tlink;
318 struct cifsTconInfo *pTcon; 332 struct cifsTconInfo *pTcon;
319 struct cifsInodeInfo *cifsInode; 333 struct cifsInodeInfo *cifsInode;
320 334
321 xid = GetXid(); 335 tlink = cifs_sb_tlink(cifs_sb);
322 336 if (IS_ERR(tlink))
323 cifs_sb_target = CIFS_SB(inode->i_sb); 337 return PTR_ERR(tlink);
324 pTcon = cifs_sb_tcon(cifs_sb_target); 338 pTcon = tlink_tcon(tlink);
325 339
326/* No need to check for cross device links since server will do that 340 xid = GetXid();
327 BB note DFS case in future though (when we may have to check) */
328 341
329 fromName = build_path_from_dentry(old_file); 342 fromName = build_path_from_dentry(old_file);
330 toName = build_path_from_dentry(direntry); 343 toName = build_path_from_dentry(direntry);
@@ -336,13 +349,13 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
336/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/ 349/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
337 if (pTcon->unix_ext) 350 if (pTcon->unix_ext)
338 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, 351 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
339 cifs_sb_target->local_nls, 352 cifs_sb->local_nls,
340 cifs_sb_target->mnt_cifs_flags & 353 cifs_sb->mnt_cifs_flags &
341 CIFS_MOUNT_MAP_SPECIAL_CHR); 354 CIFS_MOUNT_MAP_SPECIAL_CHR);
342 else { 355 else {
343 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, 356 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
344 cifs_sb_target->local_nls, 357 cifs_sb->local_nls,
345 cifs_sb_target->mnt_cifs_flags & 358 cifs_sb->mnt_cifs_flags &
346 CIFS_MOUNT_MAP_SPECIAL_CHR); 359 CIFS_MOUNT_MAP_SPECIAL_CHR);
347 if ((rc == -EIO) || (rc == -EINVAL)) 360 if ((rc == -EIO) || (rc == -EINVAL))
348 rc = -EOPNOTSUPP; 361 rc = -EOPNOTSUPP;
@@ -378,6 +391,7 @@ cifs_hl_exit:
378 kfree(fromName); 391 kfree(fromName);
379 kfree(toName); 392 kfree(toName);
380 FreeXid(xid); 393 FreeXid(xid);
394 cifs_put_tlink(tlink);
381 return rc; 395 return rc;
382} 396}
383 397
@@ -390,10 +404,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
390 char *full_path = NULL; 404 char *full_path = NULL;
391 char *target_path = NULL; 405 char *target_path = NULL;
392 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 406 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
393 struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); 407 struct tcon_link *tlink = NULL;
408 struct cifsTconInfo *tcon;
394 409
395 xid = GetXid(); 410 xid = GetXid();
396 411
412 tlink = cifs_sb_tlink(cifs_sb);
413 if (IS_ERR(tlink)) {
414 rc = PTR_ERR(tlink);
415 tlink = NULL;
416 goto out;
417 }
418 tcon = tlink_tcon(tlink);
419
397 /* 420 /*
398 * For now, we just handle symlinks with unix extensions enabled. 421 * For now, we just handle symlinks with unix extensions enabled.
399 * Eventually we should handle NTFS reparse points, and MacOS 422 * Eventually we should handle NTFS reparse points, and MacOS
@@ -442,6 +465,8 @@ out:
442 } 465 }
443 466
444 FreeXid(xid); 467 FreeXid(xid);
468 if (tlink)
469 cifs_put_tlink(tlink);
445 nd_set_link(nd, target_path); 470 nd_set_link(nd, target_path);
446 return NULL; 471 return NULL;
447} 472}
@@ -451,22 +476,25 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
451{ 476{
452 int rc = -EOPNOTSUPP; 477 int rc = -EOPNOTSUPP;
453 int xid; 478 int xid;
454 struct cifs_sb_info *cifs_sb; 479 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
480 struct tcon_link *tlink;
455 struct cifsTconInfo *pTcon; 481 struct cifsTconInfo *pTcon;
456 char *full_path = NULL; 482 char *full_path = NULL;
457 struct inode *newinode = NULL; 483 struct inode *newinode = NULL;
458 484
459 xid = GetXid(); 485 xid = GetXid();
460 486
461 cifs_sb = CIFS_SB(inode->i_sb); 487 tlink = cifs_sb_tlink(cifs_sb);
462 pTcon = cifs_sb_tcon(cifs_sb); 488 if (IS_ERR(tlink)) {
489 rc = PTR_ERR(tlink);
490 goto symlink_exit;
491 }
492 pTcon = tlink_tcon(tlink);
463 493
464 full_path = build_path_from_dentry(direntry); 494 full_path = build_path_from_dentry(direntry);
465
466 if (full_path == NULL) { 495 if (full_path == NULL) {
467 rc = -ENOMEM; 496 rc = -ENOMEM;
468 FreeXid(xid); 497 goto symlink_exit;
469 return rc;
470 } 498 }
471 499
472 cFYI(1, "Full path: %s", full_path); 500 cFYI(1, "Full path: %s", full_path);
@@ -504,8 +532,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
504 d_instantiate(direntry, newinode); 532 d_instantiate(direntry, newinode);
505 } 533 }
506 } 534 }
507 535symlink_exit:
508 kfree(full_path); 536 kfree(full_path);
537 cifs_put_tlink(tlink);
509 FreeXid(xid); 538 FreeXid(xid);
510 return rc; 539 return rc;
511} 540}