Re: [PATCH v4] readdir cf_nlink initialization

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

 



Merged into cifs-2.6.git, but required fixup because the patch was
based off an earlier kernel and did not merge cleanly (conflicted with
a small DFS fix in 3.11).   Also when you respun it you left off the
patch description, so I took it from parts of the earlier patch.

On Thu, Sep 19, 2013 at 12:39 PM, Jim McDonough <jmcd@xxxxxxxxx> wrote:
> Sigh, more comment fixup...
>
> From b575840809eb8fdad7c595202300414e25b7d286 Mon Sep 17 00:00:00 2001
> From: Jim McDonough <jmcd@xxxxxxxxx>
> Date: Thu, 19 Sep 2013 17:22:00 -0700
> Subject: Provide sane values for nlink
>
> Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>
> Reviewed-by: David Disseldorp <ddiss@xxxxxxxxx>
> ---
>  fs/cifs/cifsglob.h |  1 +
>  fs/cifs/inode.c    | 45 +++++++++++++++++++++++++++++++++++++++------
>  fs/cifs/readdir.c  |  3 +++
>  3 files changed, 43 insertions(+), 6 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 52ca861..750dbfa 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -1253,6 +1253,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_UNKNOWN_NLINK       0x10
>
>  struct cifs_fattr {
>         u32             cf_flags;
> diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
> index 449b6cf..b2f4831 100644
> --- a/fs/cifs/inode.c
> +++ b/fs/cifs/inode.c
> @@ -120,6 +120,33 @@ cifs_revalidate_cache(struct inode *inode, struct
> cifs_fattr *fattr)
>         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 we're in a situation where we can't trust what we
> +        * got from the server (readdir, some non-unix cases)
> +        * fake reasonable values
> +        */
> +       if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
> +               /* only provide fake values on a new inode */
> +               if (inode->i_state & I_NEW) {
> +                       if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
> +                               set_nlink(inode, 2);
> +                       else
> +                               set_nlink(inode, 1);
> +               }
> +               return;
> +       }
> +
> +       /* we trust the server, so update it */
> +       set_nlink(inode, fattr->cf_nlink);
> +}
> +
>  /* populate an inode with info from a cifs_fattr struct */
>  void
>  cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
> @@ -134,7 +161,7 @@ cifs_fattr_to_inode(struct inode *inode, struct
> cifs_fattr *fattr)
>         inode->i_mtime = fattr->cf_mtime;
>         inode->i_ctime = fattr->cf_ctime;
>         inode->i_rdev = fattr->cf_rdev;
> -       set_nlink(inode, fattr->cf_nlink);
> +       cifs_nlink_fattr_to_inode(inode, fattr);
>         inode->i_uid = fattr->cf_uid;
>         inode->i_gid = fattr->cf_gid;
>
> @@ -541,6 +568,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr,
> FILE_ALL_INFO *info,
>         fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
>         fattr->cf_createtime = le64_to_cpu(info->CreationTime);
>
> +       fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
>         if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
>                 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
>                 fattr->cf_dtype = DT_DIR;
> @@ -548,7 +576,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr,
> FILE_ALL_INFO *info,
>                  * Server can return wrong NumberOfLinks value for directories
>                  * when Unix extensions are disabled - fake it.
>                  */
> -               fattr->cf_nlink = 2;
> +               if (!tcon->unix_ext)
> +                       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
>         } else {
>                 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
>                 fattr->cf_dtype = DT_REG;
> @@ -557,11 +586,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr,
> FILE_ALL_INFO *info,
>                 if (fattr->cf_cifsattrs & ATTR_READONLY)
>                         fattr->cf_mode &= ~(S_IWUGO);
>
> -               fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
> -               if (fattr->cf_nlink < 1) {
> -                       cifs_dbg(1, "replacing bogus file nlink value %u\n",
> +               /*
> +                * Don't accept zero nlink from non-unix servers unless
> +                * delete is pending.  Instead mark it as unknown.
> +                */
> +               if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
> +                   !info->DeletePending) {
> +                       cifs_dbg(1, "bogus file nlink value %u\n",
>                                 fattr->cf_nlink);
> -                       fattr->cf_nlink = 1;
> +                       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
>                 }
>         }
>
> diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
> index 69d2c82..b1f67dc 100644
> --- a/fs/cifs/readdir.c
> +++ b/fs/cifs/readdir.c
> @@ -177,6 +177,9 @@ cifs_fill_common_info(struct cifs_fattr *fattr,
> struct cifs_sb_info *cifs_sb)
>                 fattr->cf_dtype = DT_REG;
>         }
>
> +       /* non-unix readdir doesn't provide nlink */
> +       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
> +
>         if (fattr->cf_cifsattrs & ATTR_READONLY)
>                 fattr->cf_mode &= ~S_IWUGO;
>
> --
> 1.8.1.4
>
>



-- 
Thanks,

Steve
--
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