From: Alex Zhuravlev Date: Mon, 18 Jan 2016 06:24:19 +0000 (+0300) Subject: LU-6838 llog: limit file size of plain logs X-Git-Tag: 2.9.51~65 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=4724b52bba54ccdb0f81d0c63010b69e87e7f65c LU-6838 llog: limit file size of plain logs on small filesystems plain log can grow dramatically. especially given large record sizes produced by DNE and extended chunksize. I saw >50% of space consumed by a single llog file which was still in use. this leads to test failures (sanityn, etc). the patch introduces additional limit on plain llog size, which is calculated as /64 (128MB at most) at llog creation time. Change-Id: I0eab8177d4e416a32a6aab56d47e4142c81d13de Signed-off-by: Alex Zhuravlev Reviewed-on: https://review.whamcloud.com/18028 Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: wangdi Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre_log.h b/lustre/include/lustre_log.h index 28dcbf2..fe107c7 100644 --- a/lustre/include/lustre_log.h +++ b/lustre/include/lustre_log.h @@ -275,6 +275,7 @@ struct llog_handle { __u64 lgh_cur_offset; /* used during llog_process */ /* used during llog_osd_write_rec */ __u64 lgh_write_offset; + int lgh_max_size; struct llog_ctxt *lgh_ctxt; union { struct plain_handle_data phd; diff --git a/lustre/obdclass/llog.c b/lustre/obdclass/llog.c index b378384..f2f2fc6 100644 --- a/lustre/obdclass/llog.c +++ b/lustre/obdclass/llog.c @@ -515,8 +515,19 @@ repeat: * while llog_processing, check this is not * the case and re-read the current chunk * otherwise. */ + int records; if (index > loghandle->lgh_last_idx) GOTO(out, rc = 0); + /* <2 records means no more records + * if the last record we processed was + * the final one, then the underlying + * object might have been destroyed yet. + * we better don't access that.. */ + mutex_lock(&loghandle->lgh_hdr_mutex); + records = loghandle->lgh_hdr->llh_count; + mutex_unlock(&loghandle->lgh_hdr_mutex); + if (records <= 1) + GOTO(out, rc = 0); CDEBUG(D_OTHER, "Re-read last llog buffer for " "new records, index %u, last %u\n", index, loghandle->lgh_last_idx); diff --git a/lustre/obdclass/llog_cat.c b/lustre/obdclass/llog_cat.c index fd3336b..86a2047 100644 --- a/lustre/obdclass/llog_cat.c +++ b/lustre/obdclass/llog_cat.c @@ -171,6 +171,25 @@ static int llog_cat_new_log(const struct lu_env *env, POSTID(&cathandle->lgh_id.lgl_oi)); loghandle->lgh_hdr->llh_cat_idx = rec->lid_hdr.lrh_index; + + /* limit max size of plain llog so that space can be + * released sooner, especially on small filesystems */ + /* 2MB for the cases when free space hasn't been learned yet */ + loghandle->lgh_max_size = 2 << 20; + dt = lu2dt_dev(cathandle->lgh_obj->do_lu.lo_dev); + rc = dt_statfs(env, dt, &lgi->lgi_statfs); + if (rc == 0 && lgi->lgi_statfs.os_bfree > 0) { + __u64 freespace = (lgi->lgi_statfs.os_bfree * + lgi->lgi_statfs.os_bsize) >> 6; + if (freespace < loghandle->lgh_max_size) + loghandle->lgh_max_size = freespace; + /* shouldn't be > 128MB in any case? + * it's 256K records of 512 bytes each */ + if (freespace > (128 << 20)) + loghandle->lgh_max_size = 128 << 20; + } + rc = 0; + out: if (handle != NULL) { handle->th_result = rc >= 0 ? 0 : rc; diff --git a/lustre/obdclass/llog_internal.h b/lustre/obdclass/llog_internal.h index e1a7c28..8d5d2ad 100644 --- a/lustre/obdclass/llog_internal.h +++ b/lustre/obdclass/llog_internal.h @@ -55,6 +55,7 @@ struct llog_thread_info { struct dt_insert_rec lgi_dt_rec; struct lu_seq_range lgi_range; struct llog_cookie lgi_cookie; + struct obd_statfs lgi_statfs; char lgi_name[32]; }; diff --git a/lustre/obdclass/llog_osd.c b/lustre/obdclass/llog_osd.c index 4fc0b4e..6c3c288 100644 --- a/lustre/obdclass/llog_osd.c +++ b/lustre/obdclass/llog_osd.c @@ -558,6 +558,19 @@ static int llog_osd_write_rec(const struct lu_env *env, orig_last_idx = loghandle->lgh_last_idx; orig_write_offset = loghandle->lgh_write_offset; lgi->lgi_off = lgi->lgi_attr.la_size; + + if (loghandle->lgh_max_size > 0 && + lgi->lgi_off >= loghandle->lgh_max_size) { + CDEBUG(D_OTHER, "llog is getting too large (%u > %u) at %u " + DOSTID"\n", (unsigned)lgi->lgi_off, + loghandle->lgh_max_size, + (int)loghandle->lgh_last_idx, + POSTID(&loghandle->lgh_id.lgl_oi)); + /* this is to signal that this llog is full */ + loghandle->lgh_last_idx = LLOG_HDR_BITMAP_SIZE(llh) - 1; + RETURN(-ENOSPC); + } + left = chunk_size - (lgi->lgi_off & (chunk_size - 1)); /* NOTE: padding is a record, but no bit is set */ if (left != 0 && left != reclen &&