From c9bde3021202f1d5c5a2d19ac05a510fc1f788ac Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Tue, 17 Jan 2017 16:40:04 +0530 Subject: 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 Signed-off-by: Raghavendra G --- .../performance/readdir-ahead/src/readdir-ahead.h | 52 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'xlators/performance/readdir-ahead/src/readdir-ahead.h') 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 */ -- cgit