diff options
author | Krutika Dhananjay <kdhananj@redhat.com> | 2017-01-17 16:40:04 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2018-08-18 07:28:53 +0000 |
commit | c9bde3021202f1d5c5a2d19ac05a510fc1f788ac (patch) | |
tree | eba54e5f791b33d079afae9655d5438d007c3091 /xlators/performance/readdir-ahead/src/readdir-ahead.h | |
parent | 045d70a5450daa85aa5564b6e9f93065c342ab12 (diff) |
performance/readdir-ahead: keep stats of cached dentries in sync with modifications
PROBLEM:
Stats of dentries that are readdirp'd ahead can become stale due to
fops like writes, truncate etc that modify the file pointed by
dentries. When a readdir is finally wound at offset corresponding to
these entries, the iatts that are returned to the application come
from readdir-ahead's cache, which are stale by now. This problem gets
further aggravated when caching translators/modules cache and continue
to serve this stale information.
FIX:
* Store the iatt in context of the inode pointed by dentry.
* Whenever the inode pointed by dentry undergoes modification, in cbk
of modification fop, update the iatt stored in inode-ctx to reflect
the modification.
* When serving a readdirp response from application, update iatts of
dentries with the iatts stored in the context of inodes pointed by
these dentries.
* Some fops don't have valid iatts in their responses. For eg., write
response whose data is still cached in write-behind will have zeroed
out stat. In this case keep only ia_type and ia_gfid and reset rest
of the iatt members to zero.
- fuse-bridge in this case just sends "entry" information back to
kernel and attr is not sent.
- gfapi sets entry->inode to NULL and zeroes out the entire stat
* There is one tiny race between the entry creation and a readdirp on
its parent dir, which could cause the inode-ctx setting and inode
ctx reading to happen on two different inode objects. To prevent
this, when entry->inode doesn't eqaul to linked_inode,
- fuse-bridge is made to send only "entry" information without
attributes
- gfapi sets entry->inode to NULL and zeroes out the entire stat.
Change-Id: Ia27ff49a61922e88c73a1547ad8aacc9968a69df
BUG: 1390050
Updates: bz#1390050
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/performance/readdir-ahead/src/readdir-ahead.h')
-rw-r--r-- | xlators/performance/readdir-ahead/src/readdir-ahead.h | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/xlators/performance/readdir-ahead/src/readdir-ahead.h b/xlators/performance/readdir-ahead/src/readdir-ahead.h index 3c06cc0f107..7dbed4c60ed 100644 --- a/xlators/performance/readdir-ahead/src/readdir-ahead.h +++ b/xlators/performance/readdir-ahead/src/readdir-ahead.h @@ -19,6 +19,44 @@ #define RDA_FD_BYPASS (1 << 4) #define RDA_FD_PLUGGED (1 << 5) + +#define RDA_COMMON_MODIFICATION_FOP(name, frame, this, __inode, __xdata, args ...)\ + do { \ + struct rda_local *__local = NULL; \ + rda_inode_ctx_t *ctx_p = NULL; \ + \ + __local = mem_get0 (this->local_pool); \ + __local->inode = inode_ref (__inode); \ + LOCK (&__inode->lock); \ + { \ + ctx_p = __rda_inode_ctx_get (__inode, this); \ + } \ + UNLOCK (&__inode->lock); \ + __local->generation = GF_ATOMIC_GET (ctx_p->generation); \ + \ + frame->local = __local; \ + if (__xdata) \ + __local->xattrs = dict_ref (__xdata); \ + \ + STACK_WIND (frame, rda_##name##_cbk, FIRST_CHILD(this), \ + FIRST_CHILD(this)->fops->name, args, __xdata); \ + } while (0) + + +#define RDA_STACK_UNWIND(fop, frame, params ...) do { \ + struct rda_local *__local = NULL; \ + if (frame) { \ + __local = frame->local; \ + frame->local = NULL; \ + } \ + STACK_UNWIND_STRICT (fop, frame, params); \ + if (__local) { \ + rda_local_wipe (__local); \ + mem_put (__local); \ + } \ +} while (0) + + struct rda_fd_ctx { off_t cur_offset; /* current head of the ctx */ size_t cur_size; /* current size of the preload */ @@ -34,9 +72,12 @@ struct rda_fd_ctx { struct rda_local { struct rda_fd_ctx *ctx; - fd_t *fd; - off_t offset; - dict_t *xattrs; /* xattrs to be sent in readdirp() */ + fd_t *fd; + dict_t *xattrs; /* md-cache keys to be sent in readdirp() */ + inode_t *inode; + off_t offset; + uint64_t generation; + int32_t skip_dir; }; struct rda_priv { @@ -48,4 +89,9 @@ struct rda_priv { gf_boolean_t parallel_readdir; }; +typedef struct rda_inode_ctx { + struct iatt statbuf; + gf_atomic_t generation; +} rda_inode_ctx_t; + #endif /* __READDIR_AHEAD_H */ |