Commit e9792be1 authored by Lai Siyao's avatar Lai Siyao Committed by Greg Kroah-Hartman

staging: lustre: statahead: statahead thread wait for RPCs to finish

Statahead thread should wait for inflight stat RPCs to finish in
case statahead RPC callback may access data allocated in statahead
thread context.

ll_sa_entry_fini() should keep old entry if stat RPC is not
finished yet.

Simplify sai refcounting:
* newly allocated sai will hold one refcount, and it will put it
  after starting statahead thread.
* statahead thread holds one refcount.
* agl thread holds one refcount.
* stat process calls do_statahead_enter() which will try to get
  sai, and if it's valid, it will revalidate from statahead cache,
  and put refcount after use.
Signed-off-by: default avatarLai Siyao <lai.siyao@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3270
Reviewed-on: http://review.whamcloud.com/9663Reviewed-by: default avatarFan Yong <fan.yong@intel.com>
Reviewed-by: default avatarJames Simmons <uja.ornl@gmail.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d38a48e5
...@@ -806,7 +806,6 @@ struct md_enqueue_info { ...@@ -806,7 +806,6 @@ struct md_enqueue_info {
int (*mi_cb)(struct ptlrpc_request *req, int (*mi_cb)(struct ptlrpc_request *req,
struct md_enqueue_info *minfo, int rc); struct md_enqueue_info *minfo, int rc);
__u64 mi_cbdata; __u64 mi_cbdata;
unsigned int mi_generation;
}; };
struct obd_ops { struct obd_ops {
......
...@@ -279,7 +279,7 @@ static int ll_revalidate_dentry(struct dentry *dentry, ...@@ -279,7 +279,7 @@ static int ll_revalidate_dentry(struct dentry *dentry,
if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE)) if (lookup_flags & (LOOKUP_PARENT | LOOKUP_OPEN | LOOKUP_CREATE))
return 1; return 1;
if (d_need_statahead(dir, dentry) <= 0) if (!dentry_need_statahead(dir, dentry))
return 1; return 1;
if (lookup_flags & LOOKUP_RCU) if (lookup_flags & LOOKUP_RCU)
......
...@@ -351,13 +351,11 @@ int ll_file_release(struct inode *inode, struct file *file) ...@@ -351,13 +351,11 @@ int ll_file_release(struct inode *inode, struct file *file)
fd = LUSTRE_FPRIVATE(file); fd = LUSTRE_FPRIVATE(file);
LASSERT(fd); LASSERT(fd);
/* The last ref on @file, maybe not be the owner pid of statahead. /* The last ref on @file, maybe not be the owner pid of statahead,
* Different processes can open the same dir, "ll_opendir_key" means: * because parent and child process can share the same file handle.
* it is me that should stop the statahead thread.
*/ */
if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd && if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd)
lli->lli_opendir_pid != 0) ll_deauthorize_statahead(inode, fd);
ll_stop_statahead(inode, lli->lli_opendir_key);
if (is_root_inode(inode)) { if (is_root_inode(inode)) {
LUSTRE_FPRIVATE(file) = NULL; LUSTRE_FPRIVATE(file) = NULL;
...@@ -530,7 +528,7 @@ int ll_file_open(struct inode *inode, struct file *file) ...@@ -530,7 +528,7 @@ int ll_file_open(struct inode *inode, struct file *file)
struct obd_client_handle **och_p = NULL; struct obd_client_handle **och_p = NULL;
__u64 *och_usecount = NULL; __u64 *och_usecount = NULL;
struct ll_file_data *fd; struct ll_file_data *fd;
int rc = 0, opendir_set = 0; int rc = 0;
CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n", CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), flags %o\n",
PFID(ll_inode2fid(inode)), inode, file->f_flags); PFID(ll_inode2fid(inode)), inode, file->f_flags);
...@@ -545,16 +543,8 @@ int ll_file_open(struct inode *inode, struct file *file) ...@@ -545,16 +543,8 @@ int ll_file_open(struct inode *inode, struct file *file)
} }
fd->fd_file = file; fd->fd_file = file;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode))
spin_lock(&lli->lli_sa_lock); ll_authorize_statahead(inode, fd);
if (!lli->lli_opendir_key && !lli->lli_sai &&
lli->lli_opendir_pid == 0) {
lli->lli_opendir_key = fd;
lli->lli_opendir_pid = current_pid();
opendir_set = 1;
}
spin_unlock(&lli->lli_sa_lock);
}
if (is_root_inode(inode)) { if (is_root_inode(inode)) {
LUSTRE_FPRIVATE(file) = fd; LUSTRE_FPRIVATE(file) = fd;
...@@ -713,9 +703,10 @@ int ll_file_open(struct inode *inode, struct file *file) ...@@ -713,9 +703,10 @@ int ll_file_open(struct inode *inode, struct file *file)
mutex_unlock(&lli->lli_och_mutex); mutex_unlock(&lli->lli_och_mutex);
out_openerr: out_openerr:
if (opendir_set != 0) if (lli->lli_opendir_key == fd)
ll_stop_statahead(inode, lli->lli_opendir_key); ll_deauthorize_statahead(inode, fd);
ll_file_data_put(fd); if (fd)
ll_file_data_put(fd);
} else { } else {
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1);
} }
......
...@@ -172,6 +172,13 @@ struct ll_inode_info { ...@@ -172,6 +172,13 @@ struct ll_inode_info {
* -- I am the owner of dir statahead. * -- I am the owner of dir statahead.
*/ */
pid_t d_opendir_pid; pid_t d_opendir_pid;
/* stat will try to access statahead entries or start
* statahead if this flag is set, and this flag will be
* set upon dir open, and cleared when dir is closed,
* statahead hit ratio is too low, or start statahead
* thread failed.
*/
unsigned int d_sa_enabled:1;
/* directory stripe information */ /* directory stripe information */
struct lmv_stripe_md *d_lsm_md; struct lmv_stripe_md *d_lsm_md;
/* striped directory size */ /* striped directory size */
...@@ -184,6 +191,7 @@ struct ll_inode_info { ...@@ -184,6 +191,7 @@ struct ll_inode_info {
#define lli_opendir_key u.d.d_opendir_key #define lli_opendir_key u.d.d_opendir_key
#define lli_sai u.d.d_sai #define lli_sai u.d.d_sai
#define lli_sa_lock u.d.d_sa_lock #define lli_sa_lock u.d.d_sa_lock
#define lli_sa_enabled u.d.d_sa_enabled
#define lli_opendir_pid u.d.d_opendir_pid #define lli_opendir_pid u.d.d_opendir_pid
#define lli_lsm_md u.d.d_lsm_md #define lli_lsm_md u.d.d_lsm_md
#define lli_stripe_dir_size u.d.d_stripe_size #define lli_stripe_dir_size u.d.d_stripe_size
...@@ -495,6 +503,9 @@ struct ll_sb_info { ...@@ -495,6 +503,9 @@ struct ll_sb_info {
atomic_t ll_sa_wrong; /* statahead thread stopped for atomic_t ll_sa_wrong; /* statahead thread stopped for
* low hit ratio * low hit ratio
*/ */
atomic_t ll_sa_running; /* running statahead thread
* count
*/
atomic_t ll_agl_total; /* AGL thread started count */ atomic_t ll_agl_total; /* AGL thread started count */
dev_t ll_sdev_orig; /* save s_dev before assign for dev_t ll_sdev_orig; /* save s_dev before assign for
...@@ -1040,7 +1051,8 @@ struct ll_statahead_info { ...@@ -1040,7 +1051,8 @@ struct ll_statahead_info {
int do_statahead_enter(struct inode *dir, struct dentry **dentry, int do_statahead_enter(struct inode *dir, struct dentry **dentry,
int only_unplug); int only_unplug);
void ll_stop_statahead(struct inode *dir, void *key); void ll_authorize_statahead(struct inode *dir, void *key);
void ll_deauthorize_statahead(struct inode *dir, void *key);
blkcnt_t dirty_cnt(struct inode *inode); blkcnt_t dirty_cnt(struct inode *inode);
...@@ -1086,25 +1098,31 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry) ...@@ -1086,25 +1098,31 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry)
ldd->lld_sa_generation = sai->sai_generation; ldd->lld_sa_generation = sai->sai_generation;
} }
static inline int static inline bool
d_need_statahead(struct inode *dir, struct dentry *dentryp) dentry_need_statahead(struct inode *dir, struct dentry *dentry)
{ {
struct ll_inode_info *lli; struct ll_inode_info *lli;
struct ll_dentry_data *ldd; struct ll_dentry_data *ldd;
if (ll_i2sbi(dir)->ll_sa_max == 0) if (ll_i2sbi(dir)->ll_sa_max == 0)
return -EAGAIN; return false;
lli = ll_i2info(dir); lli = ll_i2info(dir);
/*
* statahead is not allowed for this dir, there may be three causes:
* 1. dir is not opened.
* 2. statahead hit ratio is too low.
* 3. previous stat started statahead thread failed.
*/
if (!lli->lli_sa_enabled)
return false;
/* not the same process, don't statahead */ /* not the same process, don't statahead */
if (lli->lli_opendir_pid != current_pid()) if (lli->lli_opendir_pid != current_pid())
return -EAGAIN; return false;
/* statahead has been stopped */
if (!lli->lli_opendir_key)
return -EAGAIN;
ldd = ll_d2d(dentryp); ldd = ll_d2d(dentry);
/* /*
* When stats a dentry, the system trigger more than once "revalidate" * When stats a dentry, the system trigger more than once "revalidate"
* or "lookup", for "getattr", for "getxattr", and maybe for others. * or "lookup", for "getattr", for "getxattr", and maybe for others.
...@@ -1122,19 +1140,16 @@ d_need_statahead(struct inode *dir, struct dentry *dentryp) ...@@ -1122,19 +1140,16 @@ d_need_statahead(struct inode *dir, struct dentry *dentryp)
*/ */
if (ldd && lli->lli_sai && if (ldd && lli->lli_sai &&
ldd->lld_sa_generation == lli->lli_sai->sai_generation) ldd->lld_sa_generation == lli->lli_sai->sai_generation)
return -EAGAIN; return false;
return 1; return true;
} }
static inline int static inline int
ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug)
{ {
int ret; if (!dentry_need_statahead(dir, *dentryp))
return -EAGAIN;
ret = d_need_statahead(dir, *dentryp);
if (ret <= 0)
return ret;
return do_statahead_enter(dir, dentryp, only_unplug); return do_statahead_enter(dir, dentryp, only_unplug);
} }
......
...@@ -116,6 +116,7 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb) ...@@ -116,6 +116,7 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb)
sbi->ll_sa_max = LL_SA_RPC_DEF; sbi->ll_sa_max = LL_SA_RPC_DEF;
atomic_set(&sbi->ll_sa_total, 0); atomic_set(&sbi->ll_sa_total, 0);
atomic_set(&sbi->ll_sa_wrong, 0); atomic_set(&sbi->ll_sa_wrong, 0);
atomic_set(&sbi->ll_sa_running, 0);
atomic_set(&sbi->ll_agl_total, 0); atomic_set(&sbi->ll_agl_total, 0);
sbi->ll_flags |= LL_SBI_AGL_ENABLED; sbi->ll_flags |= LL_SBI_AGL_ENABLED;
...@@ -630,6 +631,12 @@ void ll_kill_super(struct super_block *sb) ...@@ -630,6 +631,12 @@ void ll_kill_super(struct super_block *sb)
if (sbi) { if (sbi) {
sb->s_dev = sbi->ll_sdev_orig; sb->s_dev = sbi->ll_sdev_orig;
sbi->ll_umounting = 1; sbi->ll_umounting = 1;
/* wait running statahead threads to quit */
while (atomic_read(&sbi->ll_sa_running) > 0) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC >> 3));
}
} }
} }
...@@ -795,6 +802,7 @@ void ll_lli_init(struct ll_inode_info *lli) ...@@ -795,6 +802,7 @@ void ll_lli_init(struct ll_inode_info *lli)
lli->lli_sai = NULL; lli->lli_sai = NULL;
spin_lock_init(&lli->lli_sa_lock); spin_lock_init(&lli->lli_sa_lock);
lli->lli_opendir_pid = 0; lli->lli_opendir_pid = 0;
lli->lli_sa_enabled = 0;
} else { } else {
mutex_init(&lli->lli_size_mutex); mutex_init(&lli->lli_size_mutex);
lli->lli_symlink_name = NULL; lli->lli_symlink_name = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment