From 976ecfaf9ccd744098b8ab942560cecd78c83ef9 Mon Sep 17 00:00:00 2001 From: liqiang Date: Sat, 9 Dec 2023 17:47:03 +0800 Subject: [PATCH] fix some problem of fifo, resolve problem in libvirt Signed-off-by: liqiang --- ...ifo-the-reason-is-SIGURG-recieved-in.patch | 308 ++++++++++++++++++ 0002-fix-virsh-console-problem.patch | 150 +++++++++ 0003-delete-write-path-buf-to-log-info.patch | 32 ++ dpu-utilities.spec | 9 +- 4 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 0001-fix-suspend-in-fifo-the-reason-is-SIGURG-recieved-in.patch create mode 100644 0002-fix-virsh-console-problem.patch create mode 100644 0003-delete-write-path-buf-to-log-info.patch diff --git a/0001-fix-suspend-in-fifo-the-reason-is-SIGURG-recieved-in.patch b/0001-fix-suspend-in-fifo-the-reason-is-SIGURG-recieved-in.patch new file mode 100644 index 0000000..fcb4ade --- /dev/null +++ b/0001-fix-suspend-in-fifo-the-reason-is-SIGURG-recieved-in.patch @@ -0,0 +1,308 @@ +From b6663e01b364c878e08206a4ccb3ea02a63d7ed0 Mon Sep 17 00:00:00 2001 +From: liqiang +Date: Thu, 7 Dec 2023 16:58:09 +0800 +Subject: [PATCH 1/3] fix suspend in fifo, the reason is SIGURG recieved in + client thread when wait for ack + +Signed-off-by: liqiang +--- + qtfs/include/log.h | 9 ++++--- + qtfs/qtfs/fifo.c | 21 +++++++++++++---- + qtfs/qtfs/qtfs-mod.c | 12 +++++----- + qtfs/qtfs_common/conn.c | 43 +++++++++++++++++++++++++++------- + qtfs/qtfs_server/server_fifo.c | 21 +++++++++++------ + 5 files changed, 77 insertions(+), 29 deletions(-) + +diff --git a/qtfs/include/log.h b/qtfs/include/log.h +index 4df42b3..284464e 100644 +--- a/qtfs/include/log.h ++++ b/qtfs/include/log.h +@@ -27,8 +27,11 @@ enum level { + #ifndef __KERNEL__ + #include + #define true 1 ++#ifndef log_switch ++#define log_switch 1 ++#endif + #define log_info(info, ...) \ +- if (true) {\ ++ if (log_switch) {\ + time_t t; \ + struct tm p; \ + time(&t); \ +@@ -39,7 +42,7 @@ enum level { + } + + #define log_warn(info, ...) \ +- if (true) {\ ++ if (log_switch) {\ + time_t t; \ + struct tm p; \ + time(&t); \ +@@ -50,7 +53,7 @@ enum level { + } + + #define log_err(info, ...) \ +- if (true) {\ ++ if (log_switch) {\ + time_t t; \ + struct tm p; \ + time(&t); \ +diff --git a/qtfs/qtfs/fifo.c b/qtfs/qtfs/fifo.c +index 2b636bb..55292de 100644 +--- a/qtfs/qtfs/fifo.c ++++ b/qtfs/qtfs/fifo.c +@@ -117,6 +117,10 @@ ssize_t qtfs_fifo_readiter(struct kiocb *kio, struct iov_iter *iov) + int total = 0; + int ret; + ++ if (sigismember(¤t->pending.signal, SIGURG)) { ++ qtfs_err("signal SIGURG return eintr"); ++ return -EINTR; ++ } + if (pvar == NULL || !virt_addr_valid(pvar)) { + qtfs_err("invalid fifo read req, private data is invalid"); + return -EFAULT; +@@ -127,8 +131,9 @@ ssize_t qtfs_fifo_readiter(struct kiocb *kio, struct iov_iter *iov) + qtfs_info("fifo readiter len:%llu", req->len); + rsp = qtfs_remote_run(pvar, QTFS_REQ_READITER, sizeof(struct qtreq_fifo_read)); + if (IS_ERR_OR_NULL(rsp) || rsp->err != 0) { +- qtfs_err("remote run failed. or errno:%d", (rsp == NULL) ? -1 : rsp->err); +- return -EFAULT; ++ qtfs_err("remote run failed. or errno:%d", IS_ERR_OR_NULL(rsp) ? -1 : rsp->err); ++ //return -EFAULT; ++ return (rsp == NULL) ? -EFAULT : (ssize_t)rsp; + } + + while (total < rsp->len) { +@@ -154,6 +159,10 @@ ssize_t qtfs_fifo_writeiter(struct kiocb *kio, struct iov_iter *iov) + struct qtreq_fifo_write *req; + struct qtrsp_fifo_write *rsp; + ++ if (sigismember(¤t->pending.signal, SIGURG)) { ++ qtfs_err("signal SIGURG return eintr"); ++ return -EINTR; ++ } + if (pvar == NULL || !virt_addr_valid(pvar)) { + qtfs_err("invalid fifo write req, private data is invalid"); + return -EFAULT; +@@ -164,9 +173,10 @@ ssize_t qtfs_fifo_writeiter(struct kiocb *kio, struct iov_iter *iov) + pvar->iov_send = iov; + rsp = qtfs_remote_run(pvar, QTFS_REQ_WRITE, sizeof(struct qtreq_fifo_write)); + if (IS_ERR_OR_NULL(rsp) || rsp->err != 0) { +- qtfs_err("fifo write remote run failed, or errno:%d", (rsp == NULL) ? -1 : rsp->err); +- return -EFAULT; ++ qtfs_err("fifo write remote run failed, or errno:%d", IS_ERR_OR_NULL(rsp) ? -1 : rsp->err); ++ return (rsp == NULL) ? -EFAULT : (ssize_t)rsp; + } ++ qtfs_info("fifo write over err:%d len:%llu", rsp->err, rsp->len); + return rsp->len; + } + +@@ -179,11 +189,12 @@ int qtfs_fifo_release(struct inode *inode, struct file *file) + qtfs_err("invalid fifo write req, private data is invalid"); + return -EFAULT; + } +- pvar->vec_recv.iov_len = QTFS_MSG_HEAD_LEN; ++ pvar->vec_recv.iov_len = pvar->recv_max; + rsp = qtfs_remote_run(pvar, QTFS_REQ_CLOSE, 0); + if (IS_ERR_OR_NULL(rsp)) { + qtfs_err("fifo close failed"); + } ++ qtfs_info("fifo release req over"); + qtfs_fifo_put_file(file); + return 0; + } +diff --git a/qtfs/qtfs/qtfs-mod.c b/qtfs/qtfs/qtfs-mod.c +index ad0bfc5..c4ef72c 100644 +--- a/qtfs/qtfs/qtfs-mod.c ++++ b/qtfs/qtfs/qtfs-mod.c +@@ -66,7 +66,7 @@ void *qtfs_remote_run(struct qtfs_conn_var_s *pvar, unsigned int type, unsigned + if (ret <= 0) { + qtfs_err("qtfs remote run send failed, ret:%d pvar sendlen:%lu.", ret, pvar->vec_send.iov_len); + qtinfo_senderrinc(req->type); +- return NULL; ++ return (void *)ret; + } + qtinfo_sendinc(type); + +@@ -87,7 +87,7 @@ retry: + } + // miss message retry would result in block + if (retrytimes >= 5) { +- qtfs_err("qtfs conn recv get mismatch seq_num too many times, stop retrying"); ++ qtfs_err("qtfs conn recv get mismatch seq_num too many times, stop retrying, signal:0x%lx", (unsigned long)current->pending.signal.sig[0]); + return NULL; + } + retrytimes++; +@@ -98,9 +98,9 @@ retry: + qtinfo_cntinc(QTINF_RESTART_SYS); + qtinfo_recverrinc(req->type); + } +- if (retrytimes >= 5) { +- qtfs_err("qtfs conn recv get retry signal(%d) too many times, stop retrying", ret); +- return NULL; ++ if (retrytimes >= 5 && ret == -EINTR) { ++ qtfs_err("qtfs conn recv get retry signal(%d) too many times, stop retrying, signal:0x%lx", ret, (unsigned long)current->pending.signal.sig[0]); ++ return (void *)ret; + } + retrytimes++; + msleep(1); +@@ -109,7 +109,7 @@ retry: + if (ret < 0) { + qtfs_err("qtfs remote run error, req_type:%u, ret:%d.", req->type, ret); + qtinfo_recverrinc(req->type); +- return NULL; ++ return (void *)ret; + } + if (retrytimes > 0) + qtfs_debug("qtfs remote run retry times:%lu.", retrytimes); +diff --git a/qtfs/qtfs_common/conn.c b/qtfs/qtfs_common/conn.c +index 99809d2..4f2f048 100644 +--- a/qtfs/qtfs_common/conn.c ++++ b/qtfs/qtfs_common/conn.c +@@ -274,6 +274,29 @@ int qtfs_conn_send(struct qtfs_conn_var_s *pvar) + return ret + iov_ret; + } + ++#ifdef QTFS_CLIENT ++static int qtfs_mismatch_fix(struct qtfs_conn_var_s *pvar) ++{ ++ struct qtreq *req = (struct qtreq *)pvar->vec_send.iov_base; ++ struct qtreq *rsp = (struct qtreq *)pvar->vec_recv.iov_base; ++ int ret; ++ size_t len; ++ if (req->seq_num == rsp->seq_num) ++ return 0; ++ ++ qtfs_err("recv mismatch package, req type:%u rsp type:%u req seq:%lu rsp seq:%lu", ++ req->type, rsp->type, req->seq_num, rsp->seq_num); ++ // 如果收到错包,到目前为止只接收了qtreq这个标准头,下面把rsp->len长度 ++ // 的socket缓冲区丢弃就行了 ++ len = rsp->len; ++ ret = pvar->conn_ops->conn_recv(&pvar->conn_var, pvar->vec_recv.iov_base, len, true); ++ if (ret != len) { ++ qtfs_err("mismatch drop failed, recv len:%lu ret:%d", len, ret); ++ } ++ return -1; ++} ++#endif ++ + int do_qtfs_conn_recv(struct qtfs_conn_var_s *pvar, bool block) + { + int ret = 0; +@@ -284,8 +307,10 @@ int do_qtfs_conn_recv(struct qtfs_conn_var_s *pvar, bool block) + int msglen = 0; + void *addr = NULL; + int leftlen = 0; +- int totallen = 0; + ++#ifdef QTFS_CLIENT ++start: ++#endif + headlen = pvar->conn_ops->conn_recv(&pvar->conn_var, pvar->vec_recv.iov_base, QTFS_MSG_HEAD_LEN, block); + if (headlen <= 0) { + return headlen; +@@ -294,6 +319,12 @@ int do_qtfs_conn_recv(struct qtfs_conn_var_s *pvar, bool block) + qtfs_err("qtfs recv headlen not valid, expect(%ld), get(%d)", QTFS_MSG_HEAD_LEN, headlen); + return headlen; + } ++#ifdef QTFS_CLIENT ++ if (qtfs_mismatch_fix(pvar) != 0) { ++ qtfs_err("mismatch package recved"); ++ goto start; ++ } ++#endif + + load.iov_base = pvar->vec_recv.iov_base + QTFS_MSG_HEAD_LEN; + load.iov_len = pvar->vec_recv.iov_len - QTFS_MSG_HEAD_LEN; +@@ -318,7 +349,7 @@ retry: + qtinfo_recverrinc(rsp->type); + } + #endif +- if (retrytimes >= 5) { ++ if (retrytimes >= 5 && ret == -EINTR) { + qtfs_err("qtfs recv get retry signal(%d) too many times, stop retrying", ret); + return ret; + } +@@ -331,12 +362,8 @@ retry: + return ret; + } + +- totallen += ret; +- if (totallen < msglen) { +- qtfs_err("qtfs conn recv %d msg, expect %d, goto retry", ret, msglen); +- addr += ret; +- leftlen -= ret; +- goto retry; ++ if (ret < msglen) { ++ qtfs_err("qtfs conn recv %d msg, expect %d", ret, msglen); + } + + if (ret > rsp->len) { +diff --git a/qtfs/qtfs_server/server_fifo.c b/qtfs/qtfs_server/server_fifo.c +index e1d9bd1..fc4c67c 100644 +--- a/qtfs/qtfs_server/server_fifo.c ++++ b/qtfs/qtfs_server/server_fifo.c +@@ -21,6 +21,7 @@ + #include + #include + ++int log_switch = 0; + #include "req.h" + #include "log.h" + #include "libsocket.h" +@@ -227,22 +228,26 @@ static void fifo_proc_ack(struct fifo_event_t *evt, int type, int sockfd, char * + { + int ret; + struct qtreq rsp; ++ char *msg = (char *)malloc(sizeof(rsp) + arglen); ++ if (msg == NULL) { ++ log_err("malloc failed:%d.", errno); ++ return; ++ } + + rsp.type = type; + rsp.err = 0; + rsp.seq_num = evt->seq_num; + rsp.len = arglen; + +- ret = write(sockfd, &rsp, sizeof(struct qtreq)); ++ memcpy(msg, &rsp, sizeof(rsp)); ++ memcpy(&msg[sizeof(rsp)], arg, arglen); ++ ++ ret = write(sockfd, msg, sizeof(struct qtreq) + arglen); ++ free(msg); + if (ret < 0) { + log_err("fifo ack type:%d failed, sockfd:%d err:%d", type, sockfd, errno); + return; + } +- ret = write(sockfd, arg, arglen); +- if (ret < 0) { +- log_err("fifo ack arg type:%d failed, sockfd:%d err:%d", type, sockfd, errno); +- return; +- } + log_info("Type:%d ack successed, sockfd:%d.", type, sockfd); + return; + } +@@ -639,6 +644,8 @@ int fifo_proc_main_sock(struct fifo_event_t *evt) + return FIFO_RET_OK; + } + ++ ++extern int engine_run; + void *fifo_server_main_thread(void *arg) + { + int indx = 0; +@@ -673,7 +680,7 @@ void *fifo_server_main_thread(void *arg) + + fifo_add_event(sockfd, NULL, fifo_proc_main_sock, NULL, EPOLLIN); + +- while (1) { ++ while (engine_run) { + int ret; + struct fifo_event_t *event; + int n = epoll_wait(epollfd, evts, EPOLL_MAX_EVENT_NUMS, 1000); +-- +2.37.1 (Apple Git-137.1) + diff --git a/0002-fix-virsh-console-problem.patch b/0002-fix-virsh-console-problem.patch new file mode 100644 index 0000000..0747e38 --- /dev/null +++ b/0002-fix-virsh-console-problem.patch @@ -0,0 +1,150 @@ +From 7f99bba84646a5efe0f25f83e6c45e70537798bd Mon Sep 17 00:00:00 2001 +From: liqiang +Date: Fri, 8 Dec 2023 17:18:42 +0800 +Subject: [PATCH 2/3] fix virsh console problem + +Signed-off-by: liqiang +--- + qtfs/qtfs/fifo.c | 6 +++--- + qtfs/qtfs/qtfs-mod.h | 1 + + qtfs/qtfs/sb.c | 1 + + qtfs/qtfs_server/server_fifo.c | 21 ++++++++++++++++----- + 4 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/qtfs/qtfs/fifo.c b/qtfs/qtfs/fifo.c +index 55292de..829ce66 100644 +--- a/qtfs/qtfs/fifo.c ++++ b/qtfs/qtfs/fifo.c +@@ -199,8 +199,8 @@ int qtfs_fifo_release(struct inode *inode, struct file *file) + return 0; + } + +-static __poll_t +-qtfs_fifo_poll(struct file *filp, poll_table *wait) ++__poll_t ++qtfs_poll(struct file *filp, poll_table *wait) + { + struct qtfs_inode_priv *priv = filp->f_inode->i_private; + __poll_t mask = 0; +@@ -248,5 +248,5 @@ struct file_operations qtfsfifo_ops = { + .open = qtfs_fifo_open, + .release = qtfs_fifo_release, + .llseek = no_llseek, +- .poll = qtfs_fifo_poll, ++ .poll = qtfs_poll, + }; +diff --git a/qtfs/qtfs/qtfs-mod.h b/qtfs/qtfs/qtfs-mod.h +index cecce11..21d2f2d 100644 +--- a/qtfs/qtfs/qtfs-mod.h ++++ b/qtfs/qtfs/qtfs-mod.h +@@ -192,6 +192,7 @@ int qtfs_utils_register(void); + void qtfs_utils_destroy(void); + void qtfs_whitelist_clearall(void); + void qtfs_whitelist_initset(void); ++__poll_t qtfs_poll(struct file *filp, poll_table *wait); + + #endif + +diff --git a/qtfs/qtfs/sb.c b/qtfs/qtfs/sb.c +index 79f1f89..a0d0964 100644 +--- a/qtfs/qtfs/sb.c ++++ b/qtfs/qtfs/sb.c +@@ -747,6 +747,7 @@ static struct file_operations qtfs_file_ops = { + .llseek = qtfs_llseek, + .fsync = qtfs_fsync, + .unlocked_ioctl = qtfs_ioctl, ++ .poll = qtfs_poll, + }; + + static int qtfs_readpage(struct file *file, struct page *page) +diff --git a/qtfs/qtfs_server/server_fifo.c b/qtfs/qtfs_server/server_fifo.c +index fc4c67c..0eaadea 100644 +--- a/qtfs/qtfs_server/server_fifo.c ++++ b/qtfs/qtfs_server/server_fifo.c +@@ -190,15 +190,20 @@ void fifo_suspend_event(struct fifo_event_t *evt) + + static int fifo_peer_index; + static struct fifo_event_t *fifo_peer_evt[EPOLL_MAX_EVENT_NUMS]; +-static int fifo_del_peer(int flag, struct fifo_event_t *peer) ++static int fifo_del_peer(int flag, struct fifo_event_t *me) + { ++ // 自己已经先被peer加过了就不必加peer了,peer此时已释放 ++ for (int i = 0; i < fifo_peer_index; i++) { ++ if (fifo_peer_evt[i] == me) ++ return 0; ++ } + switch (flag) { + case FIFO_PEER_PRE: + fifo_peer_index = 0; + memset(fifo_peer_evt, 0, sizeof(struct fifo_event_t *) * EPOLL_MAX_EVENT_NUMS); + break; + case FIFO_PEER_ADD: +- fifo_peer_evt[fifo_peer_index] = peer; ++ fifo_peer_evt[fifo_peer_index] = me->peerevt; + break; + case FIFO_PEER_POST: + for (int i = 0; i < fifo_peer_index; i++) { +@@ -288,6 +293,7 @@ int fifo_proc_readable(struct fifo_event_t *evt) + char *msg; + struct qtrsp_fifo_read *rsp; + int readlen = evt->len; ++ int error_ret = FIFO_RET_SUSPEND; + if (readlen > QTFS_REQ_MAX_LEN) { + log_err("Read rsp len:%d too large!", readlen); + ret = EINVAL; +@@ -307,6 +313,8 @@ int fifo_proc_readable(struct fifo_event_t *evt) + log_err("read from fifo:%d failed, readlen:%d, errno:%d", evt->fd, readlen, errno); + ret = errno; + free(msg); ++ if (errno == EPIPE) ++ error_ret = FIFO_RET_DEL_BOTH; + goto err_ack; + } + rsp->err = 0; +@@ -327,7 +335,7 @@ err_ack: + fifo_proc_ack(evt, QTFS_REQ_READITER, evt->peerevt->fd, (char *)&errrsp, sizeof(errrsp)); + } while (0); + evt->peerevt->peerevt = NULL; +- return FIFO_RET_SUSPEND; ++ return error_ret; + } + + int fifo_proc_writeable(struct fifo_event_t *evt) +@@ -337,6 +345,7 @@ int fifo_proc_writeable(struct fifo_event_t *evt) + char *msg; + struct qtrsp_fifo_write rsp; + int writelen = evt->len; ++ int error_ret = FIFO_RET_SUSPEND; + if (writelen > QTFS_REQ_MAX_LEN) { + log_err("Read rsp len:%d too large!", writelen); + ret = EINVAL; +@@ -361,6 +370,8 @@ int fifo_proc_writeable(struct fifo_event_t *evt) + log_err("write to fifo failed, ret:%d errno:%d", ret, errno); + ret = errno; + free(msg); ++ if (errno == EPIPE) ++ error_ret = FIFO_RET_DEL_BOTH; + goto err_ack; + } + rsp.err = 0; +@@ -379,7 +390,7 @@ err_ack: + errrsp.len = 0; + fifo_proc_ack(evt, QTFS_REQ_WRITE, evt->peerevt->fd, (char *)&errrsp, sizeof(errrsp)); + } while (0); +- return FIFO_RET_SUSPEND; ++ return error_ret; + } + + // 处理读请求,读可能阻塞,因为打开时已经确定是否阻塞型, +@@ -700,7 +711,7 @@ void *fifo_server_main_thread(void *arg) + } else if (ret == FIFO_RET_DEL) { + fifo_del_event(event); + } else if (ret == FIFO_RET_DEL_BOTH) { +- fifo_del_peer(FIFO_PEER_ADD, event->peerevt); ++ fifo_del_peer(FIFO_PEER_ADD, event); + fifo_del_event(event); + } + } +-- +2.37.1 (Apple Git-137.1) + diff --git a/0003-delete-write-path-buf-to-log-info.patch b/0003-delete-write-path-buf-to-log-info.patch new file mode 100644 index 0000000..d563513 --- /dev/null +++ b/0003-delete-write-path-buf-to-log-info.patch @@ -0,0 +1,32 @@ +From 44efcff94d48fe022d0eb76924ac549a3dc4d9ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= +Date: Sat, 9 Dec 2023 08:26:04 +0000 +Subject: [PATCH 3/3] =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=BF=A1=E6=81=AF?= + =?UTF-8?q?=E4=B8=AD=E5=88=A0=E9=99=A4=E6=89=93=E5=8D=B0write=E5=86=85?= + =?UTF-8?q?=E5=AE=B9=EF=BC=8C=E9=98=B2=E6=AD=A2=E4=BF=A1=E6=81=AF=E6=B3=84?= + =?UTF-8?q?=E9=9C=B2?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: 李强 +--- + qtfs/qtfs/sb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qtfs/qtfs/sb.c b/qtfs/qtfs/sb.c +index a0d0964..fb60261 100644 +--- a/qtfs/qtfs/sb.c ++++ b/qtfs/qtfs/sb.c +@@ -480,7 +480,7 @@ ssize_t qtfs_writeiter(struct kiocb *kio, struct iov_iter *iov) + wake_up_interruptible_sync_poll(&priv->readq, EPOLLIN | EPOLLRDNORM); + if (S_ISCHR(inode->i_mode)) { + wake_up_interruptible_poll(&priv->readq, EPOLLIN); +- qtfs_err("writeiter file:%s char:<%s> wakup poll.", filp->f_path.dentry->d_iname, req->path_buf); ++ qtfs_err("writeiter file:%s len:%lu wakup poll.", filp->f_path.dentry->d_iname, len - leftlen); + } + } while (0); + qtfs_info("qtfs write %s over, leftlen:%lu.", filp->f_path.dentry->d_iname, leftlen); +-- +2.37.1 (Apple Git-137.1) + diff --git a/dpu-utilities.spec b/dpu-utilities.spec index 40d0f28..cff8a9c 100644 --- a/dpu-utilities.spec +++ b/dpu-utilities.spec @@ -1,7 +1,7 @@ Name: dpu-utilities Summary: openEuler dpu utilities Version: 1.6 -Release: 1 +Release: 2 License: GPL-2.0 Source: https://gitee.com/openeuler/dpu-utilities/repository/archive/v%{version}.tar.gz ExclusiveOS: linux @@ -13,6 +13,10 @@ Provides: %{name} = %{version}-%{release} %define kernel_version %(ver=`rpm -qa|grep kernel-devel`;echo ${ver#*kernel-devel-}) BuildRequires: kernel-devel >= 5.10, gcc, make, json-c-devel, glib2-devel +Patch1: 0001-fix-suspend-in-fifo-the-reason-is-SIGURG-recieved-in.patch +Patch2: 0002-fix-virsh-console-problem.patch +Patch3: 0003-delete-write-path-buf-to-log-info.patch + %description This package contains the software utilities on dpu. @@ -139,6 +143,9 @@ sed -i '/# product cut_conf/a\dpuos kiwi/minios/cfg_dpuos yes' /opt/imageT sed -i '//a\dpuos 1 rpm-dir euler_base' /opt/imageTailor/repos/RepositoryRule.conf %changelog +* Sat Dec 9 2023 liqiang 1.6-2 +- fix some problem of fifo, resolve problem in libvirt + * Fri Dec 1 2023 Guangxing Deng 1.6-1 - Upgrade dpu-utilities version to 1.6 -- Gitee