Branch data Line data Source code
1 : : #include <stdlib.h>
2 : : #include <unistd.h>
3 : : #include <sys/file.h>
4 : : #include <fcntl.h>
5 : : #include <string.h>
6 : : #include <sys/types.h>
7 : : #include <sys/stat.h>
8 : :
9 : : #include "cr_options.h"
10 : : #include "fdset.h"
11 : : #include "image.h"
12 : : #include "servicefd.h"
13 : : #include "file-lock.h"
14 : : #include "parasite.h"
15 : : #include "parasite-syscall.h"
16 : :
17 : : struct list_head file_lock_list = LIST_HEAD_INIT(file_lock_list);
18 : :
19 : 17738 : struct file_lock *alloc_file_lock(void)
20 : : {
21 : : struct file_lock *flock;
22 : :
23 [ - + ]: 17738 : flock = xzalloc(sizeof(*flock));
24 [ + - ]: 17738 : if (!flock)
25 : : return NULL;
26 : :
27 : 17738 : INIT_LIST_HEAD(&flock->list);
28 : :
29 : 17738 : return flock;
30 : : }
31 : :
32 : 448 : void free_file_locks(void)
33 : : {
34 : : struct file_lock *flock, *tmp;
35 : :
36 [ + + ]: 468 : list_for_each_entry_safe(flock, tmp, &file_lock_list, list) {
37 [ + - ]: 20 : xfree(flock);
38 : : }
39 : :
40 : : INIT_LIST_HEAD(&file_lock_list);
41 : 448 : }
42 : :
43 : 20 : static int dump_one_file_lock(FileLockEntry *fle, const struct cr_fdset *fdset)
44 : : {
45 : 20 : pr_info("flag: %d,type: %d,pid: %d,fd: %d,start: %8"PRIx64",len: %8"PRIx64"\n",
46 : : fle->flag, fle->type, fle->pid, fle->fd, fle->start, fle->len);
47 : :
48 : 20 : return pb_write_one(fdset_fd(fdset, CR_FD_FILE_LOCKS),
49 : : fle, PB_FILE_LOCK);
50 : : }
51 : :
52 : 20 : static int fill_flock_entry(FileLockEntry *fle, const char *fl_flag,
53 : : const char *fl_type, const char *fl_option)
54 : : {
55 [ + + ]: 20 : if (!strcmp(fl_flag, "POSIX")) {
56 : 8 : fle->flag |= FL_POSIX;
57 [ + - ]: 12 : } else if (!strcmp(fl_flag, "FLOCK")) {
58 : 12 : fle->flag |= FL_FLOCK;
59 : : } else {
60 : 0 : pr_err("Unknown file lock!\n");
61 : : goto err;
62 : : }
63 : :
64 [ + + ]: 20 : if (!strcmp(fl_type, "MSNFS")) {
65 : 4 : fle->type |= LOCK_MAND;
66 : :
67 [ + - ]: 4 : if (!strcmp(fl_option, "READ")) {
68 : 4 : fle->type |= LOCK_READ;
69 [ # # ][ # # ]: 0 : } else if (!strcmp(fl_option, "RW")) {
[ # # ]
70 : 0 : fle->type |= LOCK_RW;
71 [ # # ]: 0 : } else if (!strcmp(fl_option, "WRITE")) {
72 : 0 : fle->type |= LOCK_WRITE;
73 : : } else {
74 : 0 : pr_err("Unknown lock option!\n");
75 : : goto err;
76 : : }
77 : : } else {
78 [ - + ]: 16 : if (!strcmp(fl_option, "UNLCK")) {
79 : 0 : fle->type |= F_UNLCK;
80 [ + + ]: 16 : } else if (!strcmp(fl_option, "WRITE")) {
81 : 8 : fle->type |= F_WRLCK;
82 [ - + ]: 8 : } else if (!strcmp(fl_option, "READ")) {
83 : : fle->type |= F_RDLCK;
84 : : } else {
85 : 0 : pr_err("Unknown lock option!\n");
86 : : goto err;
87 : : }
88 : : }
89 : :
90 : : return 0;
91 : : err:
92 : : return -1;
93 : : }
94 : :
95 : 20 : static int get_fd_by_ino(unsigned long i_no, struct parasite_drain_fd *dfds,
96 : : pid_t pid)
97 : : {
98 : : int i;
99 : : char buf[PATH_MAX];
100 : : struct stat fd_stat;
101 : :
102 [ + - ]: 96 : for (i = 0; i < dfds->nr_fds; i++) {
103 : 96 : snprintf(buf, sizeof(buf), "/proc/%d/fd/%d", pid,
104 : : dfds->fds[i]);
105 : :
106 [ - + ]: 96 : if (stat(buf, &fd_stat) == -1) {
107 : 0 : pr_msg("Could not get %s stat!\n", buf);
108 : 0 : continue;
109 : : }
110 : :
111 [ + + ]: 96 : if (fd_stat.st_ino == i_no)
112 : 20 : return dfds->fds[i];
113 : : }
114 : :
115 : : return -1;
116 : : }
117 : :
118 : 919 : int dump_task_file_locks(struct parasite_ctl *ctl,
119 : : struct cr_fdset *fdset, struct parasite_drain_fd *dfds)
120 : : {
121 : : FileLockEntry fle;
122 : : struct file_lock *fl;
123 : :
124 : 919 : pid_t pid = ctl->pid.real;
125 : : int ret = 0;
126 : :
127 [ + + ]: 957 : list_for_each_entry(fl, &file_lock_list, list) {
128 [ + + ]: 38 : if (fl->fl_owner != pid)
129 : 18 : continue;
130 : 20 : pr_info("lockinfo: %lld:%s %s %s %d %02x:%02x:%ld %lld %s\n",
131 : : fl->fl_id, fl->fl_flag, fl->fl_type, fl->fl_option,
132 : : fl->fl_owner, fl->maj, fl->min, fl->i_no,
133 : : fl->start, fl->end);
134 : :
135 : 20 : file_lock_entry__init(&fle);
136 : 20 : fle.pid = fl->fl_owner;
137 : :
138 : 20 : ret = fill_flock_entry(&fle, fl->fl_flag, fl->fl_type,
139 : : fl->fl_option);
140 [ + - ]: 20 : if (ret)
141 : : goto err;
142 : :
143 : 20 : fle.fd = get_fd_by_ino(fl->i_no, dfds, pid);
144 [ + - ]: 20 : if (fle.fd < 0) {
145 : : ret = -1;
146 : : goto err;
147 : : }
148 : :
149 : 20 : fle.start = fl->start;
150 : :
151 [ + - ]: 20 : if (!strncmp(fl->end, "EOF", 3))
152 : 20 : fle.len = 0;
153 : : else
154 : 0 : fle.len = (atoll(fl->end) + 1) - fl->start;
155 : :
156 : 20 : ret = dump_one_file_lock(&fle, fdset);
157 [ - + ]: 20 : if (ret) {
158 : 0 : pr_err("Dump file lock failed!\n");
159 : 0 : goto err;
160 : : }
161 : : }
162 : :
163 : : err:
164 : 919 : return ret;
165 : : }
166 : :
167 : 10 : static int restore_file_lock(FileLockEntry *fle)
168 : : {
169 : : int ret = -1;
170 : : unsigned int cmd;
171 : :
172 [ + + ]: 10 : if (fle->flag & FL_FLOCK) {
173 [ + + ]: 6 : if (fle->type & LOCK_MAND) {
174 : : cmd = fle->type;
175 [ + + ]: 4 : } else if (fle->type == F_RDLCK) {
176 : : cmd = LOCK_SH;
177 [ - + ]: 2 : } else if (fle->type == F_WRLCK) {
178 : : cmd = LOCK_EX;
179 [ # # ]: 0 : } else if (fle->type == F_UNLCK) {
180 : : cmd = LOCK_UN;
181 : : } else {
182 : 0 : pr_err("Unknown flock type!\n");
183 : 0 : goto err;
184 : : }
185 : :
186 : 6 : pr_info("(flock)flag: %d, type: %d, cmd: %d, pid: %d, fd: %d\n",
187 : : fle->flag, fle->type, cmd, fle->pid, fle->fd);
188 : :
189 : 6 : ret = flock(fle->fd, cmd);
190 [ - + ]: 6 : if (ret < 0) {
191 : 0 : pr_err("Can not set flock!\n");
192 : 0 : goto err;
193 : : }
194 [ + - ]: 4 : } else if (fle->flag & FL_POSIX) {
195 : : struct flock flk;
196 : : memset(&flk, 0, sizeof(flk));
197 : :
198 : : flk.l_whence = SEEK_SET;
199 : 4 : flk.l_start = fle->start;
200 : 4 : flk.l_len = fle->len;
201 : 4 : flk.l_pid = fle->pid;
202 : 4 : flk.l_type = fle->type;
203 : :
204 : 4 : pr_info("(posix)flag: %d, type: %d, pid: %d, fd: %d, "
205 : : "start: %8"PRIx64", len: %8"PRIx64"\n",
206 : : fle->flag, fle->type, fle->pid, fle->fd,
207 : : fle->start, fle->len);
208 : :
209 : 4 : ret = fcntl(fle->fd, F_SETLKW, &flk);
210 [ - + ]: 4 : if (ret < 0) {
211 : 0 : pr_err("Can not set posix lock!\n");
212 : 4 : goto err;
213 : : }
214 : : } else {
215 : 0 : pr_err("Unknown file lock style!\n");
216 : 0 : goto err;
217 : : }
218 : :
219 : : return 0;
220 : : err:
221 : 0 : return ret;
222 : : }
223 : :
224 : 348 : static int restore_file_locks(int pid)
225 : : {
226 : : int fd, ret = -1;
227 : : FileLockEntry *fle;
228 : :
229 : 348 : fd = open_image(CR_FD_FILE_LOCKS, O_RSTR | O_OPT, pid);
230 [ - + ]: 348 : if (fd < 0) {
231 [ # # ]: 0 : if (fd == -ENOENT)
232 : : return 0;
233 : : else
234 : 348 : return -1;
235 : : }
236 : :
237 : : while (1) {
238 : 358 : ret = pb_read_one_eof(fd, &fle, PB_FILE_LOCK);
239 [ + + ]: 358 : if (ret <= 0)
240 : : break;
241 : :
242 : 10 : ret = restore_file_lock(fle);
243 : 10 : file_lock_entry__free_unpacked(fle, NULL);
244 : :
245 [ + - ]: 10 : if (ret)
246 : : goto err;
247 : : }
248 : :
249 : 348 : close_safe(&fd);
250 : 348 : return 0;
251 : : err:
252 : 0 : close_safe(&fd);
253 : 0 : return ret;
254 : : }
255 : :
256 : 348 : int prepare_file_locks(int pid)
257 : : {
258 [ + - ]: 348 : if (!opts.handle_file_locks)
259 : : return 0;
260 : :
261 : 348 : pr_info("Restore file locks.\n");
262 : :
263 : 348 : return restore_file_locks(pid);
264 : : }
|