int ll_rw_stats_on;
/* metadata stat-ahead */
+ unsigned int ll_sa_running_max;/* max concurrent
+ * statahead instances */
unsigned int ll_sa_max; /* max statahead RPCs */
atomic_t ll_sa_total; /* statahead thread started
* count */
#define LL_SA_RPC_MIN 2
#define LL_SA_RPC_DEF 32
-#define LL_SA_RPC_MAX 8192
+#define LL_SA_RPC_MAX 512
+
+/* XXX: If want to support more concurrent statahead instances,
+ * please consider to decentralize the RPC lists attached
+ * on related import, such as imp_{sending,delayed}_list.
+ * LU-11079 */
+#define LL_SA_RUNNING_MAX 256
+#define LL_SA_RUNNING_DEF 16
#define LL_SA_CACHE_BIT 5
#define LL_SA_CACHE_SIZE (1 << LL_SA_CACHE_BIT)
}
LPROC_SEQ_FOPS(ll_track_gid);
+static int ll_statahead_running_max_seq_show(struct seq_file *m, void *v)
+{
+ struct super_block *sb = m->private;
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
+
+ seq_printf(m, "%u\n", sbi->ll_sa_running_max);
+ return 0;
+}
+
+static ssize_t ll_statahead_running_max_seq_write(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ struct seq_file *m = file->private_data;
+ struct super_block *sb = m->private;
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
+ int rc;
+ __s64 val;
+
+ rc = lprocfs_str_to_s64(buffer, count, &val);
+ if (rc)
+ return rc;
+
+ if (val >= 0 || val <= LL_SA_RUNNING_MAX)
+ sbi->ll_sa_running_max = val;
+ else
+ CERROR("%s: bad statahead_running_max value %lld. Valid values "
+ "are in the range [0, %u]\n", ll_get_fsname(sb, NULL, 0),
+ val, LL_SA_RUNNING_MAX);
+
+ return count;
+}
+LPROC_SEQ_FOPS(ll_statahead_running_max);
+
static int ll_statahead_max_seq_show(struct seq_file *m, void *v)
{
struct super_block *sb = m->private;
size_t count, loff_t *off)
{
struct seq_file *m = file->private_data;
- struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private);
+ struct super_block *sb = m->private;
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
int rc;
__s64 val;
if (val >= 0 && val <= LL_SA_RPC_MAX)
sbi->ll_sa_max = val;
else
- CERROR("Bad statahead_max value %lld. Valid values are in "
- "the range [0, %d]\n", val, LL_SA_RPC_MAX);
+ CERROR("%s: bad statahead_max value %lld. Valid values are in "
+ "are in the range [0, %u]\n", ll_get_fsname(sb, NULL, 0),
+ val, LL_SA_RPC_MAX);
return count;
}
.fops = &ll_track_gid_fops },
{ .name = "statahead_max",
.fops = &ll_statahead_max_fops },
+ { .name = "statahead_running_max",
+ .fops = &ll_statahead_running_max_fops },
{ .name = "statahead_agl",
.fops = &ll_statahead_agl_fops },
{ .name = "statahead_stats",
struct ptlrpc_thread *thread;
struct l_wait_info lwi = { 0 };
struct task_struct *task;
- int rc;
+ struct ll_sb_info *sbi = ll_i2sbi(parent->d_inode);
+ int first = LS_FIRST_DE;
+ int rc = 0;
ENTRY;
/* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */
- rc = is_first_dirent(dir, dentry);
- if (rc == LS_NOT_FIRST_DE)
+ first = is_first_dirent(dir, dentry);
+ if (first == LS_NOT_FIRST_DE)
/* It is not "ls -{a}l" operation, no need statahead for it. */
GOTO(out, rc = -EFAULT);
+ if (unlikely(atomic_inc_return(&sbi->ll_sa_running) >
+ sbi->ll_sa_running_max)) {
+ CDEBUG(D_READA,
+ "Too many concurrent statahead instances, "
+ "avoid new statahead instance temporarily.\n");
+ GOTO(out, rc = -EMFILE);
+ }
+
sai = ll_sai_alloc(parent);
if (sai == NULL)
GOTO(out, rc = -ENOMEM);
- sai->sai_ls_all = (rc == LS_FIRST_DOT_DE);
+ sai->sai_ls_all = (first == LS_FIRST_DOT_DE);
/* if current lli_opendir_key was deauthorized, or dir re-opened by
* another process, don't start statahead, otherwise the newly spawned
lli->lli_sai = sai;
spin_unlock(&lli->lli_sa_lock);
- atomic_inc(&ll_i2sbi(parent->d_inode)->ll_sa_running);
-
CDEBUG(D_READA, "start statahead thread: [pid %d] [parent %.*s]\n",
current_pid(), parent->d_name.len, parent->d_name.name);
if (sai != NULL)
ll_sai_free(sai);
+ if (first != LS_NOT_FIRST_DE)
+ atomic_dec(&sbi->ll_sa_running);
RETURN(rc);
}