From: Donald Buczek <buczek@molgen.mpg.de>
To: Trond Myklebust <trond.myklebust@primarydata.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH] NFS: Fix attribute cache revalidation
Date: Wed, 30 Dec 2015 12:23:07 +0100 [thread overview]
Message-ID: <5683BE9B.3000006@molgen.mpg.de> (raw)
In-Reply-To: <1451433763-27093-1-git-send-email-trond.myklebust@primarydata.com>
On 30.12.2015 01:02, Trond Myklebust wrote:
> 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@molgen.mpg.de>
> Cc: stable@vger.kernel.org
> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
> ---
> Hi Donald,
>
> Can you please apply this on top of the other 2 patches and see if it
> fixes your access() testcase?
>
> Thanks!
>
>
> fs/nfs/inode.c | 51 +++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 37 insertions(+), 14 deletions(-)
>
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index c7e8b87da5b2..7431feeb16f1 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -1641,6 +1641,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,
> @@ -1702,22 +1703,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) {
> @@ -1737,19 +1744,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)) {
> @@ -1758,36 +1769,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) {
> @@ -1796,19 +1813,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) {
> @@ -1818,8 +1838,11 @@ 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))
> + if (cache_revalidated &&
> + !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;
> }
> @@ -1829,7 +1852,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 */
Hi, Trond,
your three patches
[PATCH] NFSv4: Don't perform cached access checks before we've OPENed
the file
[PATCH] NFS: Ensure we revalidate attributes before using execute_ok()
[PATCH] NFS: Fix attribute cache revalidation
applied to your github master fix the user-visible problems (exec and
access case). I currently don't have time to analyze the code or do more
testing than running my test script, though. I hope I can apply these on
our cluster nodes during the holiday and we'd have it on production
systems in January.
Btw: There is a little whitespace error in the last patch (space before
tab at the "} else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)" line).
Thank you very much & Happy New Year
Donald
--
Donald Buczek
buczek@molgen.mpg.de
Tel: +49 30 8413 1433
next prev parent reply other threads:[~2015-12-30 11:23 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-25 12:30 [PATCH] nfs: do not deny execute access based on outdated mode in inode Donald Buczek
2015-12-26 18:36 ` Trond Myklebust
2015-12-26 23:58 ` Donald Buczek
2015-12-27 0:11 ` Trond Myklebust
2015-12-27 0:38 ` Al Viro
2015-12-27 1:26 ` Trond Myklebust
2015-12-27 2:28 ` Al Viro
2015-12-27 2:54 ` Trond Myklebust
2015-12-27 3:06 ` [PATCH] NFSv4: Don't perform cached access checks before we've OPENed the file Trond Myklebust
2015-12-27 12:18 ` Donald Buczek
2015-12-27 16:23 ` Trond Myklebust
2015-12-27 17:57 ` Al Viro
2015-12-28 19:38 ` [PATCH] nfs: revalidate inode before access checks Donald Buczek
2015-12-28 21:10 ` Trond Myklebust
2015-12-29 0:40 ` [PATCH] NFS: Ensure we revalidate attributes before using execute_ok() Trond Myklebust
2015-12-29 19:51 ` Donald Buczek
2015-12-29 20:18 ` Trond Myklebust
2015-12-30 0:02 ` [PATCH] NFS: Fix attribute cache revalidation Trond Myklebust
2015-12-30 11:23 ` Donald Buczek [this message]
2015-12-30 14:04 ` Trond Myklebust
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5683BE9B.3000006@molgen.mpg.de \
--to=buczek@molgen.mpg.de \
--cc=linux-nfs@vger.kernel.org \
--cc=trond.myklebust@primarydata.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).