summaryrefslogtreecommitdiffstats
path: root/src/btrfs_ioc_test.c
blob: e12bad14d1b576c3d52bc7926c2e7c2052bbf081 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include "common/safe_io.h"
#include "os/btrfs_ioctl.h"

void do_open_wr(const char *fname, int *fd)
{
	*fd = open(fname, O_WRONLY | O_CREAT, 0644);
	if (*fd < 0) {
		perror("open");
		exit(1);
	}
}

void do_open_rd(const char *fname, int *fd)
{
	*fd = open(fname, O_RDONLY);
	if (*fd < 0) {
		perror("open");
		exit(1);
	}
}

void do_lseek(int fd, int ofs)
{
	int rc = lseek(fd, ofs, SEEK_SET);
	if (rc < 0) {
		perror("lseek");
		exit(1);
	}
}

void do_write(int fd, int len)
{
	char *buf = malloc(len);
	int rc;
	if (!buf) {
		printf("not enough memory\n");
		exit(1);
	}

	memset(buf, 0, len);
	rc = safe_write(fd, buf, len);
	if (rc) {
		fprintf(stderr, "safe_write failed with error %d (%s)\n",
			rc, strerror(rc));
		exit(1);
	}

	if (rc != len) {
		printf("invalid number of bytes written\n");
		exit(1);
	}

	free(buf);
}

void do_link(const char *old, const char *new)
{
	int rc = link(old, new);
	if (rc < 0) {
		perror("link");
		exit(1);
	}
}

void do_clone_range(int from, int to, int off, int len)
{
	struct btrfs_ioctl_clone_range_args a;
	int r;

	a.src_fd = from;
	a.src_offset = off;
	a.src_length = len;
	a.dest_offset = off;
	r = ioctl(to, BTRFS_IOC_CLONE_RANGE, &a);
	if (r < 0) {
		perror("ioctl");
		exit(1);
	}
}

void do_snap_async(int fd, const char *name, unsigned long long *transid)
{
	struct btrfs_ioctl_async_vol_args async_args;
	struct btrfs_ioctl_vol_args volargs;
	int r;

	strcpy(volargs.name, name);
	volargs.fd = fd;

	async_args.args = &volargs;
	async_args.transid = transid;

	r = ioctl(fd, BTRFS_IOC_SNAP_CREATE_ASYNC, &async_args);

	if (r < 0) {
		perror("ioctl");
		exit(1);
	}
}

void do_snap_destroy(int fd, const char *name)
{
	struct btrfs_ioctl_vol_args volargs;
	int r;

	strcpy(volargs.name, name);
	volargs.fd = 0;

	r = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &volargs);

	if (r < 0) {
		perror("snap_destroy: ioctl");
		exit(1);
	}
}

void do_snap_wait(int fd, unsigned long long transid)
{
	int r = ioctl(fd, BTRFS_IOC_WAIT_SYNC, &transid);
	if (r < 0) {
		perror("do_snap_wait: ioctl");
		exit(1);
	}
}

void usage_exit(char *arg)
{
	printf("usage: %s <btrfs_base> <snap_name>\n", arg);
	exit(1);
}

#define TEMP_FILENAME "temp"
#define DEST_FILENAME "dest"
#define SRC_FILENAME "src"

int main(int argc, char *argv[])
{
	const char *base_dir;
	const char *snap_name;

	int fd;
	int i;
	unsigned long long transid;

	if (argc < 3)
		usage_exit(argv[0]);

	base_dir = argv[1];
	snap_name = argv[2];

	for (i=0; i<10; i++) {
		printf("%d\n", i);
		do_open_rd(base_dir, &fd);
		do_snap_async(fd, snap_name, &transid);
		sleep(2);
		//do_snap_wait(fd, transid);
		do_snap_destroy(fd, snap_name);
		close(fd);
	}
	
	return 0;
}