1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * BSD 3 Clause License
8 *
9 * Copyright (c) 2007, The Storage Networking Industry Association.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <cstack.h>
42 #include <ctype.h>
43 #include <dirent.h>
44 #include <errno.h>
45 #include "ndmpd.h"
46 #include <bitmap.h>
47 #include <traverse.h>
48 #include <limits.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <time.h>
53 #include "tlm_buffers.h"
54
55
56 /*
57 * Parameter passed to traverse for marking inodes
58 * when traversing backup hierarchy in V2. It
59 * includes:
60 * mp_bmd: the bitmap describptor.
61 * mp_ddate: backup date.
62 * mp_session: pointer to the session structure.
63 * mp_nlp: pointer to the nlp.
64 * mp_tacl: pointer to the acl.
65 */
66 typedef struct mark_param {
67 int mp_bmd;
68 time_t mp_ddate;
69 ndmpd_session_t *mp_session;
70 ndmp_lbr_params_t *mp_nlp;
71 tlm_acls_t *mp_tacl;
72 } mark_param_t;
73
74
75 /*
76 * Set this variable to non-zero to print the inodes
77 * marked after traversing file system.
78 */
79 static int ndmpd_print_inodes = 0;
80
81
82 /*
83 * Flag passed to traverse_post.
84 */
85 static int ndmpd_mark_flags = 0;
86
87
88 /*
89 * Verbose traversing prints the file/dir path names
90 * if they are being marked.
91 */
92 static int ndmpd_verbose_traverse = 0;
93
94
95 /*
96 * Set this flag to count the number of inodes marked
97 * after traversing backup hierarchy.
98 */
99 static int ndmpd_mark_count_flag = 0;
100
101
102 /*
103 * Set this variable to non-zero value to force traversing
104 * backup hierarchy for tar format.
105 */
106 static int ndmp_tar_force_traverse = 0;
107
108
109 /*
110 * Set this variable to non-zero value to skip processing
111 * directories both for tar and dump.
112 */
113 static int ndmp_skip_traverse = 0;
114
115
116 /*
117 * count_bits_cb
118 *
119 * Call back for counting the set bits in the dbitmap.
120 *
121 * Parameters:
122 * bmd (input) - bitmap descriptor
123 * bn (input) - the bit number
124 * arg (input) - pointer to the argument
125 *
126 * Returns:
127 * 0: always
128 */
129 static int
count_bits_cb(int bmd,u_longlong_t bn,void * arg)130 count_bits_cb(int bmd, u_longlong_t bn, void *arg)
131 {
132 if (dbm_getone(bmd, bn)) {
133 (*(u_longlong_t *)arg)++;
134 if (ndmpd_print_inodes)
135 NDMP_LOG(LOG_DEBUG, "%llu", bn);
136 }
137
138 return (0);
139 }
140
141
142 /*
143 * count_set_bits
144 *
145 * Count bits set in the bitmap.
146 *
147 * Parameters:
148 * path (input) - the backup path
149 * bmd (input) - bitmap descriptor
150 *
151 * Returns:
152 * void
153 */
154 void
count_set_bits(char * path,int bmd)155 count_set_bits(char *path, int bmd)
156 {
157 u_longlong_t cnt;
158
159 if (!ndmpd_mark_count_flag)
160 return;
161
162 cnt = 0;
163 (void) dbm_apply_ifset(bmd, count_bits_cb, &cnt);
164 NDMP_LOG(LOG_DEBUG, "%s %llu inodes marked", path, cnt);
165 }
166
167
168 /*
169 * traverse
170 *
171 * Starts the post-traverse the backup hierarchy. Checks
172 * for exceptional cases, like aborting operation and if
173 * asked, report detailed information after traversing.
174 *
175 * Parameters:
176 * session (input) - pointer to the session
177 * nlp (input) - pointer to the nlp structure
178 * ftp (input) - pointer to the traverse parameters
179 *
180 * Returns:
181 * 0: on success
182 * != 0: otherwise
183 */
184 int
traverse(ndmpd_session_t * session,ndmp_lbr_params_t * nlp,fs_traverse_t * ftp)185 traverse(ndmpd_session_t *session, ndmp_lbr_params_t *nlp,
186 fs_traverse_t *ftp)
187 {
188 int rv;
189 time_t s, e;
190
191 if (!session || !nlp || !ftp) {
192 NDMP_LOG(LOG_DEBUG, "Invalid argument");
193 return (-1);
194 }
195 NDMP_LOG(LOG_DEBUG, "Processing directories of \"%s\"",
196 nlp->nlp_backup_path);
197
198 (void) time(&s);
199 if (traverse_post(ftp) != 0) {
200 rv = -1;
201 if (!session->ns_data.dd_abort && !NLP_ISSET(nlp,
202 NLPF_ABORTED)) {
203 NDMP_LOG(LOG_DEBUG,
204 "Traversing backup path hierarchy \"%s\"",
205 nlp->nlp_backup_path);
206 }
207 } else {
208 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE);
209 rv = 0;
210 (void) time(&e);
211 NDMP_LOG(LOG_DEBUG,
212 "\"%s\" traversed in %u sec", nlp->nlp_backup_path,
213 (uint_t)(e-s));
214
215 count_set_bits(nlp->nlp_backup_path, nlp->nlp_bkmap);
216 }
217
218 return (rv);
219 }
220
221
222 /*
223 * mark_cb
224 *
225 * The callback function, called by traverse_post to mark bits
226 * in the bitmap.
227 *
228 * Set the bit of the entry if it's been modified (obviously
229 * should be backed up) plus its parent directory.
230 *
231 * If the entry is a directory and is not modified itself,
232 * but it's marked, then there is something below it that
233 * is being backed up. It shows the the path, leads to
234 * an object that will be backed up. So the path should
235 * be marked too.
236 *
237 * The backup path itself is always marked.
238 *
239 * Parameters:
240 * arg (input) - pointer to the mark parameter
241 * pnp (input) - pointer to the path node
242 * enp (input) - pointer to the entry node
243 *
244 * Returns:
245 * 0: as long as traversing should continue
246 * != 0: if traversing should stop
247 */
248 int
mark_cb(void * arg,fst_node_t * pnp,fst_node_t * enp)249 mark_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
250 {
251 int bmd;
252 int rv;
253 u_longlong_t bl;
254 time_t ddate;
255 fs_fhandle_t *pfhp, *efhp;
256 struct stat64 *pstp, *estp;
257 mark_param_t *mpp;
258 ndmp_lbr_params_t *nlp;
259 tlm_acls_t *tacl;
260
261 rv = 0;
262 mpp = (mark_param_t *)arg;
263 tacl = mpp->mp_tacl;
264 nlp = ndmp_get_nlp(mpp->mp_session);
265 if (!mpp) {
266 NDMP_LOG(LOG_DEBUG, "NULL argument passed");
267 rv = -1;
268 } else if (mpp->mp_session->ns_eof) {
269 NDMP_LOG(LOG_INFO, "Connection to the client is closed");
270 rv = -1;
271 } else if (mpp->mp_session->ns_data.dd_abort ||
272 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) {
273 NDMP_LOG(LOG_INFO, "Processing directories aborted.");
274 rv = -1;
275 }
276
277 if (rv != 0)
278 return (rv);
279
280 ddate = mpp->mp_ddate;
281 bmd = mpp->mp_bmd;
282 bl = dbm_getlen(bmd);
283
284 pfhp = pnp->tn_fh;
285 pstp = pnp->tn_st;
286
287 /* sanity check on fh and stat of the path passed */
288 if (pstp->st_ino > bl) {
289 NDMP_LOG(LOG_DEBUG, "Invalid path inode #%u",
290 (uint_t)pstp->st_ino);
291 return (-1);
292 }
293 if (pstp->st_ino != pfhp->fh_fid) {
294 NDMP_LOG(LOG_DEBUG, "Path ino mismatch %u %u",
295 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid);
296 return (-1);
297 }
298
299 /*
300 * Always mark the backup path inode number.
301 */
302 if (!enp->tn_path) {
303 (void) dbm_setone(bmd, pstp->st_ino);
304 return (0);
305 }
306
307 efhp = enp->tn_fh;
308 estp = enp->tn_st;
309
310 /* sanity check on fh and stat of the entry passed */
311 if (estp->st_ino > bl) {
312 NDMP_LOG(LOG_DEBUG, "Invalid entry inode #%u",
313 (uint_t)estp->st_ino);
314 return (-1);
315 }
316 if (estp->st_ino != efhp->fh_fid) {
317 NDMP_LOG(LOG_DEBUG, "Entry ino mismatch %u %u", estp->st_ino,
318 (uint_t)pfhp->fh_fid);
319 return (-1);
320 }
321
322 /* check the dates and mark the bitmap inode */
323 if (ddate == 0) {
324 /* base backup */
325 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
326 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
327 if (ndmpd_verbose_traverse) {
328 NDMP_LOG(LOG_DEBUG, "Base Backup");
329 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"",
330 pnp->tn_path, enp->tn_path);
331 }
332
333 } else if (estp->st_mtime > ddate) {
334 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
335 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
336 if (ndmpd_verbose_traverse) {
337 NDMP_LOG(LOG_DEBUG,
338 "m(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
339 (uint_t)estp->st_ino, (uint_t)estp->st_mtime,
340 (uint_t)ddate);
341 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"",
342 pnp->tn_path, enp->tn_path);
343 }
344 } else if (iscreated(nlp, NULL, tacl, ddate)) {
345 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
346 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
347 if (ndmpd_verbose_traverse) {
348 NDMP_LOG(LOG_DEBUG,
349 "cr(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
350 (uint_t)estp->st_ino, (uint_t)estp->st_mtime,
351 (uint_t)ddate);
352 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"",
353 pnp->tn_path, enp->tn_path);
354 }
355 } else if (estp->st_ctime > ddate) {
356 if (!NLP_IGNCTIME(nlp)) {
357 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
358 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
359 }
360 if (ndmpd_verbose_traverse) {
361 if (NLP_IGNCTIME(nlp)) {
362 NDMP_LOG(LOG_DEBUG,
363 "ign c(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
364 (uint_t)estp->st_ino,
365 (uint_t)estp->st_ctime, (uint_t)ddate);
366 } else {
367 NDMP_LOG(LOG_DEBUG,
368 "c(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
369 (uint_t)estp->st_ino,
370 (uint_t)estp->st_ctime, (uint_t)ddate);
371 }
372 NDMP_LOG(LOG_DEBUG, "\"%s/%s\"",
373 pnp->tn_path, enp->tn_path);
374 }
375 } else if (S_ISDIR(estp->st_mode) &&
376 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) {
377 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
378 if (ndmpd_verbose_traverse) {
379 NDMP_LOG(LOG_DEBUG, "d(%u,%u)",
380 (uint_t)pstp->st_ino, (uint_t)estp->st_ino);
381 NDMP_LOG(LOG_DEBUG, "\"%s, %s\"",
382 pnp->tn_path, enp->tn_path);
383 }
384 }
385
386 return (0);
387 }
388
389
390 /*
391 * mark_inodes_v2
392 *
393 * Traverse the file system in post-order and mark
394 * all the modified objects and also directories leading
395 * to them.
396 *
397 * Parameters:
398 * session (input) - pointer to the session
399 * nlp (input) - pointer to the nlp structure
400 * path (input) - the physical path to traverse
401 *
402 * Returns:
403 * 0: on success.
404 * != 0: on error.
405 */
406 int
mark_inodes_v2(ndmpd_session_t * session,ndmp_lbr_params_t * nlp,char * path)407 mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
408 {
409 fs_traverse_t ft;
410 mark_param_t mp;
411
412 if (!session || !nlp || !path || !*path) {
413 NDMP_LOG(LOG_DEBUG, "Invalid argument");
414 return (-1);
415 }
416
417 NDMP_LOG(LOG_DEBUG, "path \"%s\"", path);
418
419 mp.mp_bmd = nlp->nlp_bkmap;
420 mp.mp_ddate = nlp->nlp_ldate;
421 mp.mp_session = session;
422 mp.mp_nlp = nlp;
423
424 ft.ft_path = path;
425 ft.ft_lpath = nlp->nlp_backup_path;
426 ft.ft_callbk = mark_cb;
427 ft.ft_arg = ∓
428 ft.ft_logfp = (ft_log_t)ndmp_log;
429 ft.ft_flags = ndmpd_mark_flags;
430
431 return (traverse(session, nlp, &ft));
432 }
433
434
435 /*
436 * create_bitmap
437 *
438 * Create a dbitmap and return its descriptor.
439 *
440 * Parameters:
441 * path (input) - path for which the bitmap should be created
442 * value (input) - the initial value for the bitmap
443 *
444 * Returns:
445 * the dbitmap descriptor
446 */
447 static int
create_bitmap(char * path,int value)448 create_bitmap(char *path, int value)
449 {
450 char bm_fname[PATH_MAX];
451 char buf[TLM_MAX_PATH_NAME];
452 char *livepath;
453 ulong_t ninode;
454
455 NDMP_LOG(LOG_DEBUG, "path \"%s\"", path);
456
457 if (fs_is_chkpntvol(path))
458 livepath = (char *)tlm_remove_checkpoint(path, buf);
459 else
460 livepath = path;
461 ninode = 1024 * 1024 * 1024;
462 if (ninode == 0)
463 return (-1);
464 (void) ndmpd_mk_temp(bm_fname);
465
466 NDMP_LOG(LOG_DEBUG, "path \"%s\"ninode %u bm_fname \"%s\"",
467 livepath, ninode, bm_fname);
468
469 return (dbm_alloc(bm_fname, (u_longlong_t)ninode, value));
470 }
471
472
473 /*
474 * create_allset_bitmap
475 *
476 * A helper function to create a bitmap with all the
477 * values set to 1.
478 *
479 * Parameters:
480 * nlp (input) - pointer to the nlp structure
481 *
482 * Returns:
483 * the dbitmap descriptor
484 */
485 static int
create_allset_bitmap(ndmp_lbr_params_t * nlp)486 create_allset_bitmap(ndmp_lbr_params_t *nlp)
487 {
488 int rv;
489
490 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 1);
491 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);
492
493 if (nlp->nlp_bkmap < 0) {
494 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap.");
495 rv = -1;
496 } else
497 rv = 0;
498
499 return (rv);
500 }
501
502
503 /*
504 * mark_common_v2
505 *
506 * Create the inode bitmap. If last date of the the
507 * backup is epoch, then all the objects should be backed
508 * up; there is no need to traverse the backup hierarchy
509 * and mark the inodes. All the bits should be marked.
510 *
511 * Otherwise, the backup hierarchy should be traversed and
512 * the objects should be marked.
513 *
514 * Parameters:
515 * session (input) - pointer to the session
516 * nlp (input) - pointer to the nlp structure
517 *
518 * Returns:
519 * 0: on success.
520 * != 0: on error.
521 */
522 static int
mark_common_v2(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)523 mark_common_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
524 {
525 char buf[TLM_MAX_PATH_NAME], *chkpath;
526 int rv;
527
528 /*
529 * Everything is needed for full backup.
530 */
531 if (nlp->nlp_ldate == (time_t)0)
532 return (create_allset_bitmap(nlp));
533
534 rv = 0;
535 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0);
536 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);
537
538 if (nlp->nlp_bkmap < 0) {
539 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap.");
540 rv = -1;
541 } else {
542 if (fs_is_chkpntvol(nlp->nlp_backup_path))
543 chkpath = nlp->nlp_backup_path;
544 else
545 chkpath = tlm_build_snapshot_name(
546 nlp->nlp_backup_path, buf,
547 nlp->nlp_jstat->js_job_name);
548 rv = mark_inodes_v2(session, nlp, chkpath);
549 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE);
550 }
551
552 return (rv);
553 }
554
555
556 /*
557 * mark_tar_inodes_v2
558 *
559 * Create the bitmap for tar backup format.
560 *
561 * Parameters:
562 * session (input) - pointer to the session
563 * nlp (input) - pointer to the nlp structure
564 *
565 * Returns:
566 * 0: on success.
567 * != 0: on error.
568 */
569 static int
mark_tar_inodes_v2(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)570 mark_tar_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
571 {
572 int rv;
573
574 if (ndmp_tar_force_traverse)
575 rv = mark_common_v2(session, nlp);
576 else
577 rv = create_allset_bitmap(nlp);
578
579 return (rv);
580 }
581
582
583 /*
584 * mark_dump_inodes_v2
585 *
586 * Create the bitmap for dump backup format.
587 *
588 * Parameters:
589 * session (input) - pointer to the session
590 * nlp (input) - pointer to the nlp structure
591 *
592 * Returns:
593 * 0: on success.
594 * != 0: on error.
595 */
596 static int
mark_dump_inodes_v2(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)597 mark_dump_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
598 {
599 return (mark_common_v2(session, nlp));
600 }
601
602
603 /*
604 * ndmpd_mark_inodes_v2
605 *
606 * Mark the inodes of the backup hierarchy if necessary.
607 *
608 * Parameters:
609 * session (input) - pointer to the session
610 * nlp (input) - pointer to the nlp structure
611 *
612 * Returns:
613 * 0: on success.
614 * != 0: on error.
615 */
616 int
ndmpd_mark_inodes_v2(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)617 ndmpd_mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
618 {
619 int rv;
620
621 if (ndmp_skip_traverse) {
622 NDMP_LOG(LOG_INFO, "Skip processing directories \"%s\"",
623 nlp->nlp_backup_path);
624 rv = create_allset_bitmap(nlp);
625 } else {
626 if (NLP_ISTAR(nlp))
627 rv = mark_tar_inodes_v2(session, nlp);
628 else if (NLP_ISDUMP(nlp))
629 rv = mark_dump_inodes_v2(session, nlp);
630 else {
631 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"",
632 nlp->nlp_backup_path);
633 rv = -1;
634 }
635 }
636
637 return (rv);
638 }
639
640
641 /*
642 * ndmpd_abort_making_v2
643 *
644 * Abort the process of marking inodes.
645 *
646 * Parameters:
647 * session (input) - pointer to the session
648 *
649 * Returns:
650 * void
651 */
652 void
ndmpd_abort_marking_v2(ndmpd_session_t * session)653 ndmpd_abort_marking_v2(ndmpd_session_t *session)
654 {
655 ndmp_lbr_params_t *nlp;
656
657 nlp = ndmp_get_nlp(session);
658 if (nlp)
659 NLP_SET(nlp, NLPF_ABORTED);
660 }
661
662
663 /*
664 * mark_tokv3
665 *
666 * Traverse the backup hierarchy and mark the bits for the
667 * modified objects of directories leading to a modified
668 * object for the token-based backup.
669 *
670 * Parameters:
671 * session (input) - pointer to the session
672 * nlp (input) - pointer to the nlp structure
673 * path (input) - the physical path to traverse
674 *
675 * Returns:
676 * 0: on success
677 * != 0: otherwise
678 */
679 int
mark_tokv3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp,char * path)680 mark_tokv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
681 {
682 fs_traverse_t ft;
683 mark_param_t mp;
684
685 if (!session || !nlp || !path || !*path) {
686 NDMP_LOG(LOG_DEBUG, "Invalid argument");
687 return (-1);
688 }
689 if (nlp->nlp_tokdate == (time_t)0)
690 return (create_allset_bitmap(nlp));
691
692 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0);
693 if (nlp->nlp_bkmap < 0) {
694 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap.");
695 return (-1);
696 }
697 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);
698
699 mp.mp_bmd = nlp->nlp_bkmap;
700 mp.mp_ddate = nlp->nlp_tokdate;
701 mp.mp_session = session;
702 mp.mp_nlp = nlp;
703
704 ft.ft_path = path;
705 ft.ft_lpath = nlp->nlp_backup_path;
706 ft.ft_callbk = mark_cb;
707 ft.ft_arg = ∓
708 ft.ft_logfp = (ft_log_t)ndmp_log;
709 ft.ft_flags = ndmpd_mark_flags;
710
711 return (traverse(session, nlp, &ft));
712 }
713
714
715 /*
716 * marklbrv3_cb
717 *
718 * The callback function, called by traverse_post to mark
719 * bits in the bitmap.
720 *
721 * It's so much like mark_cb for time-based (token-based
722 * and level-type) backup types, except that it looks at
723 * the archive bit of the objects instead of their timestamp.
724 *
725 * Parameters:
726 * arg (input) - pointer to the mark parameter
727 * pnp (input) - pointer to the path node
728 * enp (input) - pointer to the entry node
729 *
730 * Returns:
731 * 0: as long as traversing should continue
732 * != 0: if traversing should stop
733 */
734 int
marklbrv3_cb(void * arg,fst_node_t * pnp,fst_node_t * enp)735 marklbrv3_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
736 {
737 int bmd;
738 u_longlong_t bl;
739 fs_fhandle_t *pfhp, *efhp;
740 struct stat64 *pstp, *estp;
741 mark_param_t *mpp;
742 ndmp_lbr_params_t *nlp;
743
744 mpp = (mark_param_t *)arg;
745 if (!mpp) {
746 NDMP_LOG(LOG_DEBUG, "NULL argument passed");
747 return (-1);
748 }
749 nlp = ndmp_get_nlp(mpp->mp_session);
750 if (mpp->mp_session->ns_data.dd_abort ||
751 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) {
752 NDMP_LOG(LOG_INFO, "Processing directories aborted.");
753 return (-1);
754 }
755
756 bmd = mpp->mp_bmd;
757 bl = dbm_getlen(bmd);
758
759 pfhp = pnp->tn_fh;
760 pstp = pnp->tn_st;
761
762 /* sanity check on fh and stat of the path passed */
763 if (pstp->st_ino > bl) {
764 NDMP_LOG(LOG_DEBUG, "Invalid path inode #%u",
765 (uint_t)pstp->st_ino);
766 return (-1);
767 }
768 if (pstp->st_ino != pfhp->fh_fid) {
769 NDMP_LOG(LOG_DEBUG, "Path ino mismatch %u %u",
770 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid);
771 return (-1);
772 }
773
774 /*
775 * Always mark the backup path inode number.
776 */
777 if (!enp->tn_path) {
778 (void) dbm_setone(bmd, pstp->st_ino);
779 if (ndmpd_verbose_traverse) {
780 NDMP_LOG(LOG_DEBUG, "d(%u)", (uint_t)pstp->st_ino);
781 NDMP_LOG(LOG_DEBUG, "\"%s\"", pnp->tn_path);
782 }
783 return (0);
784 }
785
786 efhp = enp->tn_fh;
787 estp = enp->tn_st;
788
789 /* sanity check on fh and stat of the entry passed */
790 if (estp->st_ino > bl) {
791 NDMP_LOG(LOG_DEBUG, "Invalid entry inode #%u",
792 (uint_t)estp->st_ino);
793 return (-1);
794 }
795 if (estp->st_ino != efhp->fh_fid) {
796 NDMP_LOG(LOG_DEBUG, "Entry ino mismatch %u %u", estp->st_ino,
797 (uint_t)pfhp->fh_fid);
798 return (-1);
799 }
800
801 if (S_ISDIR(estp->st_mode) &&
802 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) {
803 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
804 if (ndmpd_verbose_traverse) {
805 NDMP_LOG(LOG_DEBUG, "d(%u,%u)",
806 (uint_t)pstp->st_ino, (uint_t)estp->st_ino);
807 NDMP_LOG(LOG_DEBUG, "\"%s, %s\"",
808 pnp->tn_path, enp->tn_path);
809 }
810 }
811
812 return (0);
813 }
814
815
816 /*
817 * mark_lbrv3
818 *
819 * Traverse the backup hierarchy and mark the bits for the
820 * modified objects of directories leading to a modified
821 * object for the LBR-type backup.
822 *
823 * Parameters:
824 * session (input) - pointer to the session
825 * nlp (input) - pointer to the nlp structure
826 * path (input) - the physical path to traverse
827 *
828 * Returns:
829 * 0: on success
830 * != 0: otherwise
831 */
832 int
mark_lbrv3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp,char * path)833 mark_lbrv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
834 {
835 char c;
836 fs_traverse_t ft;
837 mark_param_t mp;
838
839 if (!session || !nlp || !path || !*path) {
840 NDMP_LOG(LOG_DEBUG, "Invalid argument");
841 return (-1);
842 }
843 /* full and archive backups backup everything */
844 c = toupper(nlp->nlp_clevel);
845 if (c == 'F' || c == 'A')
846 return (create_allset_bitmap(nlp));
847
848 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0);
849 if (nlp->nlp_bkmap < 0) {
850 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap.");
851 return (-1);
852 }
853 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);
854
855 mp.mp_bmd = nlp->nlp_bkmap;
856 mp.mp_ddate = 0;
857 mp.mp_session = session;
858 mp.mp_nlp = nlp;
859
860 ft.ft_path = path;
861 ft.ft_lpath = nlp->nlp_backup_path;
862 ft.ft_callbk = marklbrv3_cb;
863 ft.ft_arg = ∓
864 ft.ft_logfp = (ft_log_t)ndmp_log;
865 ft.ft_flags = ndmpd_mark_flags;
866
867 return (traverse(session, nlp, &ft));
868 }
869
870
871 /*
872 * mark_levelv3
873 *
874 * Traverse the backup hierarchy and mark the bits for the
875 * modified objects of directories leading to a modified
876 * object for the level-type backup.
877 *
878 * Parameters:
879 * session (input) - pointer to the session
880 * nlp (input) - pointer to the nlp structure
881 * path (input) - the physical path to traverse
882 *
883 * Returns:
884 * 0: on success
885 * != 0: otherwise
886 */
887 int
mark_levelv3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp,char * path)888 mark_levelv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
889 {
890 fs_traverse_t ft;
891 mark_param_t mp;
892 tlm_acls_t traverse_acl;
893
894 if (!session || !nlp || !path || !*path) {
895 NDMP_LOG(LOG_DEBUG, "Invalid argument");
896 return (-1);
897 }
898 if (nlp->nlp_ldate == (time_t)0)
899 return (create_allset_bitmap(nlp));
900
901 nlp->nlp_bkmap = create_bitmap(nlp->nlp_backup_path, 0);
902 if (nlp->nlp_bkmap < 0) {
903 NDMP_LOG(LOG_DEBUG, "Failed to allocate bitmap.");
904 return (-1);
905 }
906 NDMP_LOG(LOG_DEBUG, "nlp_bkmap %d", nlp->nlp_bkmap);
907
908 /*
909 * We do not want to allocate memory for acl every time we
910 * process a file.
911 */
912 (void) memset(&traverse_acl, 0, sizeof (traverse_acl));
913 mp.mp_tacl = &traverse_acl;
914
915 mp.mp_bmd = nlp->nlp_bkmap;
916 mp.mp_ddate = nlp->nlp_ldate;
917 mp.mp_session = session;
918 mp.mp_nlp = nlp;
919
920 ft.ft_path = path;
921 ft.ft_lpath = nlp->nlp_backup_path;
922 ft.ft_callbk = mark_cb;
923 ft.ft_arg = ∓
924 ft.ft_logfp = (ft_log_t)ndmp_log;
925 ft.ft_flags = ndmpd_mark_flags;
926
927 return (traverse(session, nlp, &ft));
928 }
929
930
931 /*
932 * mark_commonv3
933 *
934 * Create the inode bitmap. If last date of the the
935 * backup is epoch, then all the objects should be backed
936 * up; there is no need to traverse the backup hierarchy
937 * and mark the inodes. All the bits should be marked.
938 *
939 * Otherwise, the backup hierarchy should be traversed and
940 * the objects should be marked.
941 *
942 * Parameters:
943 * session (input) - pointer to the session
944 * nlp (input) - pointer to the nlp structure
945 *
946 * Returns:
947 * 0: on success.
948 * != 0: on error.
949 */
950 int
mark_commonv3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)951 mark_commonv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
952 {
953 char buf[TLM_MAX_PATH_NAME], *chkpath;
954 int rv;
955
956 if (NLP_ISCHKPNTED(nlp))
957 chkpath = nlp->nlp_backup_path;
958 else
959 chkpath = tlm_build_snapshot_name(nlp->nlp_backup_path, buf,
960 nlp->nlp_jstat->js_job_name);
961
962 if (NLP_ISSET(nlp, NLPF_TOKENBK))
963 rv = mark_tokv3(session, nlp, chkpath);
964 else if (NLP_ISSET(nlp, NLPF_LBRBK))
965 rv = mark_lbrv3(session, nlp, chkpath);
966 else if (NLP_ISSET(nlp, NLPF_LEVELBK)) {
967 rv = mark_levelv3(session, nlp, chkpath);
968 } else {
969 rv = -1;
970 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"",
971 nlp->nlp_backup_path);
972 }
973
974 return (rv);
975 }
976
977
978 /*
979 * mark_tar_inodesv3
980 *
981 * Mark bits for tar backup format of V3. Normally, the
982 * backup hierarchy is not traversed for tar format
983 * unless it's forced by setting the ndmp_tar_force_traverse
984 * to a non-zero value.
985 *
986 * Parameters:
987 * session (input) - pointer to the session
988 * nlp (input) - pointer to the nlp structure
989 *
990 * Returns:
991 * 0: on success
992 * != 0: otherwise
993 */
994 int
mark_tar_inodesv3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)995 mark_tar_inodesv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
996 {
997 int rv;
998
999 if (ndmp_tar_force_traverse)
1000 rv = mark_commonv3(session, nlp);
1001 else
1002 rv = create_allset_bitmap(nlp);
1003
1004 return (rv);
1005 }
1006
1007
1008 /*
1009 * ndmpd_mark_inodes_v3
1010 *
1011 * Mark the inodes of the backup hierarchy if necessary.
1012 *
1013 * Parameters:
1014 * session (input) - pointer to the session
1015 * nlp (input) - pointer to the nlp structure
1016 *
1017 * Returns:
1018 * 0: on success.
1019 * != 0: on error.
1020 */
1021 int
ndmpd_mark_inodes_v3(ndmpd_session_t * session,ndmp_lbr_params_t * nlp)1022 ndmpd_mark_inodes_v3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
1023 {
1024 int rv;
1025
1026 if (ndmp_skip_traverse) {
1027 NDMP_LOG(LOG_INFO, "Skip processing directories \"%s\"",
1028 nlp->nlp_backup_path);
1029 rv = create_allset_bitmap(nlp);
1030 } else {
1031 if (NLP_ISTAR(nlp))
1032 rv = mark_tar_inodesv3(session, nlp);
1033 else if (NLP_ISDUMP(nlp)) {
1034 rv = mark_commonv3(session, nlp);
1035 } else {
1036 NDMP_LOG(LOG_DEBUG, "Unknown backup type for \"%s\"",
1037 nlp->nlp_backup_path);
1038 rv = -1;
1039 }
1040 }
1041
1042 return (rv);
1043 }
1044