From d29a92f4d336fb25b35f71e134db910039f6e9dc Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sat, 20 Mar 2021 05:14:04 -0600 Subject: [PATCH] EX-2872 pcc: mtime rule for 'lctl pcc add' Add an "mtime>N" rule to allow skipping files for PCC-RO auto-attach if they were created or modified more than N seconds ago. Otherwise, it may be that files are added to the PCC cache before they finished writing, or if they will be modified again quickly after creation. Signed-off-by: Andreas Dilger Signed-off-by: Qian Yingjin Change-Id: Ibb99bff5b483717ae6e5b83f82f1bcd86c3ebbe5 Reviewed-on: https://review.whamcloud.com/42122 Tested-by: jenkins Tested-by: Maloo --- lustre/llite/namei.c | 1 + lustre/llite/pcc.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- lustre/llite/pcc.h | 7 ++++-- lustre/tests/sanity-pcc.sh | 28 ++++++++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 6ecc339..7ab8b45 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -1113,6 +1113,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, item.pm_projid = ll_i2info(dir)->lli_projid; item.pm_name = &dentry->d_name; item.pm_size = 0; + item.pm_mtime = ktime_get_seconds(); dataset = pcc_dataset_match_get(&sbi->ll_pcc_super, LU_PCC_READWRITE, &item); diff --git a/lustre/llite/pcc.c b/lustre/llite/pcc.c index ef415ab..b7c8d68 100644 --- a/lustre/llite/pcc.c +++ b/lustre/llite/pcc.c @@ -183,6 +183,8 @@ static void pcc_expression_free(struct pcc_expression *expr) case PCC_FIELD_SIZE: pcc_size_list_free(expr); break; + case PCC_FIELD_MTIME: + break; default: LBUG(); } @@ -392,6 +394,45 @@ pcc_expr_size_parse(char *str, int len, struct pcc_expression *expr) return sysfs_memparse(str, len, &expr->pe_size, "MiB"); } +/* + * Parse relative file age timestamp, allowing suffix for ease of use: + * s = seconds, m = minutes, h = hours, d = days, w = weeks, y = years + */ +static int pcc_expr_time_parse(char *str, int len, struct pcc_expression *expr) +{ + unsigned long mtime; + unsigned mult = 1; + char buf[10]; + int rc; + + if (expr->pe_opc == PCC_FIELD_OP_EQ) + return -EOPNOTSUPP; + + /* 1B seconds is enough, and avoids the need for overflow checking */ + if (len > 10) + return -EOVERFLOW; + + strncpy(buf, str, sizeof(buf)); + rc = strspn(buf, "0123456789"); + if (rc < len) { + switch(str[rc]) { + case 'y': mult *= 52; /* fallthrough */ + case 'w': mult *= 7; /* fallthrough */ + case 'd': mult *= 24; /* fallthrough */ + case 'h': mult *= 60; /* fallthrough */ + case 'm': mult *= 60; /* fallthrough */ + case 's': break; + default: return -EINVAL; + } + buf[rc] = '\0'; + } + rc = kstrtoul(buf, 10, &mtime); + if (!rc) + expr->pe_mtime = mtime * mult; + + return rc; +} + static inline bool pcc_check_field(struct cfs_lstr *field, char *str) { @@ -479,7 +520,12 @@ pcc_expression_parse(struct cfs_lstr *src, struct list_head *cond_list) expr->pe_field = PCC_FIELD_SIZE; if (pcc_expr_size_parse(src->ls_str, src->ls_len, expr) < 0) GOTO(out, rc = -EINVAL); - } else if (pcc_check_field(&field, "fname")) { + } else if (pcc_check_field(&field, "mtime")) { + expr->pe_field = PCC_FIELD_MTIME; + if (pcc_expr_time_parse(src->ls_str, src->ls_len, expr) < 0) + GOTO(out, rc = -EINVAL); + } else if (pcc_check_field(&field, "fname") || + pcc_check_field(&field, "filename")) { if (opc != PCC_FIELD_OP_EQ) GOTO(out, rc = -EINVAL); @@ -827,6 +873,13 @@ pcc_expr_size_match(struct pcc_expression *expr, __u64 sz) } } +static inline int +pcc_expr_time_match(struct pcc_expression *expr, __u64 time) +{ + /* pe_mtime and pe_size are both __u64 in the same union */ + return pcc_expr_size_match(expr, ktime_get_real_seconds() - time); +} + static int pcc_expression_match(struct pcc_expression *expr, struct pcc_matcher *matcher) { @@ -839,6 +892,8 @@ pcc_expression_match(struct pcc_expression *expr, struct pcc_matcher *matcher) return pcc_expr_id_match(expr, matcher->pm_projid); case PCC_FIELD_SIZE: return pcc_expr_size_match(expr, matcher->pm_size); + case PCC_FIELD_MTIME: + return pcc_expr_time_match(expr, matcher->pm_mtime); case PCC_FIELD_FNAME: return pcc_fname_list_match(&expr->pe_cond, matcher->pm_name->name); @@ -1775,6 +1830,7 @@ static int pcc_try_readonly_open_attach(struct inode *inode, struct file *file, item.pm_projid = ll_i2info(inode)->lli_projid; item.pm_name = &dentry->d_name; item.pm_size = ll_i2info(inode)->lli_lazysize; + item.pm_mtime = inode->i_mtime.tv_sec; dataset = pcc_dataset_match_get(&ll_i2sbi(inode)->ll_pcc_super, LU_PCC_READONLY, &item); if (dataset == NULL) diff --git a/lustre/llite/pcc.h b/lustre/llite/pcc.h index 6d659ee..acb8d25 100644 --- a/lustre/llite/pcc.h +++ b/lustre/llite/pcc.h @@ -66,6 +66,7 @@ enum pcc_field { PCC_FIELD_PROJID, PCC_FIELD_FNAME, PCC_FIELD_SIZE, + PCC_FIELD_MTIME, PCC_FIELD_MAX }; @@ -83,8 +84,9 @@ struct pcc_expression { enum pcc_field_op pe_opc; union { struct list_head pe_cond; - __u64 pe_size; - __u32 pe_id; + __u64 pe_size; /* file size in bytes */ + __u64 pe_mtime; /* relative age in seconds */ + __u32 pe_id; /* UID/GID/PROJID */ }; }; @@ -108,6 +110,7 @@ struct pcc_matcher { __u32 pm_gid; __u32 pm_projid; __u64 pm_size; + __u64 pm_mtime; struct qstr *pm_name; }; diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index b708c85..01df9af 100644 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -3270,6 +3270,34 @@ test_40() { } run_test 40 "Test async open attach in the background for PCC-RO file" +test_41() { + local loopfile="$TMP/$tfile" + local mntpt="/mnt/pcc.$tdir" + local hsm_root="$mntpt/$tdir" + local file=$DIR/$tfile + + $LCTL get_param -n mdc.*.connect_flags | grep -q pccro || + skip "Server does not support PCC-RO" + + setup_loopdev $SINGLEAGT $loopfile $mntpt 50 + do_facet $SINGLEAGT mkdir $hsm_root || error "mkdir $hsm_root failed" + setup_pcc_mapping $SINGLEAGT \ + "mtime\>{1m}\ roid=$HSM_ARCHIVE_NUMBER\ ropcc=1" + do_facet $SINGLEAGT $LCTL pcc list $MOUNT + + echo "pcc_ro_data" > $file || error "echo $file failed" + do_facet $SINGLEAGT cat $file || error "cat $file failed" + check_lpcc_state $file "none" + + local mtime=$(date -d "2min ago" +%s) + + do_facet $SINGLEAGT touch -m -d @$mtime $file || + error "failed to change mtime for $file $mtime" + do_facet $SINGLEAGT cat $file || error "cat $file failed" + check_lpcc_state $file "readonly" +} +run_test 41 "Test mtime rule for PCC-RO open attach with O_RDONLY mode" + complete $SECONDS check_and_cleanup_lustre exit_status -- 1.8.3.1