diff options
| -rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 21 |
2 files changed, 20 insertions, 2 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index ecf0ffbe2b64..0c2fd17439c8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -502,6 +502,7 @@ struct dfs_info3_param { | |||
| 502 | #define CIFS_FATTR_DFS_REFERRAL 0x1 | 502 | #define CIFS_FATTR_DFS_REFERRAL 0x1 |
| 503 | #define CIFS_FATTR_DELETE_PENDING 0x2 | 503 | #define CIFS_FATTR_DELETE_PENDING 0x2 |
| 504 | #define CIFS_FATTR_NEED_REVAL 0x4 | 504 | #define CIFS_FATTR_NEED_REVAL 0x4 |
| 505 | #define CIFS_FATTR_INO_COLLISION 0x8 | ||
| 505 | 506 | ||
| 506 | struct cifs_fattr { | 507 | struct cifs_fattr { |
| 507 | u32 cf_flags; | 508 | u32 cf_flags; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35ec11716213..29b9ea244c81 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -715,6 +715,16 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
| 715 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | 715 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
| 716 | return 0; | 716 | return 0; |
| 717 | 717 | ||
| 718 | /* | ||
| 719 | * uh oh -- it's a directory. We can't use it since hardlinked dirs are | ||
| 720 | * verboten. Disable serverino and return it as if it were found, the | ||
| 721 | * caller can discard it, generate a uniqueid and retry the find | ||
| 722 | */ | ||
| 723 | if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { | ||
| 724 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; | ||
| 725 | cifs_autodisable_serverino(CIFS_SB(inode->i_sb)); | ||
| 726 | } | ||
| 727 | |||
| 718 | return 1; | 728 | return 1; |
| 719 | } | 729 | } |
| 720 | 730 | ||
| @@ -734,15 +744,22 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | |||
| 734 | unsigned long hash; | 744 | unsigned long hash; |
| 735 | struct inode *inode; | 745 | struct inode *inode; |
| 736 | 746 | ||
| 747 | retry_iget5_locked: | ||
| 737 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | 748 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); |
| 738 | 749 | ||
| 739 | /* hash down to 32-bits on 32-bit arch */ | 750 | /* hash down to 32-bits on 32-bit arch */ |
| 740 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | 751 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); |
| 741 | 752 | ||
| 742 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | 753 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); |
| 743 | |||
| 744 | /* we have fattrs in hand, update the inode */ | ||
| 745 | if (inode) { | 754 | if (inode) { |
| 755 | /* was there a problematic inode number collision? */ | ||
| 756 | if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { | ||
| 757 | iput(inode); | ||
| 758 | fattr->cf_uniqueid = iunique(sb, ROOT_I); | ||
| 759 | fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; | ||
| 760 | goto retry_iget5_locked; | ||
| 761 | } | ||
| 762 | |||
| 746 | cifs_fattr_to_inode(inode, fattr); | 763 | cifs_fattr_to_inode(inode, fattr); |
| 747 | if (sb->s_flags & MS_NOATIME) | 764 | if (sb->s_flags & MS_NOATIME) |
| 748 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | 765 | inode->i_flags |= S_NOATIME | S_NOCMTIME; |
