[Ocfs2-tools-devel] [PATCH 4/7] record.c

Larry Chen lchen at suse.com
Fri Oct 12 03:20:11 PDT 2018


Signed-off-by: Larry Chen <lchen at suse.com>
---
 defragfs.ocfs2/record.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 262 insertions(+)
 create mode 100644 defragfs.ocfs2/record.c

diff --git a/defragfs.ocfs2/record.c b/defragfs.ocfs2/record.c
new file mode 100644
index 00000000..bcf1e395
--- /dev/null
+++ b/defragfs.ocfs2/record.c
@@ -0,0 +1,262 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/limits.h>
+#include <linux/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ocfs2-kernel/kernel-list.h>
+#include <record.h>
+#include <libdefrag.h>
+
+
+#define MAX_RECORD_FILE_SIZE (2<<20)
+
+static char record_path[PATH_MAX] = "/tmp/"RECORD_FILE_NAME;
+
+void mv_record(struct resume_record *dst, struct resume_record *src)
+{
+	dst->r_argc = src->r_argc;
+	dst->r_inode_no = src->r_inode_no;
+	dst->r_mode_flag = src->r_mode_flag;
+	INIT_LIST_HEAD(&dst->r_argvs);
+	list_splice(&src->r_argvs, &dst->r_argvs);
+}
+
+void dump_record(char *base_name, struct resume_record *rr,
+		void (*dump_mode_flag)(int mode_flag))
+{
+		struct list_head *pos;
+		struct argv_node *n;
+		int mode_flag = rr->r_mode_flag;
+
+
+		printf("%s", base_name);
+		dump_mode_flag(mode_flag);
+
+		list_for_each(pos, &rr->r_argvs) {
+			n = list_entry(pos, struct argv_node, a_list);
+			printf(" %s ", n->a_path);
+		}
+		puts("");
+}
+
+
+void free_argv_node(struct argv_node *n)
+{
+	list_del(&n->a_list);
+	if (n->a_path)
+		free(n->a_path);
+	free(n);
+}
+
+static inline
+struct argv_node *allocate_argv_node(int len)
+{
+	struct argv_node *n;
+
+	n = do_malloc(sizeof(struct argv_node));
+	n->a_path = do_malloc(len);
+	return n;
+}
+
+void free_record(struct resume_record *rr)
+{
+	struct list_head *pos;
+	struct argv_node *n;
+
+	list_for_each(pos, &rr->r_argvs) {
+		n = list_entry(pos, struct argv_node, a_list);
+		free_argv_node(n);
+	}
+}
+
+static int read_record(int fd, struct resume_record **p, int *len)
+{
+	struct stat s;
+	void *content_buf = NULL;
+
+	if (fstat(fd, &s))
+		goto error;
+
+	content_buf = do_malloc(s.st_size);
+
+	if (do_read(fd, content_buf, s.st_size) != s.st_size)
+		goto error;
+
+	if (p)
+		*p = content_buf;
+	if (len)
+		*len = s.st_size;
+	return 0;
+
+error:
+	if (content_buf)
+		free(content_buf);
+	if (p)
+		*p = NULL;
+	if (len)
+		*len = 0;
+	return -errno;
+
+}
+
+static int is_record_file_valid(void *buf, int len)
+{
+	int data_len = len - sizeof(unsigned int);
+	unsigned int check_sum = *(int *)(buf + data_len);
+
+	if (check_sum == do_csum(buf, data_len))
+		return 1;
+	return 0;
+}
+
+static int __store_record(int fd, struct resume_record *rr)
+{
+	struct list_head *pos;
+	struct argv_node *n;
+	int index = 0;
+	unsigned char *buf = do_malloc(MAX_RECORD_FILE_SIZE);
+	int len;
+	int ret;
+
+	memcpy(buf, rr, RECORD_HEADER_LEN);
+	index += RECORD_HEADER_LEN;
+
+	list_for_each(pos, &rr->r_argvs) {
+		n = list_entry(pos, struct argv_node, a_list);
+		len = strlen(n->a_path) + 1;
+		if (index + len > MAX_RECORD_FILE_SIZE) {
+			PRINT_ERR("Arg too long");
+			ret = -1;
+			goto out;
+		}
+		strcpy((char *)&buf[index], n->a_path);
+		index += len;
+	}
+
+	*(int *)&buf[index] = do_csum(buf, index);
+	index += sizeof(int);
+	ret = do_write(fd, buf, index);
+
+out:
+	free(buf);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+
+void fill_resume_record(struct resume_record *rr,
+		int mode_flag, char **argv, int argc, ino_t inode_no)
+{
+	int i;
+	int len;
+	struct argv_node *node;
+
+	rr->r_mode_flag = mode_flag;
+	rr->r_argc = argc;
+	rr->r_inode_no = inode_no;
+	INIT_LIST_HEAD(&rr->r_argvs);
+	for (i = 0; i < argc; i++) {
+		len = strlen(argv[i]) + 1;
+		node = do_malloc(sizeof(struct argv_node));
+		node->a_path = do_malloc(len);
+		strcpy(node->a_path, argv[i]);
+		list_add_tail(&node->a_list, &rr->r_argvs);
+	}
+}
+
+int remove_record(void)
+{
+	int ret;
+
+	ret = unlink(record_path);
+	if (ret && errno != ENOENT) {
+		perror("while deleting record file");
+		return -errno;
+	}
+	return 0;
+}
+
+int store_record(struct resume_record *rr)
+{
+	int fd;
+
+	fd = open(record_path,
+			O_TRUNC | O_CREAT | O_WRONLY, 0600);
+	if (fd < 0) {
+		perror("while opening record file");
+		return -errno;
+	}
+	if (__store_record(fd, rr))
+		goto out;
+
+	if (fsync(fd))
+		goto out;
+
+	close(fd);
+	return 0;
+out:
+	return -1;
+}
+
+static int __load_record(int fd, struct resume_record *rr)
+{
+	int ret = -1, i;
+	struct resume_record *rr_tmp = NULL;
+	char **argv = NULL;
+	int argc;
+	char *p;
+	int len = 0;
+
+	if (read_record(fd, &rr_tmp, &len))
+		goto out;
+
+	if (!is_record_file_valid(rr_tmp, len))
+		goto out;
+
+
+	argc = rr_tmp->r_argc;
+
+	argv = do_malloc(sizeof(char *) * argc);
+
+	p = (void *)rr_tmp + RECORD_HEADER_LEN;
+	for (i = 0; i < argc; i++, p++) {
+		argv[i] = (char *)p;
+		p += strlen(p) + 1;
+	}
+
+	fill_resume_record(rr, rr_tmp->r_mode_flag,
+			argv, argc, rr_tmp->r_inode_no);
+
+	ret = 0;
+out:
+	if (rr_tmp)
+		free(rr_tmp);
+	if (argv)
+		free(argv);
+	return ret;
+
+}
+
+int load_record(struct resume_record *rr)
+{
+	int ret;
+	int record_fd = open(record_path, O_RDONLY, 0700);
+
+	if (record_fd < 0) {
+		perror("while opening record file");
+		return -errno;
+	}
+	ret = __load_record(record_fd, rr);
+	close(record_fd);
+	return ret;
+}
+
-- 
2.13.7




More information about the Ocfs2-tools-devel mailing list