Print this page
NEX-9532 NDMP: readdir errors when file/directory has special characters
Reviewed by: Peer Dampmann <peer.dampmann@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2911 NDMP logging should use syslog and is too chatty
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ndmpd/tlm/tlm_backup_reader.c
+++ new/usr/src/cmd/ndmpd/tlm/tlm_backup_reader.c
1 1 /*
2 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 3 * Copyright (c) 2015 by Delphix. All rights reserved.
4 4 */
5 5
6 6 /*
7 7 * BSD 3 Clause License
8 8 *
9 9 * Copyright (c) 2007, The Storage Networking Industry Association.
10 10 *
11 11 * Redistribution and use in source and binary forms, with or without
12 12 * modification, are permitted provided that the following conditions
13 13 * are met:
14 14 * - Redistributions of source code must retain the above copyright
15 15 * notice, this list of conditions and the following disclaimer.
16 16 *
17 17 * - Redistributions in binary form must reproduce the above copyright
18 18 * notice, this list of conditions and the following disclaimer in
19 19 * the documentation and/or other materials provided with the
20 20 * distribution.
21 21 *
22 22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 23 * nor the names of its contributors may be used to endorse or promote
24 24 * products derived from this software without specific prior written
25 25 * permission.
26 26 *
27 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
29 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 37 * POSSIBILITY OF SUCH DAMAGE.
38 38 */
39 +/* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
40 +
41 +#include <syslog.h>
39 42 #include <stdio.h>
40 43 #include <limits.h>
41 44 #include <time.h>
42 45 #include <sys/stat.h>
43 46 #include <unistd.h>
44 47 #include <dirent.h>
45 48 #include <pthread.h>
46 49 #include <archives.h>
47 50 #include <tlm.h>
48 51 #include <sys/fs/zfs.h>
49 52 #include <sys/mkdev.h>
50 53 #include <libzfs.h>
51 54 #include <libcmdutils.h>
52 55 #include <pwd.h>
53 56 #include <grp.h>
54 57 #include "tlm_proto.h"
55 58
56 59
57 60 static char *get_write_buffer(long size,
58 61 long *actual_size,
59 62 boolean_t zero,
60 63 tlm_cmd_t *);
61 64 static int output_acl_header(sec_attr_t *,
62 65 tlm_cmd_t *);
63 66 static int output_file_header(char *name,
64 67 char *link,
65 68 tlm_acls_t *,
66 69 int section,
67 70 tlm_cmd_t *);
68 71 static int output_xattr_header(char *fname,
69 72 char *aname,
70 73 int fd,
71 74 tlm_acls_t *,
72 75 int section,
73 76 tlm_cmd_t *);
74 77
75 78 extern libzfs_handle_t *zlibh;
76 79 extern mutex_t zlib_mtx;
77 80
78 81 #define S_ISPECIAL(a) (S_ISLNK(a) || S_ISFIFO(a) || S_ISBLK(a) || \
79 82 S_ISCHR(a))
80 83
81 84 /*
82 85 * output_mem
83 86 *
84 87 * Gets a IO write buffer and copies memory to the that.
85 88 */
86 89 static void
87 90 output_mem(tlm_cmd_t *local_commands, char *mem,
88 91 int len)
89 92 {
90 93 long actual_size, rec_size;
91 94 char *rec;
92 95
93 96 while (len > 0) {
94 97 rec = get_write_buffer(len, &actual_size,
95 98 FALSE, local_commands);
96 99 rec_size = min(actual_size, len);
97 100 (void) memcpy(rec, mem, rec_size);
98 101 mem += rec_size;
99 102 len -= rec_size;
100 103 }
101 104 }
102 105
103 106 /*
104 107 * tlm_output_dir
105 108 *
106 109 * Put the directory information into the output buffers.
107 110 */
|
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
108 111 int
109 112 tlm_output_dir(char *name, tlm_acls_t *tlm_acls,
110 113 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
111 114 {
112 115 u_longlong_t pos;
113 116
114 117 /*
115 118 * Send the node or path history of the directory itself.
116 119 */
117 120 pos = tlm_get_data_offset(local_commands);
118 - NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
119 121 (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos);
120 122 (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos);
121 123 /* fhdir_cb is handled in ndmpd_tar3.c */
122 124
123 125 (void) output_acl_header(&tlm_acls->acl_info,
124 126 local_commands);
125 127 (void) output_file_header(name, "", tlm_acls, 0,
126 128 local_commands);
127 129
128 130 return (0);
129 131 }
130 132
131 133 /*
132 134 * tar_putdir
133 135 *
134 136 * Main dir backup function for tar
135 137 */
136 138 int
137 139 tar_putdir(char *name, tlm_acls_t *tlm_acls,
138 140 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
139 141 {
140 142 int rv;
141 143
142 144 rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats);
143 145 return (rv < 0 ? rv : 0);
144 146 }
145 147
146 148 /*
147 149 * output_acl_header
148 150 *
149 151 * output the ACL header record and data
150 152 */
151 153 static int
152 154 output_acl_header(sec_attr_t *acl_info,
153 155 tlm_cmd_t *local_commands)
154 156 {
155 157 long actual_size;
156 158 tlm_tar_hdr_t *tar_hdr;
157 159 long acl_size;
158 160
159 161 if ((acl_info == NULL) || (*acl_info->attr_info == '\0'))
160 162 return (0);
161 163
162 164 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
163 165 &actual_size, TRUE, local_commands);
164 166 if (!tar_hdr)
165 167 return (0);
166 168
167 169 tar_hdr->th_linkflag = LF_ACL;
168 170 acl_info->attr_type = UFSD_ACL;
169 171 (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len),
170 172 "%06o", strlen(acl_info->attr_info));
171 173
172 174 acl_size = sizeof (*acl_info);
173 175 (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE);
174 176 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
175 177 acl_size);
176 178 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
177 179 0444);
178 180 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0);
179 181 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0);
180 182 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
181 183 "%011o ", 0);
182 184 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
183 185 sizeof (tar_hdr->th_magic));
184 186
185 187 tlm_build_header_checksum(tar_hdr);
186 188
187 189 (void) output_mem(local_commands, (void *)acl_info, acl_size);
188 190 return (0);
189 191 }
190 192
191 193 /*
192 194 * output_humongus_header
193 195 *
194 196 * output a special header record for HUGE files
195 197 * output is: 1) a TAR "HUGE" header redord
196 198 * 2) a "file" of size, name
197 199 */
198 200 static int
199 201 output_humongus_header(char *fullname, longlong_t file_size,
200 202 tlm_cmd_t *local_commands)
201 203 {
202 204 char *buf;
203 205 int len;
204 206 long actual_size;
205 207 tlm_tar_hdr_t *tar_hdr;
206 208
207 209 /*
208 210 * buf will contain: "%llu %s":
209 211 * - 20 is the maximum length of 'ulong_tlong' decimal notation.
210 212 * - The first '1' is for the ' ' between the "%llu" and the fullname.
211 213 * - The last '1' is for the null-terminator of fullname.
212 214 */
213 215 len = 20 + 1 + strlen(fullname) + 1;
214 216
215 217 if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL)
216 218 return (-1);
217 219
218 220 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
219 221 &actual_size, TRUE, local_commands);
220 222 if (!tar_hdr) {
221 223 free(buf);
222 224 return (0);
223 225 }
224 226
225 227 tar_hdr->th_linkflag = LF_HUMONGUS;
226 228 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
227 229 len);
228 230 tlm_build_header_checksum(tar_hdr);
229 231 (void) snprintf(buf, len, "%lld %s", file_size, fullname);
230 232 (void) output_mem(local_commands, buf, len);
231 233
232 234 free(buf);
233 235 return (0);
234 236 }
235 237
236 238
237 239 /*
238 240 * output_xattr_header
239 241 *
240 242 * output the TAR header record for extended attributes
241 243 */
242 244 static int
243 245 output_xattr_header(char *fname, char *aname, int fd,
244 246 tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
245 247 {
246 248 struct stat64 *attr = &tlm_acls->acl_attr;
247 249 struct xattr_hdr *xhdr;
248 250 struct xattr_buf *xbuf;
249 251 tlm_tar_hdr_t *tar_hdr;
|
↓ open down ↓ |
121 lines elided |
↑ open up ↑ |
250 252 long actual_size;
251 253 char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
252 254 int hsize;
253 255 int comlen;
254 256 int namesz;
255 257
256 258 if (section_name == NULL)
257 259 return (-TLM_NO_SCRATCH_SPACE);
258 260
259 261 if (fstat64(fd, attr) == -1) {
260 - NDMP_LOG(LOG_DEBUG, "output_file_header stat failed.");
262 + syslog(LOG_ERR, "output_file_header stat failed.");
261 263 free(section_name);
262 264 return (-TLM_OPEN_ERR);
263 265 }
264 266
265 267 /*
266 268 * if the file has to go out in sections,
267 269 * we must mung the name.
268 270 */
269 271 if (section == 0) {
270 272 (void) snprintf(section_name, TLM_MAX_PATH_NAME,
271 273 "/dev/null/%s.hdr", aname);
272 274 } else {
273 275 (void) snprintf(section_name,
274 276 TLM_MAX_PATH_NAME, "%s.%03d", aname, section);
275 277 }
276 278 namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */
277 279 hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf);
278 280 comlen = namesz + sizeof (struct xattr_buf);
279 281
280 282 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
281 283 &actual_size, TRUE, local_commands);
282 284 if (!tar_hdr) {
283 285 free(section_name);
284 286 return (0);
285 287 }
286 288
287 289 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
288 290
289 291 tar_hdr->th_linkflag = LF_XATTR;
290 292 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
291 293 hsize);
292 294 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
|
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
293 295 attr->st_mode & 07777);
294 296 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
295 297 attr->st_uid);
296 298 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
297 299 attr->st_gid);
298 300 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
299 301 attr->st_mtime);
300 302 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
301 303 sizeof (tar_hdr->th_magic));
302 304
303 - NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
304 - aname, hsize, attr->st_mode & 07777, attr->st_uid, attr->st_gid);
305 -
306 305 tlm_build_header_checksum(tar_hdr);
307 306
308 307 xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE,
309 308 &actual_size, TRUE, local_commands);
310 309 if (!xhdr) {
311 310 free(section_name);
312 311 return (0);
313 312 }
314 313
315 314 (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s",
316 315 XATTR_ARCH_VERS);
317 316 (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d",
318 317 sizeof (xhdr->h_size) - 1, hsize);
319 318 (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len),
320 319 "%0*d", sizeof (xhdr->h_component_len) - 1, comlen);
321 320 (void) snprintf(xhdr->h_link_component_len,
322 321 sizeof (xhdr->h_link_component_len), "%0*d",
323 322 sizeof (xhdr->h_link_component_len) - 1, 0);
324 323
325 324 xbuf = (struct xattr_buf *)(((caddr_t)xhdr) +
326 325 sizeof (struct xattr_hdr));
327 326 (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d",
328 327 sizeof (xbuf->h_namesz) - 1, namesz);
329 328
330 329 /* No support for links in extended attributes */
331 330 xbuf->h_typeflag = LF_NORMAL;
332 331
333 332 (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE);
334 333 (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname,
335 334 TLM_NAME_SIZE);
336 335
337 336 free(section_name);
338 337 return (0);
339 338 }
340 339
341 340
342 341 /*
343 342 * output_file_header
344 343 *
345 344 * output the TAR header record
346 345 */
347 346 static int
348 347 output_file_header(char *name, char *link,
349 348 tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
350 349 {
351 350 static longlong_t file_count = 0;
352 351 struct stat64 *attr = &tlm_acls->acl_attr;
353 352 tlm_tar_hdr_t *tar_hdr;
354 353 long actual_size;
355 354 boolean_t long_name = FALSE;
356 355 boolean_t long_link = FALSE;
357 356 char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
358 357 int nmlen, lnklen;
359 358 uid_t uid;
360 359 gid_t gid;
361 360 char *uname = "";
362 361 char *gname = "";
363 362 struct passwd *pwd;
364 363 struct group *grp;
365 364
366 365 if (section_name == NULL)
367 366 return (-TLM_NO_SCRATCH_SPACE);
368 367
369 368 /*
370 369 * if the file has to go out in sections,
371 370 * we must mung the name.
372 371 */
373 372 if (section == 0) {
374 373 (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME);
375 374 } else {
376 375 (void) snprintf(section_name,
377 376 TLM_MAX_PATH_NAME, "%s.%03d", name, section);
378 377 }
379 378
380 379 if ((pwd = getpwuid(attr->st_uid)) != NULL)
381 380 uname = pwd->pw_name;
382 381 if ((grp = getgrgid(attr->st_gid)) != NULL)
383 382 gname = grp->gr_name;
384 383
385 384 if ((ulong_t)(uid = attr->st_uid) > (ulong_t)OCTAL7CHAR)
386 385 uid = UID_NOBODY;
387 386 if ((ulong_t)(gid = attr->st_gid) > (ulong_t)OCTAL7CHAR)
388 387 gid = GID_NOBODY;
389 388
390 389 nmlen = strlen(section_name);
391 390 if (nmlen >= NAMSIZ) {
392 391 /*
393 392 * file name is too big, it must go out
394 393 * in its own data file
395 394 */
396 395 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
397 396 &actual_size, TRUE, local_commands);
398 397 if (!tar_hdr) {
399 398 free(section_name);
400 399 return (0);
401 400 }
402 401 (void) snprintf(tar_hdr->th_name,
403 402 sizeof (tar_hdr->th_name),
404 403 "%s%08qd.fil",
405 404 LONGNAME_PREFIX,
406 405 file_count++);
407 406
408 407 tar_hdr->th_linkflag = LF_LONGNAME;
409 408 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size),
410 409 "%011o ", nmlen);
411 410 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode),
412 411 "%06o ", attr->st_mode & 07777);
413 412 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid),
414 413 "%06o ", uid);
415 414 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid),
416 415 "%06o ", gid);
417 416 (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname),
418 417 "%.31s", uname);
419 418 (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname),
420 419 "%.31s", gname);
421 420 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
422 421 "%011o ", attr->st_mtime);
423 422 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
424 423 sizeof (tar_hdr->th_magic));
425 424
426 425 tlm_build_header_checksum(tar_hdr);
427 426
428 427 (void) output_mem(local_commands,
429 428 (void *)section_name, nmlen);
430 429 long_name = TRUE;
431 430 }
432 431
433 432 lnklen = strlen(link);
434 433 if (lnklen >= NAMSIZ) {
435 434 /*
436 435 * link name is too big, it must go out
437 436 * in its own data file
438 437 */
439 438 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
440 439 &actual_size, TRUE, local_commands);
441 440 if (!tar_hdr) {
442 441 free(section_name);
443 442 return (0);
444 443 }
445 444 (void) snprintf(tar_hdr->th_linkname,
446 445 sizeof (tar_hdr->th_name),
447 446 "%s%08qd.slk",
448 447 LONGNAME_PREFIX,
449 448 file_count++);
450 449
451 450 tar_hdr->th_linkflag = LF_LONGLINK;
452 451 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size),
453 452 "%011o ", lnklen);
454 453 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode),
455 454 "%06o ", attr->st_mode & 07777);
456 455 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid),
457 456 "%06o ", uid);
458 457 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid),
459 458 "%06o ", gid);
460 459 (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname),
461 460 "%.31s", uname);
462 461 (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname),
463 462 "%.31s", gname);
464 463 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
465 464 "%011o ", attr->st_mtime);
466 465 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
467 466 sizeof (tar_hdr->th_magic));
468 467
469 468 tlm_build_header_checksum(tar_hdr);
470 469
471 470 (void) output_mem(local_commands, (void *)link,
472 471 lnklen);
473 472 long_link = TRUE;
474 473 }
475 474 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
476 475 &actual_size, TRUE, local_commands);
477 476 if (!tar_hdr) {
478 477 free(section_name);
479 478 return (0);
480 479 }
|
↓ open down ↓ |
165 lines elided |
↑ open up ↑ |
481 480 if (long_name) {
482 481 (void) snprintf(tar_hdr->th_name,
483 482 sizeof (tar_hdr->th_name),
484 483 "%s%08qd.fil",
485 484 LONGNAME_PREFIX,
486 485 file_count++);
487 486 } else {
488 487 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
489 488 }
490 489
491 - NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE",
492 - link);
493 -
494 490 if (long_link) {
495 491 (void) snprintf(tar_hdr->th_linkname,
496 492 sizeof (tar_hdr->th_name),
497 493 "%s%08qd.slk",
498 494 LONGNAME_PREFIX,
499 495 file_count++);
500 496 } else {
501 497 (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE);
502 498 }
503 499 switch (attr->st_mode & S_IFMT) {
504 500 case S_IFDIR:
505 501 tar_hdr->th_linkflag = LF_DIR;
506 502 break;
507 503 case S_IFIFO:
508 504 tar_hdr->th_linkflag = LF_FIFO;
509 505 break;
510 506 case S_IFBLK:
511 507 case S_IFCHR:
512 508 if (S_ISBLK(attr->st_mode))
513 509 tar_hdr->th_linkflag = LF_BLK;
514 510 else
515 511 tar_hdr->th_linkflag = LF_CHR;
516 512 (void) snprintf(tar_hdr->th_shared.th_dev.th_devmajor,
517 513 sizeof (tar_hdr->th_shared.th_dev.th_devmajor), "%06o ",
518 514 major(attr->st_rdev));
519 515 (void) snprintf(tar_hdr->th_shared.th_dev.th_devminor,
520 516 sizeof (tar_hdr->th_shared.th_dev.th_devminor), "%06o ",
521 517 minor(attr->st_rdev));
522 518 break;
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
523 519 default:
524 520 if (attr->st_nlink > 1) {
525 521 /* mark file with hardlink LF_LINK */
526 522 tar_hdr->th_linkflag = LF_LINK;
527 523 (void) snprintf(tar_hdr->th_shared.th_hlink_ino,
528 524 sizeof (tar_hdr->th_shared.th_hlink_ino),
529 525 "%011llo ", attr->st_ino);
530 526 } else {
531 527 tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL :
532 528 LF_SYMLINK;
533 - NDMP_LOG(LOG_DEBUG, "linkflag: '%c'",
534 - tar_hdr->th_linkflag);
535 529 }
536 530 }
537 531 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
538 532 (long)attr->st_size);
539 533 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
540 534 attr->st_mode & 07777);
541 535 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
542 536 uid);
543 537 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
544 538 gid);
545 539 (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s",
546 540 uname);
547 541 (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s",
548 542 gname);
549 543 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
550 544 attr->st_mtime);
551 545 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
552 546 sizeof (tar_hdr->th_magic));
553 547
554 548 tlm_build_header_checksum(tar_hdr);
555 549 if (long_name || long_link) {
556 550 if (file_count > 99999990) {
557 551 file_count = 0;
558 552 }
559 553 }
560 554 free(section_name);
561 555 return (0);
562 556 }
563 557
564 558
565 559 /*
566 560 * tlm_readlink
567 561 *
568 562 * Read where the softlink points to. Read the link in the checkpointed
569 563 * path if the backup is being done on a checkpointed file system.
570 564 */
571 565 static int
572 566 tlm_readlink(char *nm, char *snap, char *buf, int bufsize)
|
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
573 567 {
574 568 int len;
575 569
576 570 if ((len = readlink(snap, buf, bufsize)) >= 0) {
577 571 /*
578 572 * realink(2) doesn't null terminate the link name. We must
579 573 * do it here.
580 574 */
581 575 buf[len] = '\0';
582 576 } else {
583 - NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]",
577 + syslog(LOG_ERR, "Error %d reading softlink of [%s]",
584 578 errno, nm);
585 579 buf[0] = '\0';
586 580
587 581 /* Backup the link if the destination missing */
588 582 if (errno == ENOENT)
589 583 return (0);
590 584
591 585 }
592 586
593 587 return (len);
594 588 }
595 589
596 590 /*
597 591 * Read the system attribute file in a single buffer to write
598 592 * it as a single write. A partial write to system attribute would
599 593 * cause an EINVAL on write.
600 594 */
601 595 static char *
602 596 get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size,
603 597 tlm_cmd_t *lc)
604 598 {
605 599 int len;
606 600 long write_size;
607 601
608 602 if (rec_size > buf_size)
609 603 return (rec);
610 604
611 605 len = rec_size;
612 606 (void) memcpy(rec, buf, len);
613 607 buf += len;
614 608 while (rec_size < buf_size) {
615 609 rec = get_write_buffer(buf_size - rec_size,
616 610 &write_size, FALSE, lc);
617 611 if (!rec)
618 612 return (0);
619 613
620 614 len = min(buf_size - rec_size, write_size);
621 615 (void) memcpy(rec, buf, len);
622 616 rec_size += len;
623 617 buf += len;
624 618 }
625 619 return (rec);
626 620 }
627 621
628 622
629 623 /*
630 624 * tlm_output_xattr
631 625 *
632 626 * Put this file into the output buffers.
633 627 */
634 628 /*ARGSUSED*/
635 629 longlong_t
636 630 tlm_output_xattr(char *dir, char *name, char *chkdir,
|
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
637 631 tlm_acls_t *tlm_acls, tlm_commands_t *commands,
638 632 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
639 633 {
640 634 char *fullname; /* directory + name */
641 635 char *snapname; /* snapshot name */
642 636 int section; /* section of a huge file */
643 637 int fd;
644 638 int afd = 0;
645 639 longlong_t seek_spot = 0; /* location in the file */
646 640 /* for Multi Volume record */
647 - u_longlong_t pos;
648 641 DIR *dp;
649 642 struct dirent *dtp;
650 643 char *attrname;
651 644 char *fnamep;
652 645 int rv = 0;
653 646
654 647 if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
655 648 return (TLM_NO_SOURCE_FILE);
656 649 }
657 650
658 651 fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
659 652 if (fullname == NULL) {
660 653 free(fullname);
661 654 return (-TLM_NO_SCRATCH_SPACE);
662 655 }
663 656
664 657 if (!tlm_cat_path(fullname, dir, name)) {
665 - NDMP_LOG(LOG_DEBUG, "Path too long.");
658 + syslog(LOG_ERR, "Path too long.");
666 659 free(fullname);
667 660 return (-TLM_NO_SCRATCH_SPACE);
668 661 }
669 662
670 663 if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 &&
671 664 sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) {
672 665 free(fullname);
673 666 return (0);
674 667 }
675 668
676 669 attrname = ndmp_malloc(TLM_MAX_PATH_NAME);
677 670 snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
678 671 if (attrname == NULL || snapname == NULL) {
679 672 rv = -TLM_NO_SCRATCH_SPACE;
680 673 goto err_out;
681 674 }
682 675
683 676 if (!tlm_cat_path(snapname, chkdir, name)) {
684 - NDMP_LOG(LOG_DEBUG, "Path too long.");
677 + syslog(LOG_ERR, "Path too long.");
685 678 rv = -TLM_NO_SCRATCH_SPACE;
686 679 goto err_out;
687 680 }
688 681
689 682 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
690 683
691 684 /*
692 685 * Open the file for reading.
693 686 */
694 687 fd = attropen(fnamep, ".", O_RDONLY);
695 688 if (fd == -1) {
696 - NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]",
689 + syslog(LOG_ERR, "BACKUP> Can't open file [%s][%s]",
697 690 fullname, fnamep);
698 691 rv = TLM_NO_SOURCE_FILE;
699 692 goto err_out;
700 693 }
701 694
702 - pos = tlm_get_data_offset(local_commands);
703 - NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
704 -
705 695 section = 0;
706 696
707 697 dp = (DIR *)fdopendir(fd);
708 698 if (dp == NULL) {
709 - NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname);
699 + syslog(LOG_ERR, "BACKUP> Can't open file [%s]", fullname);
710 700 (void) close(fd);
711 701 rv = TLM_NO_SOURCE_FILE;
712 702 goto err_out;
713 703 }
714 704
715 705 while ((dtp = readdir(dp)) != NULL) {
716 706 int section_size;
717 707
718 708 if (*dtp->d_name == '.')
719 709 continue;
720 710
721 711 if (sysattr_rdonly(dtp->d_name))
722 712 continue;
723 713
724 714 afd = attropen(fnamep, dtp->d_name, O_RDONLY);
725 715 if (afd == -1) {
726 - NDMP_LOG(LOG_DEBUG,
716 + syslog(LOG_ERR,
727 717 "problem(%d) opening xattr file [%s][%s]", errno,
728 718 fullname, fnamep);
729 719 goto tear_down;
730 720 }
731 721
732 722 (void) output_xattr_header(fullname, dtp->d_name, afd,
733 723 tlm_acls, section, local_commands);
734 724 (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s",
735 725 dtp->d_name);
736 726 (void) output_file_header(attrname, "", tlm_acls, 0,
737 727 local_commands);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
738 728
739 729 section_size = (long)llmin(tlm_acls->acl_attr.st_size,
740 730 (longlong_t)TLM_MAX_TAR_IMAGE);
741 731
742 732 /* We only can read upto one section extended attribute */
743 733 while (section_size > 0) {
744 734 char *buf;
745 735 long actual_size;
746 736 int read_size;
747 737 int sysattr_read = 0;
748 - char *rec;
749 - int size;
738 + char *rec = NULL;
739 + int size = 0;
750 740
751 741 /*
752 742 * check for Abort commands
753 743 */
754 744 if (commands->tcs_reader != TLM_BACKUP_RUN) {
755 745 local_commands->tc_writer = TLM_ABORT;
756 746 goto tear_down;
757 747 }
758 748
759 749 local_commands->tc_buffers->tbs_buffer[
760 750 local_commands->tc_buffers->tbs_buffer_in].
761 751 tb_file_size = section_size;
762 752 local_commands->tc_buffers->tbs_buffer[
763 753 local_commands->tc_buffers->tbs_buffer_in].
764 754 tb_seek_spot = seek_spot;
765 755
766 756 buf = get_write_buffer(section_size,
767 757 &actual_size, FALSE, local_commands);
768 758 if (!buf)
769 759 goto tear_down;
770 760
771 761 if ((actual_size < section_size) &&
772 762 sysattr_rw(dtp->d_name)) {
773 763 rec = buf;
774 764 buf = ndmp_malloc(section_size);
775 765 if (!buf)
776 766 goto tear_down;
777 767 size = actual_size;
778 768 actual_size = section_size;
779 769 sysattr_read = 1;
780 770 }
781 771
782 772 /*
783 773 * check for Abort commands
784 774 */
785 775 if (commands->tcs_reader != TLM_BACKUP_RUN) {
786 776 local_commands->tc_writer = TLM_ABORT;
787 777 goto tear_down;
788 778 }
789 779
790 780 read_size = min(section_size, actual_size);
791 781 if ((actual_size = read(afd, buf, read_size)) < 0)
792 782 break;
793 783
794 784 if (sysattr_read) {
795 785 if (get_write_one_buf(buf, rec, read_size,
796 786 size, local_commands) == 0) {
797 787 free(buf);
|
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
798 788 goto tear_down;
799 789 }
800 790 free(buf);
801 791 }
802 792
803 793
804 794 NS_ADD(rdisk, actual_size);
805 795 NS_INC(rfile);
806 796
807 797 if (actual_size == -1) {
808 - NDMP_LOG(LOG_DEBUG,
798 + syslog(LOG_ERR,
809 799 "problem(%d) reading file [%s][%s]",
810 800 errno, fullname, snapname);
811 801 goto tear_down;
812 802 }
813 803 seek_spot += actual_size;
814 804 section_size -= actual_size;
815 805 }
816 806 (void) close(afd);
817 807 afd = -1;
818 808 }
819 809
820 810 tear_down:
821 811 local_commands->tc_buffers->tbs_buffer[
822 812 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
823 813
824 814 if (afd > 0)
825 815 (void) close(afd);
826 816
827 817 /* closedir closes fd too */
828 818 (void) closedir(dp);
829 819
830 820 err_out:
831 821 free(fullname);
832 822 free(attrname);
833 823 free(snapname);
834 824 return (rv);
835 825 }
836 826
837 827
838 828 /*
839 829 * tlm_output_file
840 830 *
841 831 * Put this file into the output buffers.
842 832 */
843 833 longlong_t
844 834 tlm_output_file(char *dir, char *name, char *chkdir,
845 835 tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands,
846 836 tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q)
847 837 {
848 838 char *fullname; /* directory + name */
849 839 char *snapname; /* snapshot name */
850 840 char *linkname; /* where this file points */
851 841 int section = 0; /* section of a huge file */
852 842 int fd;
853 843 longlong_t real_size; /* the origional file size */
854 844 longlong_t file_size; /* real size of this file */
855 845 longlong_t seek_spot = 0; /* location in the file */
856 846 /* for Multi Volume record */
857 847 u_longlong_t pos;
858 848 char *fnamep;
859 849
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
860 850 /* Indicate whether a file with the same inode has been backed up. */
861 851 int hardlink_done = 0;
862 852
863 853 /*
864 854 * If a file with the same inode has been backed up, hardlink_pos holds
865 855 * the tape offset of the data record.
866 856 */
867 857 u_longlong_t hardlink_pos = 0;
868 858
869 859 if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) {
870 - NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name);
860 + syslog(LOG_ERR, "Path too long [%s][%s]", dir, name);
871 861 return (-TLM_NO_SCRATCH_SPACE);
872 862 }
873 863
874 864 fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
875 865 linkname = ndmp_malloc(TLM_MAX_PATH_NAME);
876 866 snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
877 867 if (fullname == NULL || linkname == NULL || snapname == NULL) {
878 868 real_size = -TLM_NO_SCRATCH_SPACE;
879 869 goto err_out;
880 870 }
881 871 if (!tlm_cat_path(fullname, dir, name) ||
882 872 !tlm_cat_path(snapname, chkdir, name)) {
883 - NDMP_LOG(LOG_DEBUG, "Path too long.");
873 + syslog(LOG_ERR, "Path too long.");
884 874 real_size = -TLM_NO_SCRATCH_SPACE;
885 875 goto err_out;
886 876 }
887 877
888 878 pos = tlm_get_data_offset(local_commands);
889 - NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
890 879
891 880 if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
892 881 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) {
893 882 file_size = tlm_readlink(fullname, snapname, linkname,
894 883 TLM_MAX_PATH_NAME-1);
895 884 if (file_size < 0) {
896 885 real_size = -ENOENT;
897 886 goto err_out;
898 887 }
899 888 }
900 889
901 890 /*
902 891 * Since soft links can not be read(2), we should only
903 892 * backup the file header.
904 893 */
905 894 (void) output_file_header(fullname,
906 895 linkname,
907 896 tlm_acls,
908 897 section,
909 898 local_commands);
910 899
911 900 (void) tlm_log_fhnode(job_stats, dir, name,
912 901 &tlm_acls->acl_attr, pos);
913 902 (void) tlm_log_fhpath_name(job_stats, fullname,
914 903 &tlm_acls->acl_attr, pos);
915 904
916 905 free(fullname);
917 906 free(linkname);
918 907 free(snapname);
919 908 return (0);
920 909 }
921 910
922 911 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
923 912
924 913 /*
925 914 * For hardlink, only read the data if no other link
926 915 * belonging to the same inode has been backed up.
927 916 */
928 917 if (tlm_acls->acl_attr.st_nlink > 1) {
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
929 918 hardlink_done = !hardlink_q_get(hardlink_q,
930 919 tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL);
931 920 }
932 921
933 922 if (!hardlink_done) {
934 923 /*
935 924 * Open the file for reading.
936 925 */
937 926 fd = open(fnamep, O_RDONLY);
938 927 if (fd == -1) {
939 - NDMP_LOG(LOG_DEBUG,
928 + syslog(LOG_ERR,
940 929 "BACKUP> Can't open file [%s][%s] err(%d)",
941 930 fullname, fnamep, errno);
942 931 real_size = -TLM_NO_SOURCE_FILE;
943 932 goto err_out;
944 933 }
945 934 } else {
946 - NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
935 + syslog(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
947 936 tlm_acls->acl_attr.st_ino, hardlink_pos);
948 937
949 938 fd = -1;
950 939 }
951 940
952 941 linkname[0] = 0;
953 942
954 943 real_size = tlm_acls->acl_attr.st_size;
955 944 (void) output_acl_header(&tlm_acls->acl_info,
956 945 local_commands);
957 946
958 947 /*
959 948 * section = 0: file is small enough for TAR
960 949 * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
961 950 * and the file name gets munged
962 951 */
963 952 file_size = real_size;
964 953 if (file_size > TLM_MAX_TAR_IMAGE) {
965 954 if (output_humongus_header(fullname, file_size,
966 955 local_commands) < 0) {
967 956 (void) close(fd);
968 957 real_size = -TLM_NO_SCRATCH_SPACE;
969 958 goto err_out;
970 959 }
971 960 section = 1;
972 961 } else {
973 962 section = 0;
974 963 }
975 964
976 965 /*
977 966 * For hardlink, if other link belonging to the same inode
978 967 * has been backed up, only backup an empty record.
979 968 */
980 969 if (hardlink_done)
981 970 file_size = 0;
982 971
983 972 /*
984 973 * work
985 974 */
986 975 if (file_size == 0) {
987 976 (void) output_file_header(fullname,
988 977 linkname,
989 978 tlm_acls,
990 979 section,
991 980 local_commands);
992 981 /*
993 982 * this can fall right through since zero size files
994 983 * will be skipped by the WHILE loop anyway
995 984 */
996 985 }
997 986
998 987 while (file_size > 0) {
999 988 int section_size = llmin(file_size,
1000 989 (longlong_t)TLM_MAX_TAR_IMAGE);
1001 990
1002 991 tlm_acls->acl_attr.st_size = (longlong_t)section_size;
1003 992 (void) output_file_header(fullname,
1004 993 linkname,
1005 994 tlm_acls,
1006 995 section,
1007 996 local_commands);
1008 997 while (section_size > 0) {
1009 998 char *buf;
1010 999 long actual_size;
1011 1000 int read_size;
1012 1001
1013 1002 /*
1014 1003 * check for Abort commands
1015 1004 */
1016 1005 if (commands->tcs_reader != TLM_BACKUP_RUN) {
1017 1006 local_commands->tc_writer = TLM_ABORT;
1018 1007 goto tear_down;
1019 1008 }
1020 1009
1021 1010 local_commands->tc_buffers->tbs_buffer[
1022 1011 local_commands->tc_buffers->tbs_buffer_in].
1023 1012 tb_file_size = section_size;
1024 1013 local_commands->tc_buffers->tbs_buffer[
1025 1014 local_commands->tc_buffers->tbs_buffer_in].
1026 1015 tb_seek_spot = seek_spot;
1027 1016
1028 1017 buf = get_write_buffer(section_size,
1029 1018 &actual_size, FALSE, local_commands);
1030 1019 if (!buf)
1031 1020 goto tear_down;
1032 1021
1033 1022 /*
1034 1023 * check for Abort commands
1035 1024 */
1036 1025 if (commands->tcs_reader != TLM_BACKUP_RUN) {
1037 1026 local_commands->tc_writer = TLM_ABORT;
1038 1027 goto tear_down;
1039 1028 }
|
↓ open down ↓ |
83 lines elided |
↑ open up ↑ |
1040 1029
1041 1030 read_size = min(section_size, actual_size);
1042 1031 actual_size = read(fd, buf, read_size);
1043 1032 NS_ADD(rdisk, actual_size);
1044 1033 NS_INC(rfile);
1045 1034
1046 1035 if (actual_size == 0)
1047 1036 break;
1048 1037
1049 1038 if (actual_size == -1) {
1050 - NDMP_LOG(LOG_DEBUG,
1039 + syslog(LOG_ERR,
1051 1040 "problem(%d) reading file [%s][%s]",
1052 1041 errno, fullname, snapname);
1053 1042 goto tear_down;
1054 1043 }
1055 1044 seek_spot += actual_size;
1056 1045 file_size -= actual_size;
1057 1046 section_size -= actual_size;
1058 1047 }
1059 1048 section++;
1060 1049 }
1061 1050
1062 1051 /*
1063 1052 * If data belonging to this hardlink has been backed up, add the link
1064 1053 * to hardlink queue.
1065 1054 */
1066 1055 if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) {
1067 1056 (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino,
1068 1057 pos, NULL, 0);
1069 - NDMP_LOG(LOG_DEBUG,
1058 + syslog(LOG_DEBUG,
1070 1059 "backed up hardlink file %s, inode = %llu, pos = %llu ",
1071 1060 fullname, tlm_acls->acl_attr.st_ino, pos);
1072 1061 }
1073 1062
1074 1063 /*
1075 1064 * For hardlink, if other link belonging to the same inode has been
1076 1065 * backed up, no add_node entry should be sent for this link.
1077 1066 */
1078 1067 if (hardlink_done) {
1079 - NDMP_LOG(LOG_DEBUG,
1068 + syslog(LOG_DEBUG,
1080 1069 "backed up hardlink link %s, inode = %llu, pos = %llu ",
1081 1070 fullname, tlm_acls->acl_attr.st_ino, hardlink_pos);
1082 1071 } else {
1083 1072 (void) tlm_log_fhnode(job_stats, dir, name,
1084 1073 &tlm_acls->acl_attr, pos);
1085 1074 }
1086 1075
1087 1076 (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr,
1088 1077 pos);
1089 1078
1090 1079 tear_down:
1091 1080 local_commands->tc_buffers->tbs_buffer[
1092 1081 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
1093 1082
1094 1083 (void) close(fd);
1095 1084
1096 1085 err_out:
1097 1086 free(fullname);
1098 1087 free(linkname);
1099 1088 free(snapname);
1100 1089 return (real_size);
1101 1090 }
1102 1091
1103 1092 /*
1104 1093 * tar_putfile
1105 1094 *
1106 1095 * Main file backup function for tar
1107 1096 */
1108 1097 int
1109 1098 tar_putfile(char *dir, char *name, char *chkdir,
1110 1099 tlm_acls_t *tlm_acls, tlm_commands_t *commands,
1111 1100 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats,
1112 1101 struct hardlink_q *hardlink_q)
1113 1102 {
1114 1103 int rv;
1115 1104
1116 1105 rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands,
1117 1106 local_commands, job_stats, hardlink_q);
1118 1107 if (rv < 0)
1119 1108 return (rv);
1120 1109
1121 1110 rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands,
1122 1111 local_commands, job_stats);
1123 1112
1124 1113 return (rv < 0 ? rv : 0);
1125 1114 }
1126 1115
1127 1116 /*
1128 1117 * get_write_buffer
1129 1118 *
1130 1119 * a wrapper to tlm_get_write_buffer so that
1131 1120 * we can cleanly detect ABORT commands
1132 1121 * without involving the TLM library with
1133 1122 * our problems.
1134 1123 */
1135 1124 static char *
1136 1125 get_write_buffer(long size, long *actual_size,
1137 1126 boolean_t zero, tlm_cmd_t *local_commands)
1138 1127 {
1139 1128 while (local_commands->tc_reader == TLM_BACKUP_RUN) {
1140 1129 char *rec = tlm_get_write_buffer(size, actual_size,
1141 1130 local_commands->tc_buffers, zero);
1142 1131 if (rec != 0) {
1143 1132 return (rec);
1144 1133 }
1145 1134 }
1146 1135 return (NULL);
1147 1136 }
1148 1137
1149 1138 #define NDMP_MORE_RECORDS 2
1150 1139
1151 1140 /*
1152 1141 * write_tar_eof
1153 1142 *
1154 1143 * This function is initially written for NDMP support. It appends
1155 1144 * two tar headers to the tar file, and also N more empty buffers
1156 1145 * to make sure that the two tar headers will be read as a part of
1157 1146 * a mover record and don't get locked because of EOM on the mover
1158 1147 * side.
1159 1148 */
1160 1149 void
1161 1150 write_tar_eof(tlm_cmd_t *local_commands)
1162 1151 {
1163 1152 int i;
1164 1153 long actual_size;
1165 1154 tlm_buffers_t *bufs;
1166 1155
1167 1156 /*
1168 1157 * output 2 zero filled records,
1169 1158 * TAR wants this.
1170 1159 */
1171 1160 (void) get_write_buffer(sizeof (tlm_tar_hdr_t),
1172 1161 &actual_size, TRUE, local_commands);
1173 1162 (void) get_write_buffer(sizeof (tlm_tar_hdr_t),
1174 1163 &actual_size, TRUE, local_commands);
1175 1164
1176 1165 /*
1177 1166 * NDMP: Clear the rest of the buffer and write two more buffers
1178 1167 * to the tape.
1179 1168 */
1180 1169 bufs = local_commands->tc_buffers;
1181 1170 (void) get_write_buffer(bufs->tbs_data_transfer_size,
1182 1171 &actual_size, TRUE, local_commands);
1183 1172
1184 1173 for (i = 0; i < NDMP_MORE_RECORDS &&
1185 1174 local_commands->tc_reader == TLM_BACKUP_RUN; i++) {
1186 1175 /*
1187 1176 * We don't need the return value of get_write_buffer(),
1188 1177 * since it's already zeroed out if the buffer is returned.
1189 1178 */
1190 1179 (void) get_write_buffer(bufs->tbs_data_transfer_size,
1191 1180 &actual_size, TRUE, local_commands);
1192 1181 }
1193 1182
1194 1183 bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE;
1195 1184 tlm_buffer_release_in_buf(bufs);
1196 1185 }
1197 1186
1198 1187 /*
1199 1188 * Callback to backup each ZFS property
1200 1189 */
1201 1190 static int
1202 1191 zfs_put_prop_cb(int prop, void *pp)
1203 1192 {
1204 1193 ndmp_metadata_handle_t *mhd;
1205 1194 ndmp_metadata_header_ext_t *mhp;
1206 1195 ndmp_metadata_property_ext_t *mpp;
1207 1196 char vbuf[ZFS_MAXPROPLEN];
1208 1197 char sbuf[ZFS_MAXPROPLEN];
1209 1198 zprop_source_t stype;
1210 1199 char *sourcestr;
1211 1200
1212 1201 if (pp == NULL)
1213 1202 return (ZPROP_INVAL);
1214 1203
1215 1204 mhd = (ndmp_metadata_handle_t *)pp;
1216 1205 mhp = mhd->ml_xhdr;
1217 1206 mpp = &mhp->nh_property[mhp->nh_count];
1218 1207
1219 1208 if (mhp->nh_count * sizeof (ndmp_metadata_property_ext_t) +
1220 1209 sizeof (ndmp_metadata_header_ext_t) > mhp->nh_total_bytes)
1221 1210 return (ZPROP_INVAL);
1222 1211
1223 1212 if (zfs_prop_get(mhd->ml_handle, prop, vbuf, sizeof (vbuf),
1224 1213 &stype, sbuf, sizeof (sbuf), B_TRUE) != 0) {
1225 1214 mhp->nh_count++;
1226 1215 return (ZPROP_CONT);
1227 1216 }
1228 1217
1229 1218 (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop),
1230 1219 ZFS_MAX_DATASET_NAME_LEN);
1231 1220 (void) strlcpy(mpp->mp_value, vbuf, ZFS_MAXPROPLEN);
1232 1221
1233 1222 switch (stype) {
1234 1223 case ZPROP_SRC_NONE:
1235 1224 sourcestr = "none";
1236 1225 break;
1237 1226 case ZPROP_SRC_RECEIVED:
1238 1227 sourcestr = "received";
1239 1228 break;
1240 1229 case ZPROP_SRC_LOCAL:
1241 1230 sourcestr = mhp->nh_dataset;
1242 1231 break;
1243 1232 case ZPROP_SRC_TEMPORARY:
1244 1233 sourcestr = "temporary";
1245 1234 break;
1246 1235 case ZPROP_SRC_DEFAULT:
1247 1236 sourcestr = "default";
1248 1237 break;
1249 1238 default:
1250 1239 sourcestr = sbuf;
1251 1240 break;
1252 1241 }
1253 1242 (void) strlcpy(mpp->mp_source, sourcestr, ZFS_MAXPROPLEN);
1254 1243
1255 1244 mhp->nh_count++;
1256 1245 return (ZPROP_CONT);
1257 1246 }
1258 1247
1259 1248 /*
1260 1249 * Callback to backup each ZFS user/group quota
1261 1250 */
1262 1251 static int
1263 1252 zfs_put_quota_cb(void *pp, const char *domain, uid_t rid, uint64_t space)
1264 1253 {
1265 1254 ndmp_metadata_handle_t *mhd;
1266 1255 ndmp_metadata_header_ext_t *mhp;
1267 1256 ndmp_metadata_property_ext_t *mpp;
1268 1257 char *typestr;
1269 1258
1270 1259 if (pp == NULL)
1271 1260 return (ZPROP_INVAL);
1272 1261
1273 1262 mhd = (ndmp_metadata_handle_t *)pp;
1274 1263 mhp = mhd->ml_xhdr;
1275 1264 mpp = &mhp->nh_property[mhp->nh_count];
1276 1265
1277 1266 if (mhp->nh_count * sizeof (ndmp_metadata_property_ext_t) +
1278 1267 sizeof (ndmp_metadata_header_ext_t) > mhp->nh_total_bytes)
1279 1268 return (ZPROP_INVAL);
1280 1269
1281 1270 if (mhd->ml_quota_prop == ZFS_PROP_USERQUOTA)
1282 1271 typestr = "userquota";
1283 1272 else
1284 1273 typestr = "groupquota";
1285 1274
1286 1275 if (domain == NULL || *domain == '\0') {
1287 1276 (void) snprintf(mpp->mp_name, ZFS_MAX_DATASET_NAME_LEN,
1288 1277 "%s@%llu", typestr, (longlong_t)rid);
1289 1278 } else {
1290 1279 (void) snprintf(mpp->mp_name, ZFS_MAX_DATASET_NAME_LEN,
1291 1280 "%s@%s-%llu", typestr, domain, (longlong_t)rid);
1292 1281 }
1293 1282 (void) snprintf(mpp->mp_value, ZFS_MAXPROPLEN, "%llu", space);
1294 1283 (void) strlcpy(mpp->mp_source, mhp->nh_dataset, ZFS_MAXPROPLEN);
1295 1284
1296 1285 mhp->nh_count++;
1297 1286 return (0);
1298 1287 }
1299 1288
1300 1289 /*
1301 1290 * Callback to count each ZFS property
1302 1291 */
1303 1292 /*ARGSUSED*/
1304 1293 static int
1305 1294 zfs_count_prop_cb(int prop, void *pp)
1306 1295 {
1307 1296 (*(int *)pp)++;
1308 1297 return (ZPROP_CONT);
1309 1298 }
1310 1299
1311 1300 /*
1312 1301 * Callback to count each ZFS user/group quota
1313 1302 */
1314 1303 /*ARGSUSED*/
1315 1304 static int
1316 1305 zfs_count_quota_cb(void *pp, const char *domain, uid_t rid, uint64_t space)
1317 1306 {
1318 1307 (*(int *)pp)++;
1319 1308 return (0);
1320 1309 }
1321 1310
1322 1311 /*
1323 1312 * Count the number of ZFS properties and user/group quotas
1324 1313 */
1325 1314 int
1326 1315 zfs_get_prop_counts(zfs_handle_t *zhp)
1327 1316 {
1328 1317 int count = 0;
1329 1318 nvlist_t *uprops;
1330 1319 nvpair_t *elp;
1331 1320
1332 1321 if (zhp == NULL)
1333 1322 return (0);
1334 1323
1335 1324 (void) zprop_iter(zfs_count_prop_cb, &count, TRUE, TRUE,
1336 1325 ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET);
1337 1326
1338 1327 (void) zfs_userspace(zhp, ZFS_PROP_USERQUOTA, zfs_count_quota_cb,
1339 1328 &count);
1340 1329 (void) zfs_userspace(zhp, ZFS_PROP_GROUPQUOTA, zfs_count_quota_cb,
1341 1330 &count);
1342 1331
1343 1332 uprops = zfs_get_user_props(zhp);
1344 1333
1345 1334 elp = nvlist_next_nvpair(uprops, NULL);
1346 1335 for (; elp != NULL; elp = nvlist_next_nvpair(uprops, elp))
1347 1336 count++;
1348 1337
1349 1338 return (count);
1350 1339 }
1351 1340
1352 1341 /*
1353 1342 * Notifies ndmpd that the metadata associated with the given ZFS dataset
1354 1343 * should be backed up.
1355 1344 */
1356 1345 int
1357 1346 ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset)
1358 1347 {
1359 1348 tlm_commands_t *cmds;
1360 1349 ndmp_metadata_handle_t mhd;
1361 1350 ndmp_metadata_header_ext_t *mhp;
1362 1351 ndmp_metadata_property_ext_t *mpp;
1363 1352 zfs_handle_t *zhp;
1364 1353 tlm_cmd_t *lcmd;
1365 1354 long actual_size;
1366 1355 nvlist_t *uprops, *ulist;
1367 1356 const char *pname;
1368 1357 nvpair_t *elp;
1369 1358 char *sval, *ssrc;
1370 1359 char *wbuf, *pp, *tp;
1371 1360 long size, lsize, sz;
1372 1361 int align = RECORDSIZE - 1;
1373 1362 int pcount;
1374 1363
1375 1364 if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
1376 1365 return (-1);
1377 1366
1378 1367 if ((lcmd = cmds->tcs_command) == NULL ||
1379 1368 lcmd->tc_buffers == NULL)
1380 1369 return (-1);
1381 1370
1382 1371 (void) mutex_lock(&zlib_mtx);
1383 1372 if ((zhp = zfs_open(zlibh, dataset, ZFS_TYPE_DATASET)) == NULL) {
1384 1373 (void) mutex_unlock(&zlib_mtx);
1385 1374 return (-1);
1386 1375 }
1387 1376
1388 1377 pcount = zfs_get_prop_counts(zhp);
1389 1378 size = sizeof (ndmp_metadata_header_ext_t) +
1390 1379 pcount * sizeof (ndmp_metadata_property_ext_t);
1391 1380
1392 1381 size += align;
1393 1382 size &= ~align;
1394 1383
1395 1384 if ((mhp = malloc(size)) == NULL) {
1396 1385 zfs_close(zhp);
1397 1386 (void) mutex_unlock(&zlib_mtx);
1398 1387 return (-1);
1399 1388 }
1400 1389
1401 1390 (void) memset(mhp, 0, size);
1402 1391
1403 1392 mhd.ml_handle = zhp;
1404 1393 mhd.ml_xhdr = mhp;
1405 1394 mhp->nh_total_bytes = size;
1406 1395 mhp->nh_major = META_HDR_MAJOR_VERSION;
1407 1396 mhp->nh_minor = META_HDR_MINOR_VERSION;
1408 1397 mhp->nh_plversion = nctx->nc_plversion;
1409 1398
1410 1399 (void) strlcpy(mhp->nh_plname, nctx->nc_plname,
1411 1400 sizeof (mhp->nh_plname));
1412 1401 (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC_EXT,
1413 1402 sizeof (mhp->nh_magic));
1414 1403 (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset));
1415 1404
1416 1405 /* Get all the ZFS properties */
1417 1406 (void) zprop_iter(zfs_put_prop_cb, &mhd, TRUE, TRUE,
1418 1407 ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET);
1419 1408
1420 1409 /* Get user properties */
1421 1410 uprops = zfs_get_user_props(mhd.ml_handle);
1422 1411
1423 1412 elp = nvlist_next_nvpair(uprops, NULL);
1424 1413
1425 1414 while (elp != NULL) {
1426 1415 mpp = &mhp->nh_property[mhp->nh_count];
1427 1416 if (nvpair_value_nvlist(elp, &ulist) != 0 ||
1428 1417 nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 ||
1429 1418 nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) {
1430 1419 zfs_close(mhd.ml_handle);
1431 1420 (void) mutex_unlock(&zlib_mtx);
1432 1421 free(mhp);
1433 1422 return (-1);
1434 1423 }
1435 1424 if ((pname = nvpair_name(elp)) != NULL) {
1436 1425 (void) strlcpy(mpp->mp_name, pname,
1437 1426 ZFS_MAX_DATASET_NAME_LEN);
1438 1427 }
1439 1428
1440 1429 (void) strlcpy(mpp->mp_value, sval, ZFS_MAXPROPLEN);
1441 1430 (void) strlcpy(mpp->mp_source, ssrc, ZFS_MAXPROPLEN);
1442 1431 mhp->nh_count++;
1443 1432 elp = nvlist_next_nvpair(uprops, elp);
1444 1433 }
1445 1434
1446 1435 mhd.ml_quota_prop = ZFS_PROP_USERQUOTA;
1447 1436 (void) zfs_userspace(mhd.ml_handle, ZFS_PROP_USERQUOTA,
1448 1437 zfs_put_quota_cb, &mhd);
1449 1438 mhd.ml_quota_prop = ZFS_PROP_GROUPQUOTA;
1450 1439 (void) zfs_userspace(mhd.ml_handle, ZFS_PROP_GROUPQUOTA,
1451 1440 zfs_put_quota_cb, &mhd);
1452 1441 mhp->nh_count = pcount;
1453 1442
1454 1443 zfs_close(mhd.ml_handle);
1455 1444 (void) mutex_unlock(&zlib_mtx);
1456 1445
1457 1446 if ((wbuf = get_write_buffer(size, &actual_size, TRUE,
1458 1447 lcmd)) != NULL) {
1459 1448 pp = (char *)mhp;
1460 1449
1461 1450 (void) memcpy(wbuf, pp, (actual_size < size) ?
1462 1451 actual_size : size);
1463 1452 pp += (actual_size < size) ? actual_size : size;
1464 1453
1465 1454 sz = actual_size;
1466 1455 while (sz < size &&
1467 1456 ((tp = get_write_buffer(size - sz, &lsize,
1468 1457 TRUE, lcmd))) != NULL) {
1469 1458 (void) memcpy(tp, pp, lsize);
1470 1459 sz += lsize;
1471 1460 pp += lsize;
1472 1461 }
1473 1462 if (sz > size) {
1474 1463 tlm_unget_write_buffer(lcmd->tc_buffers, sz - size);
1475 1464 }
1476 1465 }
1477 1466
1478 1467 free(mhp);
1479 1468 return (0);
1480 1469 }
|
↓ open down ↓ |
391 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX