diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-09-29 19:51:11 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-06 12:12:44 -0400 |
commit | 7ffec372458d163492e56e663a1b3a2d7be0a0a2 (patch) | |
tree | e404e3d1000ff41e9b27d0ecb4d6a47187e110d7 /fs/cifs/link.c | |
parent | f3983c2133e9bea9c8b4f690737d15e3e9b02491 (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.c | 87 |
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; | 317 | out: |
318 | cifs_put_tlink(tlink); | ||
319 | return rc; | ||
307 | } | 320 | } |
308 | 321 | ||
309 | int | 322 | int |
@@ -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 | 535 | symlink_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 | } |