Re: [PATCH v2] readdir cf_nlink initialization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 7 Sep 2013 14:49:24 -0400
Jim McDonough <jmcd@xxxxxxxxx> wrote:

> Here's my second try.  I hope there aren't missed ops which update the
> inode without having nlink updated.  At worst, they should stop
> clobbering valid values, which was definitely happening before.
> 
> Signed-off-by: Jim McDonough <jmcdonough@xxxxxxx>
> 
> ---
>  fs/cifs/cifsglob.h |    1 +
>  fs/cifs/inode.c    |   21 ++++++++++++++++++++-
>  fs/cifs/readdir.c  |    3 +++
>  3 files changed, 24 insertions(+), 1 deletion(-)
> 
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -712,6 +712,7 @@ struct dfs_info3_param {
>  #define CIFS_FATTR_DELETE_PENDING    0x2
>  #define CIFS_FATTR_NEED_REVAL        0x4
>  #define CIFS_FATTR_INO_COLLISION    0x8
> +#define CIFS_FATTR_MISSING_NLINK    0x10
> 
>  struct cifs_fattr {
>      u32        cf_flags;
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -118,6 +118,25 @@ cifs_revalidate_cache(struct inode *inod
>      cifs_i->invalid_mapping = true;
>  }
> 
> +/* copy nlink to the inode, unless it wasn't provided.  Provide
> +   sane values if we don't have an existing one and none was provided */
> +static void
> +cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
> +{
> +    if (fattr->cf_nlink) {
> +        inode->i_nlink = fattr->cf_nlink;
> +        return;
> +    }
> +

I think it would be best to get rid of the above if block and add an
else block to the end of the following if clause that just sets
inode->i_nlink = fattr->cf_nlink unconditionally.

The problem with the logic here is that you're ignoring the
(legitimate) case where cf_nlink might be 0 as reported by the server.

> +    if ((fattr->cf_flags & CIFS_FATTR_MISSING_NLINK) &&
> +        (inode->i_state & I_NEW)) {
> +        if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
> +            inode->i_nlink = 2;
> +        else
> +            inode->i_nlink = 1;
> +    }
> +}
> +
>  /* populate an inode with info from a cifs_fattr struct */
>  void
>  cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
> @@ -132,7 +151,7 @@ cifs_fattr_to_inode(struct inode *inode,
>      inode->i_mtime = fattr->cf_mtime;
>      inode->i_ctime = fattr->cf_ctime;
>      inode->i_rdev = fattr->cf_rdev;
> -    inode->i_nlink = fattr->cf_nlink;
> +    cifs_nlink_fattr_to_inode(inode, fattr);
>      inode->i_uid = fattr->cf_uid;
>      inode->i_gid = fattr->cf_gid;
> 
> --- a/fs/cifs/readdir.c
> +++ b/fs/cifs/readdir.c
> @@ -130,6 +130,9 @@ cifs_fill_common_info(struct cifs_fattr
>          fattr->cf_dtype = DT_REG;
>      }
> 
> +    /* non-unix readdir doesn't provide nlink */
> +    fattr->cf_flags &= CIFS_FATTR_MISSING_NLINK;
> +

Shouldn't that be "|=" ?

>      if (fattr->cf_cifsattrs & ATTR_READONLY)
>          fattr->cf_mode &= ~S_IWUGO;
> 
> 
> 
> 

The only other thing I see is that the code in cifs_all_info_to_fattr
ought to be changed to use this flag and not try to fake up the
cf_nlink value.

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




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux