[4.2.y-ckt stable] Patch "NFS: Fix attribute cache revalidation" has been added to the 4.2.y-ckt tree
Donald Buczek
buczek at molgen.mpg.de
Wed Jan 27 07:26:45 UTC 2016
On 01/27/16 01:10, Kamal Mostafa wrote:
> This is a note to let you know that I have just added a patch titled
>
> NFS: Fix attribute cache revalidation
>
> to the linux-4.2.y-queue branch of the 4.2.y-ckt extended stable tree
> which can be found at:
>
> http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-4.2.y-queue
>
> This patch is scheduled to be released in version 4.2.8-ckt3.
>
> If you, or anyone else, feels it should not be added to this tree, please
> reply to this email.
You might consider to include
NFS: Ensure we revalidate attributes before using execute_ok()
NFSv4: Don't perform cached access checks before we've OPENed the file
as well, as in combination they fix
https://bugzilla.kernel.org/show_bug.cgi?id=109771
Regards
Donald
>
> For more information about the 4.2.y-ckt tree, see
> https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
>
> Thanks.
> -Kamal
>
> ---8<------------------------------------------------------------
>
> From 37c95c36efa1173b25a53241362f100ed2e3baa8 Mon Sep 17 00:00:00 2001
> From: Trond Myklebust <trond.myklebust at primarydata.com>
> Date: Tue, 29 Dec 2015 18:55:19 -0500
> Subject: NFS: Fix attribute cache revalidation
>
> commit ade14a7df796d4e86bd9d181193c883a57b13db0 upstream.
>
> If a NFSv4 client uses the cache_consistency_bitmask in order to
> request only information about the change attribute, timestamps and
> size, then it has not revalidated all attributes, and hence the
> attribute timeout timestamp should not be updated.
>
> Reported-by: Donald Buczek <buczek at molgen.mpg.de>
> Signed-off-by: Trond Myklebust <trond.myklebust at primarydata.com>
> Signed-off-by: Kamal Mostafa <kamal at canonical.com>
> ---
> fs/nfs/inode.c | 54 +++++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 39 insertions(+), 15 deletions(-)
>
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index 1c65e3f..7bf2c65 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -1630,6 +1630,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> unsigned long invalid = 0;
> unsigned long now = jiffies;
> unsigned long save_cache_validity;
> + bool cache_revalidated = true;
>
> dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
> __func__, inode->i_sb->s_id, inode->i_ino,
> @@ -1691,22 +1692,28 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> nfs_force_lookup_revalidate(inode);
> inode->i_version = fattr->change_attr;
> }
> - } else
> + } else {
> nfsi->cache_validity |= save_cache_validity;
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
> memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
> - } else if (server->caps & NFS_CAP_MTIME)
> + } else if (server->caps & NFS_CAP_MTIME) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
> memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
> - } else if (server->caps & NFS_CAP_CTIME)
> + } else if (server->caps & NFS_CAP_CTIME) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> /* Check if our cached file size is stale */
> if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
> @@ -1726,19 +1733,23 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> (long long)cur_isize,
> (long long)new_isize);
> }
> - } else
> + } else {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_REVAL_PAGECACHE
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
>
> if (fattr->valid & NFS_ATTR_FATTR_ATIME)
> memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
> - else if (server->caps & NFS_CAP_ATIME)
> + else if (server->caps & NFS_CAP_ATIME) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATIME
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_MODE) {
> if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
> @@ -1747,36 +1758,42 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> inode->i_mode = newmode;
> invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
> }
> - } else if (server->caps & NFS_CAP_MODE)
> + } else if (server->caps & NFS_CAP_MODE) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_INVALID_ACCESS
> | NFS_INO_INVALID_ACL
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
> if (!uid_eq(inode->i_uid, fattr->uid)) {
> invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
> inode->i_uid = fattr->uid;
> }
> - } else if (server->caps & NFS_CAP_OWNER)
> + } else if (server->caps & NFS_CAP_OWNER) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_INVALID_ACCESS
> | NFS_INO_INVALID_ACL
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
> if (!gid_eq(inode->i_gid, fattr->gid)) {
> invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
> inode->i_gid = fattr->gid;
> }
> - } else if (server->caps & NFS_CAP_OWNER_GROUP)
> + } else if (server->caps & NFS_CAP_OWNER_GROUP) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_INVALID_ACCESS
> | NFS_INO_INVALID_ACL
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
> if (inode->i_nlink != fattr->nlink) {
> @@ -1785,19 +1802,22 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> invalid |= NFS_INO_INVALID_DATA;
> set_nlink(inode, fattr->nlink);
> }
> - } else if (server->caps & NFS_CAP_NLINK)
> + } else if (server->caps & NFS_CAP_NLINK) {
> nfsi->cache_validity |= save_cache_validity &
> (NFS_INO_INVALID_ATTR
> | NFS_INO_REVAL_FORCED);
> + cache_revalidated = false;
> + }
>
> if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
> /*
> * report the blocks in 512byte units
> */
> inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
> - }
> - if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
> + } else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
> inode->i_blocks = fattr->du.nfs2.blocks;
> + else
> + cache_revalidated = false;
>
> /* Update attrtimeo value if we're out of the unstable period */
> if (invalid & NFS_INO_INVALID_ATTR) {
> @@ -1807,9 +1827,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> /* Set barrier to be more recent than all outstanding updates */
> nfsi->attr_gencount = nfs_inc_attr_generation_counter();
> } else {
> - if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
> - if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
> - nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
> + if (cache_revalidated) {
> + if (!time_in_range_open(now, nfsi->attrtimeo_timestamp,
> + nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
> + nfsi->attrtimeo <<= 1;
> + if (nfsi->attrtimeo > NFS_MAXATTRTIMEO(inode))
> + nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
> + }
> nfsi->attrtimeo_timestamp = now;
> }
> /* Set the barrier to be more recent than this fattr */
> @@ -1818,7 +1842,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
> }
>
> /* Don't declare attrcache up to date if there were no attrs! */
> - if (fattr->valid != 0)
> + if (cache_revalidated)
> invalid &= ~NFS_INO_INVALID_ATTR;
>
> /* Don't invalidate the data if we were to blame */
> --
> 1.9.1
>
--
Donald Buczek
buczek at molgen.mpg.de
Tel: +49 30 8413 1433
More information about the kernel-team
mailing list