Skip to contentSkip to conversation

cifs: When "refer file directly", make new inode cache if "uniqueid is different"

PATCH Applied Nakajima Akira 5 participants 11 messages Dec 24, 2014 – May 20, 2015 8 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cifs: When "refer file directly", make new inode cache if "uniqueid is different"

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

fs/cifs/inode.c +9 -0
diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
 			rc = -ENOMEM;
 	} else {
 		/* we already have inode, update it */
+
+		/* if uniqueid is different, return error */
+		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+			rc = -ENOENT;
+			goto cgiiu_exit;
+		}
+
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
+cgiiu_exit:
 	return rc;
 }
 
Reviewed-by
#2 lore raw
In reply to a message not in the archive

Looks correct.

Quoted 46 lines · Nakajima Akira

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +9 -1
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                        rc = -ENOMEM;
        } else {
                /* we already have inode, update it */
+
+               /* if uniqueid is different, return error */
+               if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                   CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                       rc = -ENOENT;
+                       goto cgiiu_exit;
+               }
+
                cifs_fattr_to_inode(*pinode, &fattr);
        }
 
+cgiiu_exit:
        return rc;
 }
 
--

To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#3 lore raw
In reply to a message not in the archive
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
 			rc = -ENOMEM;
 	} else {
 		/* we already have inode, update it */
+
+		/* if uniqueid is different, return error */
+		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+			rc = -ENOENT;

fs/cifs/inode.c int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c +4 -0
+			goto cgiiu_exit;
+		}
+
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
+cgiiu_exit:
 	return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Signature · 1 line
Jeff Layton <[email protected]>
#5 lore raw
In reply to a message not in the archive
Quoted 49 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Quoted 5 lines

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

Signature · 3 lines
Thanks,

Steve
#7 lore raw
In reply to a message not in the archive
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

+ /* if filetype is different, return error */
+ if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+ (fattr.cf_mode & S_IFMT))) {
+ rc = -ENOENT;
+ goto cgiiu_exit;
+ }

#9 lore raw
In reply to a message not in the archive
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

Review

Quoted 6 lines
(quoted diff) +6 -0
+		/* if filetype is different, return error */
+		if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ENOENT;
+			goto cgiiu_exit;
+		}

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

Signature · 1 line
Jeff Layton <[email protected]>
#11 lore raw
In reply to a message not in the archive

I am not sure if ESTALE or ENOENT would have an effect on a dcache entry. A dcache entry and dentry are two different things, as I understand. In this case, dcache entry has not changed, what has changed is the dentry, specifically the inode it points to, so there is really no reason to purge and reinstate a dcache entry.

Quoted 91 lines · Jeff Layton
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

Review

Quoted 6 lines
(quoted diff) +6 -0
+             /* if filetype is different, return error */
+             if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                 (fattr.cf_mode & S_IFMT))) {
+                     rc = -ENOENT;
+                     goto cgiiu_exit;
+             }

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

--
Jeff Layton <[email protected]> --
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#13 lore raw
In reply to a message not in the archive
Quoted 2 lines · On Sun, 12 Apr 2015 23:24:59 -0500 Shirish Pargaonkar…

I am not sure if ESTALE or ENOENT would have an effect on a dcache entry. A dcache entry and dentry are two different things, as I understand.

Oh, in this case I was specifically referring to the kernel's cache of dentries as the dcache.

Quoted 4 lines

In this case, dcache entry has not changed, what has changed is the dentry, specifically the inode it points to, so there is really no reason to purge and reinstate a dcache entry.

No, the dentry has changed. We did an operation against the server and found that the underlying inode type is different.

In practical terms, the Linux dcache should handle that by dropping the old dentry and instantiating a new one. So, I think that returning ESTALE is a better error there since it should trigger the upper VFS layers to do just that.

Quoted 92 lines · Jeff Layton
Quoted 91 lines
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

Review

Quoted 6 lines
(quoted diff) +6 -0
+             /* if filetype is different, return error */
+             if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                 (fattr.cf_mode & S_IFMT))) {
+                     rc = -ENOENT;
+                     goto cgiiu_exit;
+             }

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

--
Jeff Layton <[email protected]> --
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 1 line
Jeff Layton <[email protected]>
author Reviewed-by Shirish Pargaonkar Reviewed-by Shirish Pargaonkar
#15 lore raw
In reply to a message not in the archive
Quoted 14 lines · Jeff Layton
Quoted 2 lines · On Sun, 12 Apr 2015 23:24:59 -0500 Shirish Pargaonkar…

I am not sure if ESTALE or ENOENT would have an effect on a dcache entry. A dcache entry and dentry are two different things, as I understand.

Oh, in this case I was specifically referring to the kernel's cache of dentries as the dcache.

Quoted 4 lines

In this case, dcache entry has not changed, what has changed is the dentry, specifically the inode it points to, so there is really no reason to purge and reinstate a dcache entry.

Quoted 96 lines

No, the dentry has changed. We did an operation against the server and found that the underlying inode type is different.

In practical terms, the Linux dcache should handle that by dropping the old dentry and instantiating a new one. So, I think that returning ESTALE is a better error there since it should trigger the upper VFS layers to do just that.

Quoted 88 lines · Jeff Layton
Quoted 87 lines
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

Review

Quoted 6 lines
(quoted diff) +6 -0
+             /* if filetype is different, return error */
+             if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                 (fattr.cf_mode & S_IFMT))) {
+                     rc = -ENOENT;
+                     goto cgiiu_exit;
+             }

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

--
Jeff Layton <[email protected]>

I fixed to return -ESTALE in cifs_get_inode_info_unix().

This case (ls <filename>, cat <filename>) passes through following paths. ls <filename>
-> lookup_fast
-> .d_revalidate
-> cifs_d_revalidate (even though EATALE or ENOENT, return 0)
-> cifs_revalidate_dentry
-> cifs_revalidate_dentry_attr
-> cifs_get_inode_info_unix (return ESTALE)

In either ESTALE or ENOENT, cifs_d_revalidate() returns 0.

I didn't find out
what commands path through
other passes not including cifs_d_revalidate().
(cifs_do_create, cifs_mknod, cifs_lookup, cifs_symlink, etc..)
But I checked that this patch works properly by various commands/patterns.

Quoted 1 line

From 0ff83baa2069c86aa35a8081cdb6e4f4380e66a1 Mon Sep 17 00:00:00 2001

From: Nakajima Akira <nakajima.akira-o7dWnD6vFTHqq2nvvmkE/[email protected]>
Date: Wed, 22 Apr 2015 15:24:44 +0900
Subject: [PATCH] Fix to check Unique id and FileType when client refer file directly.

When you refer file directly on cifs client,
(e.g. ls -li <filename>, cd <dir>, stat <filename>)
the function return old inode number and filetype from old inode cache, though server has different inode number or filetype.

When server is Windows, cifs client has same problem.
When Server is Windows
, This patch fixes bug in different filetype,
but does not fix bug in different inode number.
Because QUERY_PATH_INFO response by Windows does not include inode number(Index Number) .

BUG INFO
https://bugzilla.kernel.org/show_bug.cgi?id=90021
https://bugzilla.kernel.org/show_bug.cgi?id=90031

---
 fs/cifs/inode.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
fs/cifs/inode.c +25 -0
index 3e126d7..0d42354 100644
@@ -402,9 +402,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 			rc = -ENOMEM;
 	} else {
 		/* we already have inode, update it */
+
+		/* if uniqueid is different, return error */
+		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
+		/* if filetype is different, return error */
+		if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
+cgiiu_exit:
 	return rc;
 }
 
@@ -839,6 +855,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 		if (!*inode)
 			rc = -ENOMEM;
 	} else {
+		/* we already have inode, update it */
+
+		/* if filetype is different, return error */
+		if (unlikely(((*inode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgii_exit;
+		}
+
 		cifs_fattr_to_inode(*inode, &fattr);
 	}
 
Signature · 1 line
1.7.1

From 0ff83baa2069c86aa35a8081cdb6e4f4380e66a1 Mon Sep 17 00:00:00 2001
From: Nakajima Akira <[email protected]>
Date: Wed, 22 Apr 2015 15:24:44 +0900
Subject: [PATCH] Fix to check Unique id and FileType when client refer file directly.

When you refer file directly on cifs client,
(e.g. ls -li <filename>, cd <dir>, stat <filename>)
the function return old inode number and filetype from old inode cache, though server has different inode number or filetype.

When server is Windows, cifs client has same problem.
When Server is Windows
, This patch fixes bug in different filetype,
but does not fix bug in different inode number.
Because QUERY_PATH_INFO response by Windows does not include inode number(Index Number) .

BUG INFO
https://bugzilla.kernel.org/show_bug.cgi?id=90021
https://bugzilla.kernel.org/show_bug.cgi?id=90031

---
 fs/cifs/inode.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
fs/cifs/inode.c +25 -0
index 3e126d7..0d42354 100644
@@ -402,9 +402,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 			rc = -ENOMEM;
 	} else {
 		/* we already have inode, update it */
+
+		/* if uniqueid is different, return error */
+		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
+		/* if filetype is different, return error */
+		if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
+cgiiu_exit:
 	return rc;
 }
 
@@ -839,6 +855,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 		if (!*inode)
 			rc = -ENOMEM;
 	} else {
+		/* we already have inode, update it */
+
+		/* if filetype is different, return error */
+		if (unlikely(((*inode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgii_exit;
+		}
+
 		cifs_fattr_to_inode(*inode, &fattr);
 	}
 
Signature · 1 line
1.7.1
#16 lore raw

PATCH 1/1 cifs: When "refer file directly", make new inode cache if "uniqueid is different"

Adding linux-fsdevel since this case is similar to what other network/cluster fs have to deal with

---------- Forwarded message ----------
From: Nakajima Akira <[email protected]>
Date: Wed, Apr 22, 2015 at 1:31 AM
Subject: Re: [PATCH] cifs: When "refer file directly", make new inode cache if "uniqueid is different"
To: "[email protected]" <[email protected]>

Quoted 14 lines · Jeff Layton
Quoted 2 lines · On Sun, 12 Apr 2015 23:24:59 -0500 Shirish Pargaonkar…

I am not sure if ESTALE or ENOENT would have an effect on a dcache entry. A dcache entry and dentry are two different things, as I understand.

Oh, in this case I was specifically referring to the kernel's cache of dentries as the dcache.

Quoted 4 lines

In this case, dcache entry has not changed, what has changed is the dentry, specifically the inode it points to, so there is really no reason to purge and reinstate a dcache entry.

Quoted 96 lines

No, the dentry has changed. We did an operation against the server and found that the underlying inode type is different.

In practical terms, the Linux dcache should handle that by dropping the old dentry and instantiating a new one. So, I think that returning ESTALE is a better error there since it should trigger the upper VFS layers to do just that.

Quoted 88 lines · Jeff Layton
Quoted 87 lines
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira <[email protected]>…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

Review

Quoted 6 lines
(quoted diff) +6 -0
+             /* if filetype is different, return error */
+             if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                 (fattr.cf_mode & S_IFMT))) {
+                     rc = -ENOENT;
+                     goto cgiiu_exit;
+             }

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

--
Jeff Layton <[email protected]>

I fixed to return -ESTALE in cifs_get_inode_info_unix().

This case (ls <filename>, cat <filename>) passes through following paths. ls <filename>
-> lookup_fast
-> .d_revalidate
-> cifs_d_revalidate (even though EATALE or ENOENT, return 0)
-> cifs_revalidate_dentry
-> cifs_revalidate_dentry_attr
-> cifs_get_inode_info_unix (return ESTALE)

In either ESTALE or ENOENT, cifs_d_revalidate() returns 0.

I didn't find out
what commands path through
other passes not including cifs_d_revalidate().
(cifs_do_create, cifs_mknod, cifs_lookup, cifs_symlink, etc..)
But I checked that this patch works properly by various commands/patterns.

Quoted 1 line

From 0ff83baa2069c86aa35a8081cdb6e4f4380e66a1 Mon Sep 17 00:00:00 2001

From: Nakajima Akira <[email protected]>
Date: Wed, 22 Apr 2015 15:24:44 +0900
Subject: [PATCH] Fix to check Unique id and FileType when client refer file directly.

When you refer file directly on cifs client,
(e.g. ls -li <filename>, cd <dir>, stat <filename>)
the function return old inode number and filetype from old inode cache, though server has different inode number or filetype.

When server is Windows, cifs client has same problem. When Server is Windows
, This patch fixes bug in different filetype,
but does not fix bug in different inode number.
Because QUERY_PATH_INFO response by Windows does not include inode number(Index Number) .

BUG INFO
https://bugzilla.kernel.org/show_bug.cgi?id=90021
https://bugzilla.kernel.org/show_bug.cgi?id=90031

---
 fs/cifs/inode.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
fs/cifs/inode.c +16 -0
index 3e126d7..0d42354 100644
@@ -402,9 +402,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                        rc = -ENOMEM;
        } else {
                /* we already have inode, update it */
+
+               /* if uniqueid is different, return error */
+               if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                   CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                       rc = -ESTALE;
+                       goto cgiiu_exit;
+               }
+
+               /* if filetype is different, return error */
+               if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                   (fattr.cf_mode & S_IFMT))) {
+                       rc = -ESTALE;
+                       goto cgiiu_exit;
+               }
+
                cifs_fattr_to_inode(*pinode, &fattr);
        }
 
+cgiiu_exit:
        return rc;
 }
 
@@ -839,6 +855,15 @@ cifs_get_inode_info(struct inode **inode, const

char *full_path,

                if (!*inode)
                        rc = -ENOMEM;
        } else {

+ /* we already have inode, update it */
+
+ /* if filetype is different, return error */
+ if (unlikely(((*inode)->i_mode & S_IFMT) !=
+ (fattr.cf_mode & S_IFMT))) {
+ rc = -ESTALE;
+ goto cgii_exit;
+ }
+

                cifs_fattr_to_inode(*inode, &fattr);
        }

--
1.7.1

Signature · 3 lines
Thanks,

Steve

From 0ff83baa2069c86aa35a8081cdb6e4f4380e66a1 Mon Sep 17 00:00:00 2001
From: Nakajima Akira <[email protected]>
Date: Wed, 22 Apr 2015 15:24:44 +0900
Subject: [PATCH] Fix to check Unique id and FileType when client refer file directly.

When you refer file directly on cifs client,
(e.g. ls -li <filename>, cd <dir>, stat <filename>)
the function return old inode number and filetype from old inode cache, though server has different inode number or filetype.

When server is Windows, cifs client has same problem.
When Server is Windows
, This patch fixes bug in different filetype,
but does not fix bug in different inode number.
Because QUERY_PATH_INFO response by Windows does not include inode number(Index Number) .

BUG INFO
https://bugzilla.kernel.org/show_bug.cgi?id=90021
https://bugzilla.kernel.org/show_bug.cgi?id=90031

---
 fs/cifs/inode.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
fs/cifs/inode.c +25 -0
index 3e126d7..0d42354 100644
@@ -402,9 +402,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 			rc = -ENOMEM;
 	} else {
 		/* we already have inode, update it */
+
+		/* if uniqueid is different, return error */
+		if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+		    CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
+		/* if filetype is different, return error */
+		if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgiiu_exit;
+		}
+
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
+cgiiu_exit:
 	return rc;
 }
 
@@ -839,6 +855,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 		if (!*inode)
 			rc = -ENOMEM;
 	} else {
+		/* we already have inode, update it */
+
+		/* if filetype is different, return error */
+		if (unlikely(((*inode)->i_mode & S_IFMT) !=
+		    (fattr.cf_mode & S_IFMT))) {
+			rc = -ESTALE;
+			goto cgii_exit;
+		}
+
 		cifs_fattr_to_inode(*inode, &fattr);
 	}
 
Signature · 1 line
1.7.1
Applied
#18 lore raw
In reply to a message not in the archive

Merged into cifs-2.6.git for-next

Quoted 213 lines · Nakajima Akira
Quoted 14 lines · Jeff Layton
Quoted 2 lines · On Sun, 12 Apr 2015 23:24:59 -0500 Shirish Pargaonkar…

I am not sure if ESTALE or ENOENT would have an effect on a dcache entry. A dcache entry and dentry are two different things, as I understand.

Oh, in this case I was specifically referring to the kernel's cache of dentries as the dcache.

Quoted 4 lines

In this case, dcache entry has not changed, what has changed is the dentry, specifically the inode it points to, so there is really no reason to purge and reinstate a dcache entry.

Quoted 96 lines

No, the dentry has changed. We did an operation against the server and found that the underlying inode type is different.

In practical terms, the Linux dcache should handle that by dropping the old dentry and instantiating a new one. So, I think that returning ESTALE is a better error there since it should trigger the upper VFS layers to do just that.

Quoted 88 lines · Jeff Layton
Quoted 87 lines
Quoted 67 lines · On Thu, 9 Apr 2015 17:07:56 +0900 Nakajima Akira…
Quoted 53 lines · Steve French
Quoted 52 lines · Jeff Layton
Quoted 32 lines · On Wed, 24 Dec 2014 11:27:38 +0900 Nakajima Akira…

When refer file "directly" (e.g. ls -li <filename>),
if file is same name, old inode cache is used.
This causes that client shows wrong(old) inode number. So this patch is that if uniqueid is different, return error.

## But this patch is applicable to when Server is UNIX. ## When Server is Windows, we need another new patch.

Reproducible sample :
1. create file 'a' at cifs client.
2. rm 'a' and touch 'b a' at server.
3. ls -li 'a' at client, then client shows wrong(old) inode number.

Bug link:
https://bugzilla.kernel.org/show_bug.cgi?id=90021

diff -uprN -X linux-3.18-vanilla/Documentation/dontdiff linux-3.18-vanilla/fs/cifs/inode.c linux-3.18/fs/cifs/inode.c

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +5 -0
@@ -402,9 +402,18 @@ int cifs_get_inode_info_unix(struct inod
                      rc = -ENOMEM;
      } else {
              /* we already have inode, update it */
+
+             /* if uniqueid is different, return error */
+             if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                     rc = -ENOENT;

fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 int cifs_get_inode_info_unix(struct inod · line 419

Quoted 10 lines
fs/cifs/inode.c 2014-12-19 11:07:59.127000000 +0900 renamed from fs/cifs/inode.c 2014-12-08 07:21:05.000000000 +0900 +4 -0
+                     goto cgiiu_exit;
+             }
+
              cifs_fattr_to_inode(*pinode, &fattr);
      }
 
+cgiiu_exit:
      return rc;
 }
 

Returning ENOENT here seems like the wrong error to me. That path does exist, it just no longer refers to the same file as before.

Maybe ESTALE would be better as it would allow the VFS layer to revalidate the dcache and invalidate the old dentry?

Quoted 7 lines
Quoted 2 lines

--
Jeff Layton <[email protected]>

Similar to what Jeff mentioned, isn't the nfs_relavidate_inode path roughly equivalent to what we want here (where nfs.ko returns ESTALE on various cases where we detect an inode that doesn't match what we expect)?

If uniqueid is different, return -ESTALE.
If filetype is different, return -ENOENT.
That's right?

fs/cifs/inode.c int cifs_get_inode_info_unix(struct inode **pinode, · line 418

Quoted 6 lines
fs/cifs/inode.c +6 -0
+             /* if filetype is different, return error */
+             if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                 (fattr.cf_mode & S_IFMT))) {
+                     rc = -ENOENT;
+                     goto cgiiu_exit;
+             }

No, I don't think so. In both cases, the dcache is wrong and the dentry should be dropped and reinstantiated to point to a new inode. An ESTALE return is the trigger for that to occur. An ENOENT return is going to mean a stat() failure in your testcase, I think.

So I think you want to return ESTALE in both cases. That said, please do test it and ensure that it does the right thing.

--
Jeff Layton <[email protected]>

I fixed to return -ESTALE in cifs_get_inode_info_unix().

This case (ls <filename>, cat <filename>) passes through following paths. ls <filename>
-> lookup_fast
-> .d_revalidate
-> cifs_d_revalidate (even though EATALE or ENOENT, return 0)
-> cifs_revalidate_dentry
-> cifs_revalidate_dentry_attr
-> cifs_get_inode_info_unix (return ESTALE)

In either ESTALE or ENOENT, cifs_d_revalidate() returns 0.

I didn't find out
what commands path through
other passes not including cifs_d_revalidate().
(cifs_do_create, cifs_mknod, cifs_lookup, cifs_symlink, etc..)
But I checked that this patch works properly by various commands/patterns.

From 0ff83baa2069c86aa35a8081cdb6e4f4380e66a1 Mon Sep 17 00:00:00 2001
From: Nakajima Akira <nakajima.akira-o7dWnD6vFTHqq2nvvmkE/[email protected]>
Date: Wed, 22 Apr 2015 15:24:44 +0900
Subject: [PATCH] Fix to check Unique id and FileType when client refer file directly.

When you refer file directly on cifs client,
(e.g. ls -li <filename>, cd <dir>, stat <filename>)
the function return old inode number and filetype from old inode cache, though server has different inode number or filetype.

When server is Windows, cifs client has same problem.
When Server is Windows
, This patch fixes bug in different filetype,
but does not fix bug in different inode number.
Because QUERY_PATH_INFO response by Windows does not include inode number(Index Number) .

BUG INFO
https://bugzilla.kernel.org/show_bug.cgi?id=90021
https://bugzilla.kernel.org/show_bug.cgi?id=90031

---
 fs/cifs/inode.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
fs/cifs/inode.c +25 -1
index 3e126d7..0d42354 100644
@@ -402,9 +402,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                        rc = -ENOMEM;
        } else {
                /* we already have inode, update it */
+
+               /* if uniqueid is different, return error */
+               if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+                   CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+                       rc = -ESTALE;
+                       goto cgiiu_exit;
+               }
+
+               /* if filetype is different, return error */
+               if (unlikely(((*pinode)->i_mode & S_IFMT) !=
+                   (fattr.cf_mode & S_IFMT))) {
+                       rc = -ESTALE;
+                       goto cgiiu_exit;
+               }
+
                cifs_fattr_to_inode(*pinode, &fattr);
        }
 
+cgiiu_exit:
        return rc;
 }
 
@@ -839,6 +855,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                if (!*inode)
                        rc = -ENOMEM;
        } else {
+               /* we already have inode, update it */
+
+               /* if filetype is different, return error */
+               if (unlikely(((*inode)->i_mode & S_IFMT) !=
+                   (fattr.cf_mode & S_IFMT))) {
+                       rc = -ESTALE;
+                       goto cgii_exit;
+               }
+
                cifs_fattr_to_inode(*inode, &fattr);
        }
 
--

1.7.1

Signature · 3 lines
Thanks,

Steve