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 | |
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')
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 21 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 42 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 51 | ||||
-rw-r--r-- | fs/cifs/dir.c | 65 | ||||
-rw-r--r-- | fs/cifs/file.c | 9 | ||||
-rw-r--r-- | fs/cifs/inode.c | 157 | ||||
-rw-r--r-- | fs/cifs/link.c | 87 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 32 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 60 |
9 files changed, 376 insertions, 148 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f1e13ea45a17..f4aab6f01174 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -306,6 +306,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
306 | int xid, i; | 306 | int xid, i; |
307 | int rc = 0; | 307 | int rc = 0; |
308 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 308 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
309 | struct tcon_link *tlink; | ||
309 | 310 | ||
310 | cFYI(1, "in %s", __func__); | 311 | cFYI(1, "in %s", __func__); |
311 | BUG_ON(IS_ROOT(dentry)); | 312 | BUG_ON(IS_ROOT(dentry)); |
@@ -315,14 +316,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
315 | dput(nd->path.dentry); | 316 | dput(nd->path.dentry); |
316 | nd->path.dentry = dget(dentry); | 317 | nd->path.dentry = dget(dentry); |
317 | 318 | ||
318 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); | ||
319 | ses = cifs_sb_tcon(cifs_sb)->ses; | ||
320 | |||
321 | if (!ses) { | ||
322 | rc = -EINVAL; | ||
323 | goto out_err; | ||
324 | } | ||
325 | |||
326 | /* | 319 | /* |
327 | * The MSDFS spec states that paths in DFS referral requests and | 320 | * The MSDFS spec states that paths in DFS referral requests and |
328 | * responses must be prefixed by a single '\' character instead of | 321 | * responses must be prefixed by a single '\' character instead of |
@@ -335,10 +328,20 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
335 | goto out_err; | 328 | goto out_err; |
336 | } | 329 | } |
337 | 330 | ||
338 | rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls, | 331 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); |
332 | tlink = cifs_sb_tlink(cifs_sb); | ||
333 | if (IS_ERR(tlink)) { | ||
334 | rc = PTR_ERR(tlink); | ||
335 | goto out_err; | ||
336 | } | ||
337 | ses = tlink_tcon(tlink)->ses; | ||
338 | |||
339 | rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, | ||
339 | &num_referrals, &referrals, | 340 | &num_referrals, &referrals, |
340 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 341 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
341 | 342 | ||
343 | cifs_put_tlink(tlink); | ||
344 | |||
342 | for (i = 0; i < num_referrals; i++) { | 345 | for (i = 0; i < num_referrals; i++) { |
343 | int len; | 346 | int len; |
344 | dump_referral(referrals+i); | 347 | dump_referral(referrals+i); |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 32f244909a0d..2647ea410c4c 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -557,11 +557,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
557 | { | 557 | { |
558 | struct cifs_ntsd *pntsd = NULL; | 558 | struct cifs_ntsd *pntsd = NULL; |
559 | int xid, rc; | 559 | int xid, rc; |
560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
561 | |||
562 | if (IS_ERR(tlink)) | ||
563 | return NULL; | ||
560 | 564 | ||
561 | xid = GetXid(); | 565 | xid = GetXid(); |
562 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen); | 566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); |
563 | FreeXid(xid); | 567 | FreeXid(xid); |
564 | 568 | ||
569 | cifs_put_tlink(tlink); | ||
565 | 570 | ||
566 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | 571 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); |
567 | return pntsd; | 572 | return pntsd; |
@@ -574,10 +579,16 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
574 | int oplock = 0; | 579 | int oplock = 0; |
575 | int xid, rc; | 580 | int xid, rc; |
576 | __u16 fid; | 581 | __u16 fid; |
582 | struct cifsTconInfo *tcon; | ||
583 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
584 | |||
585 | if (IS_ERR(tlink)) | ||
586 | return NULL; | ||
577 | 587 | ||
588 | tcon = tlink_tcon(tlink); | ||
578 | xid = GetXid(); | 589 | xid = GetXid(); |
579 | 590 | ||
580 | rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, READ_CONTROL, 0, | 591 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, |
581 | &fid, &oplock, NULL, cifs_sb->local_nls, | 592 | &fid, &oplock, NULL, cifs_sb->local_nls, |
582 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 593 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
583 | if (rc) { | 594 | if (rc) { |
@@ -585,11 +596,12 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
585 | goto out; | 596 | goto out; |
586 | } | 597 | } |
587 | 598 | ||
588 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, &pntsd, pacllen); | 599 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); |
589 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | 600 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); |
590 | 601 | ||
591 | CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid); | 602 | CIFSSMBClose(xid, tcon, fid); |
592 | out: | 603 | out: |
604 | cifs_put_tlink(tlink); | ||
593 | FreeXid(xid); | 605 | FreeXid(xid); |
594 | return pntsd; | 606 | return pntsd; |
595 | } | 607 | } |
@@ -616,10 +628,15 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid, | |||
616 | struct cifs_ntsd *pnntsd, u32 acllen) | 628 | struct cifs_ntsd *pnntsd, u32 acllen) |
617 | { | 629 | { |
618 | int xid, rc; | 630 | int xid, rc; |
631 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
632 | |||
633 | if (IS_ERR(tlink)) | ||
634 | return PTR_ERR(tlink); | ||
619 | 635 | ||
620 | xid = GetXid(); | 636 | xid = GetXid(); |
621 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen); | 637 | rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen); |
622 | FreeXid(xid); | 638 | FreeXid(xid); |
639 | cifs_put_tlink(tlink); | ||
623 | 640 | ||
624 | cFYI(DBG2, "SetCIFSACL rc = %d", rc); | 641 | cFYI(DBG2, "SetCIFSACL rc = %d", rc); |
625 | return rc; | 642 | return rc; |
@@ -631,10 +648,16 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, | |||
631 | int oplock = 0; | 648 | int oplock = 0; |
632 | int xid, rc; | 649 | int xid, rc; |
633 | __u16 fid; | 650 | __u16 fid; |
651 | struct cifsTconInfo *tcon; | ||
652 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
634 | 653 | ||
654 | if (IS_ERR(tlink)) | ||
655 | return PTR_ERR(tlink); | ||
656 | |||
657 | tcon = tlink_tcon(tlink); | ||
635 | xid = GetXid(); | 658 | xid = GetXid(); |
636 | 659 | ||
637 | rc = CIFSSMBOpen(xid, cifs_sb_tcon(cifs_sb), path, FILE_OPEN, WRITE_DAC, 0, | 660 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0, |
638 | &fid, &oplock, NULL, cifs_sb->local_nls, | 661 | &fid, &oplock, NULL, cifs_sb->local_nls, |
639 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 662 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
640 | if (rc) { | 663 | if (rc) { |
@@ -642,12 +665,13 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, | |||
642 | goto out; | 665 | goto out; |
643 | } | 666 | } |
644 | 667 | ||
645 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb_tcon(cifs_sb), fid, pnntsd, acllen); | 668 | rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen); |
646 | cFYI(DBG2, "SetCIFSACL rc = %d", rc); | 669 | cFYI(DBG2, "SetCIFSACL rc = %d", rc); |
647 | 670 | ||
648 | CIFSSMBClose(xid, cifs_sb_tcon(cifs_sb), fid); | 671 | CIFSSMBClose(xid, tcon, fid); |
649 | out: | 672 | out: |
650 | FreeXid(xid); | 673 | FreeXid(xid); |
674 | cifs_put_tlink(tlink); | ||
651 | return rc; | 675 | return rc; |
652 | } | 676 | } |
653 | 677 | ||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c265ebdcd177..cdfd2db4e70d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -311,6 +311,44 @@ struct cifsTconInfo { | |||
311 | }; | 311 | }; |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * This is a refcounted and timestamped container for a tcon pointer. The | ||
315 | * container holds a tcon reference. It is considered safe to free one of | ||
316 | * these when the tl_count goes to 0. The tl_time is the time of the last | ||
317 | * "get" on the container. | ||
318 | */ | ||
319 | struct tcon_link { | ||
320 | spinlock_t tl_lock; | ||
321 | u32 tl_count; | ||
322 | u64 tl_time; | ||
323 | struct cifsTconInfo *tl_tcon; | ||
324 | }; | ||
325 | |||
326 | static inline struct tcon_link * | ||
327 | cifs_sb_tlink(struct cifs_sb_info *cifs_sb) | ||
328 | { | ||
329 | return (struct tcon_link *)cifs_sb->ptcon; | ||
330 | } | ||
331 | |||
332 | static inline struct cifsTconInfo * | ||
333 | tlink_tcon(struct tcon_link *tlink) | ||
334 | { | ||
335 | return (struct cifsTconInfo *)tlink; | ||
336 | } | ||
337 | |||
338 | static inline void | ||
339 | cifs_put_tlink(struct tcon_link *tlink) | ||
340 | { | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | /* This function is always expected to succeed */ | ||
345 | static inline struct cifsTconInfo * | ||
346 | cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) | ||
347 | { | ||
348 | return cifs_sb->ptcon; | ||
349 | } | ||
350 | |||
351 | /* | ||
314 | * This info hangs off the cifsFileInfo structure, pointed to by llist. | 352 | * This info hangs off the cifsFileInfo structure, pointed to by llist. |
315 | * This is used to track byte stream locks on the file | 353 | * This is used to track byte stream locks on the file |
316 | */ | 354 | */ |
@@ -413,19 +451,6 @@ CIFS_SB(struct super_block *sb) | |||
413 | return sb->s_fs_info; | 451 | return sb->s_fs_info; |
414 | } | 452 | } |
415 | 453 | ||
416 | static inline struct cifsTconInfo * | ||
417 | cifs_sb_tcon(struct cifs_sb_info *cifs_sb) | ||
418 | { | ||
419 | return cifs_sb->ptcon; | ||
420 | } | ||
421 | |||
422 | /* This function is always expected to succeed */ | ||
423 | static inline struct cifsTconInfo * | ||
424 | cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) | ||
425 | { | ||
426 | return cifs_sb->ptcon; | ||
427 | } | ||
428 | |||
429 | static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb) | 454 | static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb) |
430 | { | 455 | { |
431 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 456 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 23ec28a4c11f..bb3ea06ca6f4 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -137,7 +137,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, | |||
137 | { | 137 | { |
138 | struct cifsFileInfo *pCifsFile; | 138 | struct cifsFileInfo *pCifsFile; |
139 | struct cifsInodeInfo *pCifsInode; | 139 | struct cifsInodeInfo *pCifsInode; |
140 | struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); | ||
141 | 140 | ||
142 | pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | 141 | pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
143 | if (pCifsFile == NULL) | 142 | if (pCifsFile == NULL) |
@@ -191,7 +190,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
191 | __u32 posix_flags = 0; | 190 | __u32 posix_flags = 0; |
192 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 191 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
193 | struct cifs_fattr fattr; | 192 | struct cifs_fattr fattr; |
194 | struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); | 193 | struct tcon_link *tlink; |
194 | struct cifsTconInfo *tcon; | ||
195 | 195 | ||
196 | cFYI(1, "posix open %s", full_path); | 196 | cFYI(1, "posix open %s", full_path); |
197 | 197 | ||
@@ -226,10 +226,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
226 | posix_flags |= SMB_O_DIRECT; | 226 | posix_flags |= SMB_O_DIRECT; |
227 | 227 | ||
228 | mode &= ~current_umask(); | 228 | mode &= ~current_umask(); |
229 | |||
230 | tlink = cifs_sb_tlink(cifs_sb); | ||
231 | if (IS_ERR(tlink)) { | ||
232 | rc = PTR_ERR(tlink); | ||
233 | goto posix_open_ret; | ||
234 | } | ||
235 | |||
236 | tcon = tlink_tcon(tlink); | ||
229 | rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, | 237 | rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, |
230 | poplock, full_path, cifs_sb->local_nls, | 238 | poplock, full_path, cifs_sb->local_nls, |
231 | cifs_sb->mnt_cifs_flags & | 239 | cifs_sb->mnt_cifs_flags & |
232 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 240 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
241 | cifs_put_tlink(tlink); | ||
242 | |||
233 | if (rc) | 243 | if (rc) |
234 | goto posix_open_ret; | 244 | goto posix_open_ret; |
235 | 245 | ||
@@ -290,6 +300,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
290 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; | 300 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; |
291 | __u16 fileHandle; | 301 | __u16 fileHandle; |
292 | struct cifs_sb_info *cifs_sb; | 302 | struct cifs_sb_info *cifs_sb; |
303 | struct tcon_link *tlink; | ||
293 | struct cifsTconInfo *tcon; | 304 | struct cifsTconInfo *tcon; |
294 | char *full_path = NULL; | 305 | char *full_path = NULL; |
295 | FILE_ALL_INFO *buf = NULL; | 306 | FILE_ALL_INFO *buf = NULL; |
@@ -299,13 +310,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
299 | xid = GetXid(); | 310 | xid = GetXid(); |
300 | 311 | ||
301 | cifs_sb = CIFS_SB(inode->i_sb); | 312 | cifs_sb = CIFS_SB(inode->i_sb); |
302 | tcon = cifs_sb_tcon(cifs_sb); | 313 | tlink = cifs_sb_tlink(cifs_sb); |
303 | 314 | if (IS_ERR(tlink)) { | |
304 | full_path = build_path_from_dentry(direntry); | 315 | FreeXid(xid); |
305 | if (full_path == NULL) { | 316 | return PTR_ERR(tlink); |
306 | rc = -ENOMEM; | ||
307 | goto cifs_create_out; | ||
308 | } | 317 | } |
318 | tcon = tlink_tcon(tlink); | ||
309 | 319 | ||
310 | if (oplockEnabled) | 320 | if (oplockEnabled) |
311 | oplock = REQ_OPLOCK; | 321 | oplock = REQ_OPLOCK; |
@@ -315,6 +325,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
315 | else | 325 | else |
316 | oflags = FMODE_READ | SMB_O_CREAT; | 326 | oflags = FMODE_READ | SMB_O_CREAT; |
317 | 327 | ||
328 | full_path = build_path_from_dentry(direntry); | ||
329 | if (full_path == NULL) { | ||
330 | rc = -ENOMEM; | ||
331 | goto cifs_create_out; | ||
332 | } | ||
333 | |||
318 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 334 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
319 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 335 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
320 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 336 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
@@ -481,6 +497,7 @@ cifs_create_set_dentry: | |||
481 | cifs_create_out: | 497 | cifs_create_out: |
482 | kfree(buf); | 498 | kfree(buf); |
483 | kfree(full_path); | 499 | kfree(full_path); |
500 | cifs_put_tlink(tlink); | ||
484 | FreeXid(xid); | 501 | FreeXid(xid); |
485 | return rc; | 502 | return rc; |
486 | } | 503 | } |
@@ -491,6 +508,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
491 | int rc = -EPERM; | 508 | int rc = -EPERM; |
492 | int xid; | 509 | int xid; |
493 | struct cifs_sb_info *cifs_sb; | 510 | struct cifs_sb_info *cifs_sb; |
511 | struct tcon_link *tlink; | ||
494 | struct cifsTconInfo *pTcon; | 512 | struct cifsTconInfo *pTcon; |
495 | char *full_path = NULL; | 513 | char *full_path = NULL; |
496 | struct inode *newinode = NULL; | 514 | struct inode *newinode = NULL; |
@@ -503,10 +521,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
503 | if (!old_valid_dev(device_number)) | 521 | if (!old_valid_dev(device_number)) |
504 | return -EINVAL; | 522 | return -EINVAL; |
505 | 523 | ||
506 | xid = GetXid(); | ||
507 | |||
508 | cifs_sb = CIFS_SB(inode->i_sb); | 524 | cifs_sb = CIFS_SB(inode->i_sb); |
509 | pTcon = cifs_sb_tcon(cifs_sb); | 525 | tlink = cifs_sb_tlink(cifs_sb); |
526 | if (IS_ERR(tlink)) | ||
527 | return PTR_ERR(tlink); | ||
528 | |||
529 | pTcon = tlink_tcon(tlink); | ||
530 | |||
531 | xid = GetXid(); | ||
510 | 532 | ||
511 | full_path = build_path_from_dentry(direntry); | 533 | full_path = build_path_from_dentry(direntry); |
512 | if (full_path == NULL) { | 534 | if (full_path == NULL) { |
@@ -606,6 +628,7 @@ mknod_out: | |||
606 | kfree(full_path); | 628 | kfree(full_path); |
607 | kfree(buf); | 629 | kfree(buf); |
608 | FreeXid(xid); | 630 | FreeXid(xid); |
631 | cifs_put_tlink(tlink); | ||
609 | return rc; | 632 | return rc; |
610 | } | 633 | } |
611 | 634 | ||
@@ -619,6 +642,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
619 | __u16 fileHandle = 0; | 642 | __u16 fileHandle = 0; |
620 | bool posix_open = false; | 643 | bool posix_open = false; |
621 | struct cifs_sb_info *cifs_sb; | 644 | struct cifs_sb_info *cifs_sb; |
645 | struct tcon_link *tlink; | ||
622 | struct cifsTconInfo *pTcon; | 646 | struct cifsTconInfo *pTcon; |
623 | struct cifsFileInfo *cfile; | 647 | struct cifsFileInfo *cfile; |
624 | struct inode *newInode = NULL; | 648 | struct inode *newInode = NULL; |
@@ -633,7 +657,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
633 | /* check whether path exists */ | 657 | /* check whether path exists */ |
634 | 658 | ||
635 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); | 659 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); |
636 | pTcon = cifs_sb_tcon(cifs_sb); | 660 | tlink = cifs_sb_tlink(cifs_sb); |
661 | if (IS_ERR(tlink)) { | ||
662 | FreeXid(xid); | ||
663 | return (struct dentry *)tlink; | ||
664 | } | ||
665 | pTcon = tlink_tcon(tlink); | ||
637 | 666 | ||
638 | /* | 667 | /* |
639 | * Don't allow the separator character in a path component. | 668 | * Don't allow the separator character in a path component. |
@@ -644,8 +673,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
644 | for (i = 0; i < direntry->d_name.len; i++) | 673 | for (i = 0; i < direntry->d_name.len; i++) |
645 | if (direntry->d_name.name[i] == '\\') { | 674 | if (direntry->d_name.name[i] == '\\') { |
646 | cFYI(1, "Invalid file name"); | 675 | cFYI(1, "Invalid file name"); |
647 | FreeXid(xid); | 676 | rc = -EINVAL; |
648 | return ERR_PTR(-EINVAL); | 677 | goto lookup_out; |
649 | } | 678 | } |
650 | } | 679 | } |
651 | 680 | ||
@@ -655,7 +684,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
655 | */ | 684 | */ |
656 | if (nd && (nd->flags & LOOKUP_EXCL)) { | 685 | if (nd && (nd->flags & LOOKUP_EXCL)) { |
657 | d_instantiate(direntry, NULL); | 686 | d_instantiate(direntry, NULL); |
658 | return NULL; | 687 | rc = 0; |
688 | goto lookup_out; | ||
659 | } | 689 | } |
660 | 690 | ||
661 | /* can not grab the rename sem here since it would | 691 | /* can not grab the rename sem here since it would |
@@ -663,8 +693,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
663 | in which we already have the sb rename sem */ | 693 | in which we already have the sb rename sem */ |
664 | full_path = build_path_from_dentry(direntry); | 694 | full_path = build_path_from_dentry(direntry); |
665 | if (full_path == NULL) { | 695 | if (full_path == NULL) { |
666 | FreeXid(xid); | 696 | rc = -ENOMEM; |
667 | return ERR_PTR(-ENOMEM); | 697 | goto lookup_out; |
668 | } | 698 | } |
669 | 699 | ||
670 | if (direntry->d_inode != NULL) { | 700 | if (direntry->d_inode != NULL) { |
@@ -760,6 +790,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
760 | 790 | ||
761 | lookup_out: | 791 | lookup_out: |
762 | kfree(full_path); | 792 | kfree(full_path); |
793 | cifs_put_tlink(tlink); | ||
763 | FreeXid(xid); | 794 | FreeXid(xid); |
764 | return ERR_PTR(rc); | 795 | return ERR_PTR(rc); |
765 | } | 796 | } |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index de046e183d12..1e375abc5eb3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -224,6 +224,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
224 | __u32 oplock; | 224 | __u32 oplock; |
225 | struct cifs_sb_info *cifs_sb; | 225 | struct cifs_sb_info *cifs_sb; |
226 | struct cifsTconInfo *tcon; | 226 | struct cifsTconInfo *tcon; |
227 | struct tcon_link *tlink; | ||
227 | struct cifsFileInfo *pCifsFile = NULL; | 228 | struct cifsFileInfo *pCifsFile = NULL; |
228 | struct cifsInodeInfo *pCifsInode; | 229 | struct cifsInodeInfo *pCifsInode; |
229 | char *full_path = NULL; | 230 | char *full_path = NULL; |
@@ -235,7 +236,12 @@ int cifs_open(struct inode *inode, struct file *file) | |||
235 | xid = GetXid(); | 236 | xid = GetXid(); |
236 | 237 | ||
237 | cifs_sb = CIFS_SB(inode->i_sb); | 238 | cifs_sb = CIFS_SB(inode->i_sb); |
238 | tcon = cifs_sb_tcon(cifs_sb); | 239 | tlink = cifs_sb_tlink(cifs_sb); |
240 | if (IS_ERR(tlink)) { | ||
241 | FreeXid(xid); | ||
242 | return PTR_ERR(tlink); | ||
243 | } | ||
244 | tcon = tlink_tcon(tlink); | ||
239 | 245 | ||
240 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | 246 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); |
241 | 247 | ||
@@ -402,6 +408,7 @@ out: | |||
402 | kfree(buf); | 408 | kfree(buf); |
403 | kfree(full_path); | 409 | kfree(full_path); |
404 | FreeXid(xid); | 410 | FreeXid(xid); |
411 | cifs_put_tlink(tlink); | ||
405 | return rc; | 412 | return rc; |
406 | } | 413 | } |
407 | 414 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index da716d96dae6..aa229692aef1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -313,16 +313,21 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
313 | FILE_UNIX_BASIC_INFO find_data; | 313 | FILE_UNIX_BASIC_INFO find_data; |
314 | struct cifs_fattr fattr; | 314 | struct cifs_fattr fattr; |
315 | struct cifsTconInfo *tcon; | 315 | struct cifsTconInfo *tcon; |
316 | struct tcon_link *tlink; | ||
316 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 317 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
317 | 318 | ||
318 | tcon = cifs_sb_tcon(cifs_sb); | ||
319 | |||
320 | cFYI(1, "Getting info on %s", full_path); | 319 | cFYI(1, "Getting info on %s", full_path); |
321 | 320 | ||
321 | tlink = cifs_sb_tlink(cifs_sb); | ||
322 | if (IS_ERR(tlink)) | ||
323 | return PTR_ERR(tlink); | ||
324 | tcon = tlink_tcon(tlink); | ||
325 | |||
322 | /* could have done a find first instead but this returns more info */ | 326 | /* could have done a find first instead but this returns more info */ |
323 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, | 327 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
324 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 328 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
325 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 329 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
330 | cifs_put_tlink(tlink); | ||
326 | 331 | ||
327 | if (!rc) { | 332 | if (!rc) { |
328 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); | 333 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
@@ -361,7 +366,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
361 | int rc; | 366 | int rc; |
362 | int oplock = 0; | 367 | int oplock = 0; |
363 | __u16 netfid; | 368 | __u16 netfid; |
364 | struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); | 369 | struct tcon_link *tlink; |
370 | struct cifsTconInfo *tcon; | ||
365 | char buf[24]; | 371 | char buf[24]; |
366 | unsigned int bytes_read; | 372 | unsigned int bytes_read; |
367 | char *pbuf; | 373 | char *pbuf; |
@@ -380,7 +386,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
380 | return -EINVAL; /* EOPNOTSUPP? */ | 386 | return -EINVAL; /* EOPNOTSUPP? */ |
381 | } | 387 | } |
382 | 388 | ||
383 | rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, | 389 | tlink = cifs_sb_tlink(cifs_sb); |
390 | if (IS_ERR(tlink)) | ||
391 | return PTR_ERR(tlink); | ||
392 | tcon = tlink_tcon(tlink); | ||
393 | |||
394 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | ||
384 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 395 | CREATE_NOT_DIR, &netfid, &oplock, NULL, |
385 | cifs_sb->local_nls, | 396 | cifs_sb->local_nls, |
386 | cifs_sb->mnt_cifs_flags & | 397 | cifs_sb->mnt_cifs_flags & |
@@ -388,7 +399,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
388 | if (rc == 0) { | 399 | if (rc == 0) { |
389 | int buf_type = CIFS_NO_BUFFER; | 400 | int buf_type = CIFS_NO_BUFFER; |
390 | /* Read header */ | 401 | /* Read header */ |
391 | rc = CIFSSMBRead(xid, pTcon, netfid, | 402 | rc = CIFSSMBRead(xid, tcon, netfid, |
392 | 24 /* length */, 0 /* offset */, | 403 | 24 /* length */, 0 /* offset */, |
393 | &bytes_read, &pbuf, &buf_type); | 404 | &bytes_read, &pbuf, &buf_type); |
394 | if ((rc == 0) && (bytes_read >= 8)) { | 405 | if ((rc == 0) && (bytes_read >= 8)) { |
@@ -430,8 +441,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
430 | fattr->cf_dtype = DT_REG; | 441 | fattr->cf_dtype = DT_REG; |
431 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 442 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
432 | } | 443 | } |
433 | CIFSSMBClose(xid, pTcon, netfid); | 444 | CIFSSMBClose(xid, tcon, netfid); |
434 | } | 445 | } |
446 | cifs_put_tlink(tlink); | ||
435 | return rc; | 447 | return rc; |
436 | } | 448 | } |
437 | 449 | ||
@@ -449,11 +461,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
449 | ssize_t rc; | 461 | ssize_t rc; |
450 | char ea_value[4]; | 462 | char ea_value[4]; |
451 | __u32 mode; | 463 | __u32 mode; |
464 | struct tcon_link *tlink; | ||
465 | struct cifsTconInfo *tcon; | ||
452 | 466 | ||
453 | rc = CIFSSMBQAllEAs(xid, cifs_sb_tcon(cifs_sb), path, "SETFILEBITS", | 467 | tlink = cifs_sb_tlink(cifs_sb); |
468 | if (IS_ERR(tlink)) | ||
469 | return PTR_ERR(tlink); | ||
470 | tcon = tlink_tcon(tlink); | ||
471 | |||
472 | rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", | ||
454 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 473 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
455 | cifs_sb->mnt_cifs_flags & | 474 | cifs_sb->mnt_cifs_flags & |
456 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 475 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
476 | cifs_put_tlink(tlink); | ||
457 | if (rc < 0) | 477 | if (rc < 0) |
458 | return (int)rc; | 478 | return (int)rc; |
459 | else if (rc > 3) { | 479 | else if (rc > 3) { |
@@ -564,26 +584,33 @@ int cifs_get_inode_info(struct inode **pinode, | |||
564 | { | 584 | { |
565 | int rc = 0, tmprc; | 585 | int rc = 0, tmprc; |
566 | struct cifsTconInfo *pTcon; | 586 | struct cifsTconInfo *pTcon; |
587 | struct tcon_link *tlink; | ||
567 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 588 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
568 | char *buf = NULL; | 589 | char *buf = NULL; |
569 | bool adjustTZ = false; | 590 | bool adjustTZ = false; |
570 | struct cifs_fattr fattr; | 591 | struct cifs_fattr fattr; |
571 | 592 | ||
572 | pTcon = cifs_sb_tcon(cifs_sb); | 593 | tlink = cifs_sb_tlink(cifs_sb); |
594 | if (IS_ERR(tlink)) | ||
595 | return PTR_ERR(tlink); | ||
596 | pTcon = tlink_tcon(tlink); | ||
597 | |||
573 | cFYI(1, "Getting info on %s", full_path); | 598 | cFYI(1, "Getting info on %s", full_path); |
574 | 599 | ||
575 | if ((pfindData == NULL) && (*pinode != NULL)) { | 600 | if ((pfindData == NULL) && (*pinode != NULL)) { |
576 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 601 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
577 | cFYI(1, "No need to revalidate cached inode sizes"); | 602 | cFYI(1, "No need to revalidate cached inode sizes"); |
578 | return rc; | 603 | goto cgii_exit; |
579 | } | 604 | } |
580 | } | 605 | } |
581 | 606 | ||
582 | /* if file info not passed in then get it from server */ | 607 | /* if file info not passed in then get it from server */ |
583 | if (pfindData == NULL) { | 608 | if (pfindData == NULL) { |
584 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 609 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
585 | if (buf == NULL) | 610 | if (buf == NULL) { |
586 | return -ENOMEM; | 611 | rc = -ENOMEM; |
612 | goto cgii_exit; | ||
613 | } | ||
587 | pfindData = (FILE_ALL_INFO *)buf; | 614 | pfindData = (FILE_ALL_INFO *)buf; |
588 | 615 | ||
589 | /* could do find first instead but this returns more info */ | 616 | /* could do find first instead but this returns more info */ |
@@ -688,6 +715,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
688 | 715 | ||
689 | cgii_exit: | 716 | cgii_exit: |
690 | kfree(buf); | 717 | kfree(buf); |
718 | cifs_put_tlink(tlink); | ||
691 | return rc; | 719 | return rc; |
692 | } | 720 | } |
693 | 721 | ||
@@ -895,6 +923,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
895 | struct cifsFileInfo *open_file; | 923 | struct cifsFileInfo *open_file; |
896 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 924 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
897 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 925 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
926 | struct tcon_link *tlink = NULL; | ||
898 | struct cifsTconInfo *pTcon; | 927 | struct cifsTconInfo *pTcon; |
899 | FILE_BASIC_INFO info_buf; | 928 | FILE_BASIC_INFO info_buf; |
900 | 929 | ||
@@ -942,7 +971,13 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
942 | goto set_via_filehandle; | 971 | goto set_via_filehandle; |
943 | } | 972 | } |
944 | 973 | ||
945 | pTcon = cifs_sb_tcon(cifs_sb); | 974 | tlink = cifs_sb_tlink(cifs_sb); |
975 | if (IS_ERR(tlink)) { | ||
976 | rc = PTR_ERR(tlink); | ||
977 | tlink = NULL; | ||
978 | goto out; | ||
979 | } | ||
980 | pTcon = tlink_tcon(tlink); | ||
946 | 981 | ||
947 | /* | 982 | /* |
948 | * NT4 apparently returns success on this call, but it doesn't | 983 | * NT4 apparently returns success on this call, but it doesn't |
@@ -987,6 +1022,8 @@ set_via_filehandle: | |||
987 | else | 1022 | else |
988 | cifsFileInfo_put(open_file); | 1023 | cifsFileInfo_put(open_file); |
989 | out: | 1024 | out: |
1025 | if (tlink != NULL) | ||
1026 | cifs_put_tlink(tlink); | ||
990 | return rc; | 1027 | return rc; |
991 | } | 1028 | } |
992 | 1029 | ||
@@ -1004,10 +1041,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) | |||
1004 | struct inode *inode = dentry->d_inode; | 1041 | struct inode *inode = dentry->d_inode; |
1005 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1042 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1006 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1043 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1007 | struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); | 1044 | struct tcon_link *tlink; |
1045 | struct cifsTconInfo *tcon; | ||
1008 | __u32 dosattr, origattr; | 1046 | __u32 dosattr, origattr; |
1009 | FILE_BASIC_INFO *info_buf = NULL; | 1047 | FILE_BASIC_INFO *info_buf = NULL; |
1010 | 1048 | ||
1049 | tlink = cifs_sb_tlink(cifs_sb); | ||
1050 | if (IS_ERR(tlink)) | ||
1051 | return PTR_ERR(tlink); | ||
1052 | tcon = tlink_tcon(tlink); | ||
1053 | |||
1011 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1054 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, |
1012 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1055 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, |
1013 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1056 | &netfid, &oplock, NULL, cifs_sb->local_nls, |
@@ -1076,6 +1119,7 @@ out_close: | |||
1076 | CIFSSMBClose(xid, tcon, netfid); | 1119 | CIFSSMBClose(xid, tcon, netfid); |
1077 | out: | 1120 | out: |
1078 | kfree(info_buf); | 1121 | kfree(info_buf); |
1122 | cifs_put_tlink(tlink); | ||
1079 | return rc; | 1123 | return rc; |
1080 | 1124 | ||
1081 | /* | 1125 | /* |
@@ -1115,12 +1159,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1115 | struct cifsInodeInfo *cifs_inode; | 1159 | struct cifsInodeInfo *cifs_inode; |
1116 | struct super_block *sb = dir->i_sb; | 1160 | struct super_block *sb = dir->i_sb; |
1117 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1161 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
1118 | struct cifsTconInfo *tcon = cifs_sb_tcon(cifs_sb); | 1162 | struct tcon_link *tlink; |
1163 | struct cifsTconInfo *tcon; | ||
1119 | struct iattr *attrs = NULL; | 1164 | struct iattr *attrs = NULL; |
1120 | __u32 dosattr = 0, origattr = 0; | 1165 | __u32 dosattr = 0, origattr = 0; |
1121 | 1166 | ||
1122 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); | 1167 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); |
1123 | 1168 | ||
1169 | tlink = cifs_sb_tlink(cifs_sb); | ||
1170 | if (IS_ERR(tlink)) | ||
1171 | return PTR_ERR(tlink); | ||
1172 | tcon = tlink_tcon(tlink); | ||
1173 | |||
1124 | xid = GetXid(); | 1174 | xid = GetXid(); |
1125 | 1175 | ||
1126 | /* Unlink can be called from rename so we can not take the | 1176 | /* Unlink can be called from rename so we can not take the |
@@ -1128,8 +1178,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1128 | full_path = build_path_from_dentry(dentry); | 1178 | full_path = build_path_from_dentry(dentry); |
1129 | if (full_path == NULL) { | 1179 | if (full_path == NULL) { |
1130 | rc = -ENOMEM; | 1180 | rc = -ENOMEM; |
1131 | FreeXid(xid); | 1181 | goto unlink_out; |
1132 | return rc; | ||
1133 | } | 1182 | } |
1134 | 1183 | ||
1135 | if ((tcon->ses->capabilities & CAP_UNIX) && | 1184 | if ((tcon->ses->capabilities & CAP_UNIX) && |
@@ -1195,10 +1244,11 @@ out_reval: | |||
1195 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); | 1244 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); |
1196 | cifs_inode = CIFS_I(dir); | 1245 | cifs_inode = CIFS_I(dir); |
1197 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ | 1246 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ |
1198 | 1247 | unlink_out: | |
1199 | kfree(full_path); | 1248 | kfree(full_path); |
1200 | kfree(attrs); | 1249 | kfree(attrs); |
1201 | FreeXid(xid); | 1250 | FreeXid(xid); |
1251 | cifs_put_tlink(tlink); | ||
1202 | return rc; | 1252 | return rc; |
1203 | } | 1253 | } |
1204 | 1254 | ||
@@ -1207,6 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1207 | int rc = 0, tmprc; | 1257 | int rc = 0, tmprc; |
1208 | int xid; | 1258 | int xid; |
1209 | struct cifs_sb_info *cifs_sb; | 1259 | struct cifs_sb_info *cifs_sb; |
1260 | struct tcon_link *tlink; | ||
1210 | struct cifsTconInfo *pTcon; | 1261 | struct cifsTconInfo *pTcon; |
1211 | char *full_path = NULL; | 1262 | char *full_path = NULL; |
1212 | struct inode *newinode = NULL; | 1263 | struct inode *newinode = NULL; |
@@ -1214,16 +1265,18 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1214 | 1265 | ||
1215 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); | 1266 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); |
1216 | 1267 | ||
1217 | xid = GetXid(); | ||
1218 | |||
1219 | cifs_sb = CIFS_SB(inode->i_sb); | 1268 | cifs_sb = CIFS_SB(inode->i_sb); |
1220 | pTcon = cifs_sb_tcon(cifs_sb); | 1269 | tlink = cifs_sb_tlink(cifs_sb); |
1270 | if (IS_ERR(tlink)) | ||
1271 | return PTR_ERR(tlink); | ||
1272 | pTcon = tlink_tcon(tlink); | ||
1273 | |||
1274 | xid = GetXid(); | ||
1221 | 1275 | ||
1222 | full_path = build_path_from_dentry(direntry); | 1276 | full_path = build_path_from_dentry(direntry); |
1223 | if (full_path == NULL) { | 1277 | if (full_path == NULL) { |
1224 | rc = -ENOMEM; | 1278 | rc = -ENOMEM; |
1225 | FreeXid(xid); | 1279 | goto mkdir_out; |
1226 | return rc; | ||
1227 | } | 1280 | } |
1228 | 1281 | ||
1229 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1282 | if ((pTcon->ses->capabilities & CAP_UNIX) && |
@@ -1381,6 +1434,7 @@ mkdir_get_info: | |||
1381 | mkdir_out: | 1434 | mkdir_out: |
1382 | kfree(full_path); | 1435 | kfree(full_path); |
1383 | FreeXid(xid); | 1436 | FreeXid(xid); |
1437 | cifs_put_tlink(tlink); | ||
1384 | return rc; | 1438 | return rc; |
1385 | } | 1439 | } |
1386 | 1440 | ||
@@ -1389,6 +1443,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1389 | int rc = 0; | 1443 | int rc = 0; |
1390 | int xid; | 1444 | int xid; |
1391 | struct cifs_sb_info *cifs_sb; | 1445 | struct cifs_sb_info *cifs_sb; |
1446 | struct tcon_link *tlink; | ||
1392 | struct cifsTconInfo *pTcon; | 1447 | struct cifsTconInfo *pTcon; |
1393 | char *full_path = NULL; | 1448 | char *full_path = NULL; |
1394 | struct cifsInodeInfo *cifsInode; | 1449 | struct cifsInodeInfo *cifsInode; |
@@ -1397,18 +1452,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1397 | 1452 | ||
1398 | xid = GetXid(); | 1453 | xid = GetXid(); |
1399 | 1454 | ||
1400 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1401 | pTcon = cifs_sb_tcon(cifs_sb); | ||
1402 | |||
1403 | full_path = build_path_from_dentry(direntry); | 1455 | full_path = build_path_from_dentry(direntry); |
1404 | if (full_path == NULL) { | 1456 | if (full_path == NULL) { |
1405 | rc = -ENOMEM; | 1457 | rc = -ENOMEM; |
1406 | FreeXid(xid); | 1458 | goto rmdir_exit; |
1407 | return rc; | 1459 | } |
1460 | |||
1461 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1462 | tlink = cifs_sb_tlink(cifs_sb); | ||
1463 | if (IS_ERR(tlink)) { | ||
1464 | rc = PTR_ERR(tlink); | ||
1465 | goto rmdir_exit; | ||
1408 | } | 1466 | } |
1467 | pTcon = tlink_tcon(tlink); | ||
1409 | 1468 | ||
1410 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1469 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, |
1411 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1470 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
1471 | cifs_put_tlink(tlink); | ||
1412 | 1472 | ||
1413 | if (!rc) { | 1473 | if (!rc) { |
1414 | drop_nlink(inode); | 1474 | drop_nlink(inode); |
@@ -1429,6 +1489,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1429 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = | 1489 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = |
1430 | current_fs_time(inode->i_sb); | 1490 | current_fs_time(inode->i_sb); |
1431 | 1491 | ||
1492 | rmdir_exit: | ||
1432 | kfree(full_path); | 1493 | kfree(full_path); |
1433 | FreeXid(xid); | 1494 | FreeXid(xid); |
1434 | return rc; | 1495 | return rc; |
@@ -1439,10 +1500,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1439 | struct dentry *to_dentry, const char *toPath) | 1500 | struct dentry *to_dentry, const char *toPath) |
1440 | { | 1501 | { |
1441 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1502 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
1442 | struct cifsTconInfo *pTcon = cifs_sb_tcon(cifs_sb); | 1503 | struct tcon_link *tlink; |
1504 | struct cifsTconInfo *pTcon; | ||
1443 | __u16 srcfid; | 1505 | __u16 srcfid; |
1444 | int oplock, rc; | 1506 | int oplock, rc; |
1445 | 1507 | ||
1508 | tlink = cifs_sb_tlink(cifs_sb); | ||
1509 | if (IS_ERR(tlink)) | ||
1510 | return PTR_ERR(tlink); | ||
1511 | pTcon = tlink_tcon(tlink); | ||
1512 | |||
1446 | /* try path-based rename first */ | 1513 | /* try path-based rename first */ |
1447 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, | 1514 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, |
1448 | cifs_sb->mnt_cifs_flags & | 1515 | cifs_sb->mnt_cifs_flags & |
@@ -1454,11 +1521,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1454 | * rename by filehandle to various Windows servers. | 1521 | * rename by filehandle to various Windows servers. |
1455 | */ | 1522 | */ |
1456 | if (rc == 0 || rc != -ETXTBSY) | 1523 | if (rc == 0 || rc != -ETXTBSY) |
1457 | return rc; | 1524 | goto do_rename_exit; |
1458 | 1525 | ||
1459 | /* open-file renames don't work across directories */ | 1526 | /* open-file renames don't work across directories */ |
1460 | if (to_dentry->d_parent != from_dentry->d_parent) | 1527 | if (to_dentry->d_parent != from_dentry->d_parent) |
1461 | return rc; | 1528 | goto do_rename_exit; |
1462 | 1529 | ||
1463 | /* open the file to be renamed -- we need DELETE perms */ | 1530 | /* open the file to be renamed -- we need DELETE perms */ |
1464 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1531 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, |
@@ -1474,7 +1541,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1474 | 1541 | ||
1475 | CIFSSMBClose(xid, pTcon, srcfid); | 1542 | CIFSSMBClose(xid, pTcon, srcfid); |
1476 | } | 1543 | } |
1477 | 1544 | do_rename_exit: | |
1545 | cifs_put_tlink(tlink); | ||
1478 | return rc; | 1546 | return rc; |
1479 | } | 1547 | } |
1480 | 1548 | ||
@@ -1484,13 +1552,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1484 | char *fromName = NULL; | 1552 | char *fromName = NULL; |
1485 | char *toName = NULL; | 1553 | char *toName = NULL; |
1486 | struct cifs_sb_info *cifs_sb; | 1554 | struct cifs_sb_info *cifs_sb; |
1555 | struct tcon_link *tlink; | ||
1487 | struct cifsTconInfo *tcon; | 1556 | struct cifsTconInfo *tcon; |
1488 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1557 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
1489 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1558 | FILE_UNIX_BASIC_INFO *info_buf_target; |
1490 | int xid, rc, tmprc; | 1559 | int xid, rc, tmprc; |
1491 | 1560 | ||
1492 | cifs_sb = CIFS_SB(source_dir->i_sb); | 1561 | cifs_sb = CIFS_SB(source_dir->i_sb); |
1493 | tcon = cifs_sb_tcon(cifs_sb); | 1562 | tlink = cifs_sb_tlink(cifs_sb); |
1563 | if (IS_ERR(tlink)) | ||
1564 | return PTR_ERR(tlink); | ||
1565 | tcon = tlink_tcon(tlink); | ||
1494 | 1566 | ||
1495 | xid = GetXid(); | 1567 | xid = GetXid(); |
1496 | 1568 | ||
@@ -1566,6 +1638,7 @@ cifs_rename_exit: | |||
1566 | kfree(fromName); | 1638 | kfree(fromName); |
1567 | kfree(toName); | 1639 | kfree(toName); |
1568 | FreeXid(xid); | 1640 | FreeXid(xid); |
1641 | cifs_put_tlink(tlink); | ||
1569 | return rc; | 1642 | return rc; |
1570 | } | 1643 | } |
1571 | 1644 | ||
@@ -1728,6 +1801,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1728 | struct cifsFileInfo *open_file; | 1801 | struct cifsFileInfo *open_file; |
1729 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1802 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1730 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1803 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1804 | struct tcon_link *tlink = NULL; | ||
1731 | struct cifsTconInfo *pTcon = NULL; | 1805 | struct cifsTconInfo *pTcon = NULL; |
1732 | 1806 | ||
1733 | /* | 1807 | /* |
@@ -1758,8 +1832,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1758 | rc = -EINVAL; | 1832 | rc = -EINVAL; |
1759 | 1833 | ||
1760 | if (rc != 0) { | 1834 | if (rc != 0) { |
1761 | if (pTcon == NULL) | 1835 | if (pTcon == NULL) { |
1762 | pTcon = cifs_sb_tcon(cifs_sb); | 1836 | tlink = cifs_sb_tlink(cifs_sb); |
1837 | if (IS_ERR(tlink)) | ||
1838 | return PTR_ERR(tlink); | ||
1839 | pTcon = tlink_tcon(tlink); | ||
1840 | } | ||
1763 | 1841 | ||
1764 | /* Set file size by pathname rather than by handle | 1842 | /* Set file size by pathname rather than by handle |
1765 | either because no valid, writeable file handle for | 1843 | either because no valid, writeable file handle for |
@@ -1790,6 +1868,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1790 | CIFSSMBClose(xid, pTcon, netfid); | 1868 | CIFSSMBClose(xid, pTcon, netfid); |
1791 | } | 1869 | } |
1792 | } | 1870 | } |
1871 | if (tlink) | ||
1872 | cifs_put_tlink(tlink); | ||
1793 | } | 1873 | } |
1794 | 1874 | ||
1795 | if (rc == 0) { | 1875 | if (rc == 0) { |
@@ -1810,6 +1890,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1810 | struct inode *inode = direntry->d_inode; | 1890 | struct inode *inode = direntry->d_inode; |
1811 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1891 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1812 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1892 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1893 | struct tcon_link *tlink; | ||
1813 | struct cifsTconInfo *pTcon; | 1894 | struct cifsTconInfo *pTcon; |
1814 | struct cifs_unix_set_info_args *args = NULL; | 1895 | struct cifs_unix_set_info_args *args = NULL; |
1815 | struct cifsFileInfo *open_file; | 1896 | struct cifsFileInfo *open_file; |
@@ -1905,11 +1986,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1905 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | 1986 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); |
1906 | cifsFileInfo_put(open_file); | 1987 | cifsFileInfo_put(open_file); |
1907 | } else { | 1988 | } else { |
1908 | pTcon = cifs_sb_tcon(cifs_sb); | 1989 | tlink = cifs_sb_tlink(cifs_sb); |
1990 | if (IS_ERR(tlink)) { | ||
1991 | rc = PTR_ERR(tlink); | ||
1992 | goto out; | ||
1993 | } | ||
1994 | pTcon = tlink_tcon(tlink); | ||
1909 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | 1995 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, |
1910 | cifs_sb->local_nls, | 1996 | cifs_sb->local_nls, |
1911 | cifs_sb->mnt_cifs_flags & | 1997 | cifs_sb->mnt_cifs_flags & |
1912 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1998 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1999 | cifs_put_tlink(tlink); | ||
1913 | } | 2000 | } |
1914 | 2001 | ||
1915 | if (rc) | 2002 | if (rc) |
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 | } |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 887a7e230376..170047cf4522 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -223,33 +223,35 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, | |||
223 | static int initiate_cifs_search(const int xid, struct file *file) | 223 | static int initiate_cifs_search(const int xid, struct file *file) |
224 | { | 224 | { |
225 | int rc = 0; | 225 | int rc = 0; |
226 | char *full_path; | 226 | char *full_path = NULL; |
227 | struct cifsFileInfo *cifsFile; | 227 | struct cifsFileInfo *cifsFile; |
228 | struct cifs_sb_info *cifs_sb; | 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
229 | struct tcon_link *tlink; | ||
229 | struct cifsTconInfo *pTcon; | 230 | struct cifsTconInfo *pTcon; |
230 | 231 | ||
231 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 232 | tlink = cifs_sb_tlink(cifs_sb); |
232 | if (cifs_sb == NULL) | 233 | if (IS_ERR(tlink)) |
233 | return -EINVAL; | 234 | return PTR_ERR(tlink); |
235 | pTcon = tlink_tcon(tlink); | ||
234 | 236 | ||
235 | if (file->private_data == NULL) | 237 | if (file->private_data == NULL) |
236 | file->private_data = | 238 | file->private_data = |
237 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | 239 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
240 | if (file->private_data == NULL) { | ||
241 | rc = -ENOMEM; | ||
242 | goto error_exit; | ||
243 | } | ||
238 | 244 | ||
239 | if (file->private_data == NULL) | ||
240 | return -ENOMEM; | ||
241 | cifsFile = file->private_data; | 245 | cifsFile = file->private_data; |
242 | cifsFile->invalidHandle = true; | 246 | cifsFile->invalidHandle = true; |
243 | cifsFile->srch_inf.endOfSearch = false; | 247 | cifsFile->srch_inf.endOfSearch = false; |
244 | cifsFile->tcon = cifs_sb_tcon(cifs_sb); | 248 | cifsFile->tcon = pTcon; |
245 | pTcon = cifsFile->tcon; | ||
246 | if (pTcon == NULL) | ||
247 | return -EINVAL; | ||
248 | 249 | ||
249 | full_path = build_path_from_dentry(file->f_path.dentry); | 250 | full_path = build_path_from_dentry(file->f_path.dentry); |
250 | 251 | if (full_path == NULL) { | |
251 | if (full_path == NULL) | 252 | rc = -ENOMEM; |
252 | return -ENOMEM; | 253 | goto error_exit; |
254 | } | ||
253 | 255 | ||
254 | cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); | 256 | cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); |
255 | 257 | ||
@@ -282,7 +284,9 @@ ffirst_retry: | |||
282 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; | 284 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
283 | goto ffirst_retry; | 285 | goto ffirst_retry; |
284 | } | 286 | } |
287 | error_exit: | ||
285 | kfree(full_path); | 288 | kfree(full_path); |
289 | cifs_put_tlink(tlink); | ||
286 | return rc; | 290 | return rc; |
287 | } | 291 | } |
288 | 292 | ||
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 41f95bf67977..a264b744bb41 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -47,9 +47,10 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
47 | #ifdef CONFIG_CIFS_XATTR | 47 | #ifdef CONFIG_CIFS_XATTR |
48 | int xid; | 48 | int xid; |
49 | struct cifs_sb_info *cifs_sb; | 49 | struct cifs_sb_info *cifs_sb; |
50 | struct tcon_link *tlink; | ||
50 | struct cifsTconInfo *pTcon; | 51 | struct cifsTconInfo *pTcon; |
51 | struct super_block *sb; | 52 | struct super_block *sb; |
52 | char *full_path; | 53 | char *full_path = NULL; |
53 | 54 | ||
54 | if (direntry == NULL) | 55 | if (direntry == NULL) |
55 | return -EIO; | 56 | return -EIO; |
@@ -58,16 +59,19 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
58 | sb = direntry->d_inode->i_sb; | 59 | sb = direntry->d_inode->i_sb; |
59 | if (sb == NULL) | 60 | if (sb == NULL) |
60 | return -EIO; | 61 | return -EIO; |
61 | xid = GetXid(); | ||
62 | 62 | ||
63 | cifs_sb = CIFS_SB(sb); | 63 | cifs_sb = CIFS_SB(sb); |
64 | pTcon = cifs_sb_tcon(cifs_sb); | 64 | tlink = cifs_sb_tlink(cifs_sb); |
65 | if (IS_ERR(tlink)) | ||
66 | return PTR_ERR(tlink); | ||
67 | pTcon = tlink_tcon(tlink); | ||
68 | |||
69 | xid = GetXid(); | ||
65 | 70 | ||
66 | full_path = build_path_from_dentry(direntry); | 71 | full_path = build_path_from_dentry(direntry); |
67 | if (full_path == NULL) { | 72 | if (full_path == NULL) { |
68 | rc = -ENOMEM; | 73 | rc = -ENOMEM; |
69 | FreeXid(xid); | 74 | goto remove_ea_exit; |
70 | return rc; | ||
71 | } | 75 | } |
72 | if (ea_name == NULL) { | 76 | if (ea_name == NULL) { |
73 | cFYI(1, "Null xattr names not supported"); | 77 | cFYI(1, "Null xattr names not supported"); |
@@ -91,6 +95,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
91 | remove_ea_exit: | 95 | remove_ea_exit: |
92 | kfree(full_path); | 96 | kfree(full_path); |
93 | FreeXid(xid); | 97 | FreeXid(xid); |
98 | cifs_put_tlink(tlink); | ||
94 | #endif | 99 | #endif |
95 | return rc; | 100 | return rc; |
96 | } | 101 | } |
@@ -102,6 +107,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
102 | #ifdef CONFIG_CIFS_XATTR | 107 | #ifdef CONFIG_CIFS_XATTR |
103 | int xid; | 108 | int xid; |
104 | struct cifs_sb_info *cifs_sb; | 109 | struct cifs_sb_info *cifs_sb; |
110 | struct tcon_link *tlink; | ||
105 | struct cifsTconInfo *pTcon; | 111 | struct cifsTconInfo *pTcon; |
106 | struct super_block *sb; | 112 | struct super_block *sb; |
107 | char *full_path; | 113 | char *full_path; |
@@ -113,16 +119,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
113 | sb = direntry->d_inode->i_sb; | 119 | sb = direntry->d_inode->i_sb; |
114 | if (sb == NULL) | 120 | if (sb == NULL) |
115 | return -EIO; | 121 | return -EIO; |
116 | xid = GetXid(); | ||
117 | 122 | ||
118 | cifs_sb = CIFS_SB(sb); | 123 | cifs_sb = CIFS_SB(sb); |
119 | pTcon = cifs_sb_tcon(cifs_sb); | 124 | tlink = cifs_sb_tlink(cifs_sb); |
125 | if (IS_ERR(tlink)) | ||
126 | return PTR_ERR(tlink); | ||
127 | pTcon = tlink_tcon(tlink); | ||
128 | |||
129 | xid = GetXid(); | ||
120 | 130 | ||
121 | full_path = build_path_from_dentry(direntry); | 131 | full_path = build_path_from_dentry(direntry); |
122 | if (full_path == NULL) { | 132 | if (full_path == NULL) { |
123 | rc = -ENOMEM; | 133 | rc = -ENOMEM; |
124 | FreeXid(xid); | 134 | goto set_ea_exit; |
125 | return rc; | ||
126 | } | 135 | } |
127 | /* return dos attributes as pseudo xattr */ | 136 | /* return dos attributes as pseudo xattr */ |
128 | /* return alt name if available as pseudo attr */ | 137 | /* return alt name if available as pseudo attr */ |
@@ -132,9 +141,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
132 | returns as xattrs */ | 141 | returns as xattrs */ |
133 | if (value_size > MAX_EA_VALUE_SIZE) { | 142 | if (value_size > MAX_EA_VALUE_SIZE) { |
134 | cFYI(1, "size of EA value too large"); | 143 | cFYI(1, "size of EA value too large"); |
135 | kfree(full_path); | 144 | rc = -EOPNOTSUPP; |
136 | FreeXid(xid); | 145 | goto set_ea_exit; |
137 | return -EOPNOTSUPP; | ||
138 | } | 146 | } |
139 | 147 | ||
140 | if (ea_name == NULL) { | 148 | if (ea_name == NULL) { |
@@ -198,6 +206,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
198 | set_ea_exit: | 206 | set_ea_exit: |
199 | kfree(full_path); | 207 | kfree(full_path); |
200 | FreeXid(xid); | 208 | FreeXid(xid); |
209 | cifs_put_tlink(tlink); | ||
201 | #endif | 210 | #endif |
202 | return rc; | 211 | return rc; |
203 | } | 212 | } |
@@ -209,6 +218,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
209 | #ifdef CONFIG_CIFS_XATTR | 218 | #ifdef CONFIG_CIFS_XATTR |
210 | int xid; | 219 | int xid; |
211 | struct cifs_sb_info *cifs_sb; | 220 | struct cifs_sb_info *cifs_sb; |
221 | struct tcon_link *tlink; | ||
212 | struct cifsTconInfo *pTcon; | 222 | struct cifsTconInfo *pTcon; |
213 | struct super_block *sb; | 223 | struct super_block *sb; |
214 | char *full_path; | 224 | char *full_path; |
@@ -221,16 +231,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
221 | if (sb == NULL) | 231 | if (sb == NULL) |
222 | return -EIO; | 232 | return -EIO; |
223 | 233 | ||
224 | xid = GetXid(); | ||
225 | |||
226 | cifs_sb = CIFS_SB(sb); | 234 | cifs_sb = CIFS_SB(sb); |
227 | pTcon = cifs_sb_tcon(cifs_sb); | 235 | tlink = cifs_sb_tlink(cifs_sb); |
236 | if (IS_ERR(tlink)) | ||
237 | return PTR_ERR(tlink); | ||
238 | pTcon = tlink_tcon(tlink); | ||
239 | |||
240 | xid = GetXid(); | ||
228 | 241 | ||
229 | full_path = build_path_from_dentry(direntry); | 242 | full_path = build_path_from_dentry(direntry); |
230 | if (full_path == NULL) { | 243 | if (full_path == NULL) { |
231 | rc = -ENOMEM; | 244 | rc = -ENOMEM; |
232 | FreeXid(xid); | 245 | goto get_ea_exit; |
233 | return rc; | ||
234 | } | 246 | } |
235 | /* return dos attributes as pseudo xattr */ | 247 | /* return dos attributes as pseudo xattr */ |
236 | /* return alt name if available as pseudo attr */ | 248 | /* return alt name if available as pseudo attr */ |
@@ -323,6 +335,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
323 | get_ea_exit: | 335 | get_ea_exit: |
324 | kfree(full_path); | 336 | kfree(full_path); |
325 | FreeXid(xid); | 337 | FreeXid(xid); |
338 | cifs_put_tlink(tlink); | ||
326 | #endif | 339 | #endif |
327 | return rc; | 340 | return rc; |
328 | } | 341 | } |
@@ -333,6 +346,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
333 | #ifdef CONFIG_CIFS_XATTR | 346 | #ifdef CONFIG_CIFS_XATTR |
334 | int xid; | 347 | int xid; |
335 | struct cifs_sb_info *cifs_sb; | 348 | struct cifs_sb_info *cifs_sb; |
349 | struct tcon_link *tlink; | ||
336 | struct cifsTconInfo *pTcon; | 350 | struct cifsTconInfo *pTcon; |
337 | struct super_block *sb; | 351 | struct super_block *sb; |
338 | char *full_path; | 352 | char *full_path; |
@@ -346,18 +360,20 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
346 | return -EIO; | 360 | return -EIO; |
347 | 361 | ||
348 | cifs_sb = CIFS_SB(sb); | 362 | cifs_sb = CIFS_SB(sb); |
349 | pTcon = cifs_sb_tcon(cifs_sb); | ||
350 | |||
351 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 363 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
352 | return -EOPNOTSUPP; | 364 | return -EOPNOTSUPP; |
353 | 365 | ||
366 | tlink = cifs_sb_tlink(cifs_sb); | ||
367 | if (IS_ERR(tlink)) | ||
368 | return PTR_ERR(tlink); | ||
369 | pTcon = tlink_tcon(tlink); | ||
370 | |||
354 | xid = GetXid(); | 371 | xid = GetXid(); |
355 | 372 | ||
356 | full_path = build_path_from_dentry(direntry); | 373 | full_path = build_path_from_dentry(direntry); |
357 | if (full_path == NULL) { | 374 | if (full_path == NULL) { |
358 | rc = -ENOMEM; | 375 | rc = -ENOMEM; |
359 | FreeXid(xid); | 376 | goto list_ea_exit; |
360 | return rc; | ||
361 | } | 377 | } |
362 | /* return dos attributes as pseudo xattr */ | 378 | /* return dos attributes as pseudo xattr */ |
363 | /* return alt name if available as pseudo attr */ | 379 | /* return alt name if available as pseudo attr */ |
@@ -370,8 +386,10 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
370 | cifs_sb->mnt_cifs_flags & | 386 | cifs_sb->mnt_cifs_flags & |
371 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 387 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
372 | 388 | ||
389 | list_ea_exit: | ||
373 | kfree(full_path); | 390 | kfree(full_path); |
374 | FreeXid(xid); | 391 | FreeXid(xid); |
392 | cifs_put_tlink(tlink); | ||
375 | #endif | 393 | #endif |
376 | return rc; | 394 | return rc; |
377 | } | 395 | } |