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.
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
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
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
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,
246 * != 0: if traversing should stop
247 */
248 int
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
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
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
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
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.
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
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 */
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
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
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
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
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
950 int
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:
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
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 }
|
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 /* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
40
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #include <syslog.h>
44 #include <cstack.h>
45 #include <ctype.h>
46 #include <dirent.h>
47 #include <errno.h>
48 #include "ndmpd.h"
49 #include <bitmap.h>
50 #include <traverse.h>
51 #include <limits.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <time.h>
56 #include "tlm_buffers.h"
57
58
59 /*
60 * Parameter passed to traverse for marking inodes
61 * when traversing backup hierarchy in V2. It
62 * includes:
63 * mp_bmd: the bitmap describptor.
118
119 /*
120 * count_bits_cb
121 *
122 * Call back for counting the set bits in the dbitmap.
123 *
124 * Parameters:
125 * bmd (input) - bitmap descriptor
126 * bn (input) - the bit number
127 * arg (input) - pointer to the argument
128 *
129 * Returns:
130 * 0: always
131 */
132 static int
133 count_bits_cb(int bmd, u_longlong_t bn, void *arg)
134 {
135 if (dbm_getone(bmd, bn)) {
136 (*(u_longlong_t *)arg)++;
137 if (ndmpd_print_inodes)
138 syslog(LOG_DEBUG, "%lu", bn);
139 }
140
141 return (0);
142 }
143
144
145 /*
146 * count_set_bits
147 *
148 * Count bits set in the bitmap.
149 *
150 * Parameters:
151 * path (input) - the backup path
152 * bmd (input) - bitmap descriptor
153 *
154 * Returns:
155 * void
156 */
157 void
158 count_set_bits(char *path, int bmd)
159 {
160 u_longlong_t cnt;
161
162 if (!ndmpd_mark_count_flag)
163 return;
164
165 cnt = 0;
166 (void) dbm_apply_ifset(bmd, count_bits_cb, &cnt);
167 syslog(LOG_DEBUG, "%s %lu inodes marked", path, cnt);
168 }
169
170
171 /*
172 * traverse
173 *
174 * Starts the post-traverse the backup hierarchy. Checks
175 * for exceptional cases, like aborting operation and if
176 * asked, report detailed information after traversing.
177 *
178 * Parameters:
179 * session (input) - pointer to the session
180 * nlp (input) - pointer to the nlp structure
181 * ftp (input) - pointer to the traverse parameters
182 *
183 * Returns:
184 * 0: on success
185 * != 0: otherwise
186 */
187 int
188 traverse(ndmpd_session_t *session, ndmp_lbr_params_t *nlp,
189 fs_traverse_t *ftp)
190 {
191 int rv;
192 time_t s, e;
193
194 if (!session || !nlp || !ftp) {
195 syslog(LOG_ERR, "Invalid argument in traverse");
196 return (-1);
197 }
198 syslog(LOG_DEBUG, "Processing directories of \"%s\"",
199 nlp->nlp_backup_path);
200
201 (void) time(&s);
202 if (traverse_post(ftp) != 0) {
203 rv = -1;
204 if (!session->ns_data.dd_abort && !NLP_ISSET(nlp,
205 NLPF_ABORTED)) {
206 syslog(LOG_DEBUG,
207 "Traversing backup path hierarchy \"%s\"",
208 nlp->nlp_backup_path);
209 }
210 } else {
211 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE);
212 rv = 0;
213 (void) time(&e);
214 syslog(LOG_DEBUG,
215 "\"%s\" traversed in %u sec", nlp->nlp_backup_path,
216 (uint_t)(e-s));
217
218 count_set_bits(nlp->nlp_backup_path, nlp->nlp_bkmap);
219 }
220
221 return (rv);
222 }
223
224
225 /*
226 * mark_cb
227 *
228 * The callback function, called by traverse_post to mark bits
229 * in the bitmap.
230 *
231 * Set the bit of the entry if it's been modified (obviously
232 * should be backed up) plus its parent directory.
233 *
234 * If the entry is a directory and is not modified itself,
249 * != 0: if traversing should stop
250 */
251 int
252 mark_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
253 {
254 int bmd;
255 int rv;
256 u_longlong_t bl;
257 time_t ddate;
258 fs_fhandle_t *pfhp, *efhp;
259 struct stat64 *pstp, *estp;
260 mark_param_t *mpp;
261 ndmp_lbr_params_t *nlp;
262 tlm_acls_t *tacl;
263
264 rv = 0;
265 mpp = (mark_param_t *)arg;
266 tacl = mpp->mp_tacl;
267 nlp = ndmp_get_nlp(mpp->mp_session);
268 if (!mpp) {
269 syslog(LOG_ERR, "NULL argument passed");
270 rv = -1;
271 } else if (mpp->mp_session->ns_eof) {
272 syslog(LOG_ERR, "Connection to the client is closed");
273 rv = -1;
274 } else if (mpp->mp_session->ns_data.dd_abort ||
275 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) {
276 syslog(LOG_ERR, "Processing directories aborted.");
277 rv = -1;
278 }
279
280 if (rv != 0)
281 return (rv);
282
283 ddate = mpp->mp_ddate;
284 bmd = mpp->mp_bmd;
285 bl = dbm_getlen(bmd);
286
287 pfhp = pnp->tn_fh;
288 pstp = pnp->tn_st;
289
290 /* sanity check on fh and stat of the path passed */
291 if (pstp->st_ino > bl) {
292 syslog(LOG_ERR, "Invalid path inode #%u",
293 (uint_t)pstp->st_ino);
294 return (-1);
295 }
296 if (pstp->st_ino != pfhp->fh_fid) {
297 syslog(LOG_ERR, "Path ino mismatch %u %u",
298 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid);
299 return (-1);
300 }
301
302 /*
303 * Always mark the backup path inode number.
304 */
305 if (!enp->tn_path) {
306 (void) dbm_setone(bmd, pstp->st_ino);
307 return (0);
308 }
309
310 efhp = enp->tn_fh;
311 estp = enp->tn_st;
312
313 /* sanity check on fh and stat of the entry passed */
314 if (estp->st_ino > bl) {
315 syslog(LOG_ERR, "Invalid entry inode #%u",
316 (uint_t)estp->st_ino);
317 return (-1);
318 }
319 if (estp->st_ino != efhp->fh_fid) {
320 syslog(LOG_ERR, "Entry ino mismatch %u %u", estp->st_ino,
321 (uint_t)pfhp->fh_fid);
322 return (-1);
323 }
324
325 /* check the dates and mark the bitmap inode */
326 if (ddate == 0) {
327 /* base backup */
328 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
329 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
330
331 } else if (estp->st_mtime > ddate) {
332 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
333 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
334 if (ndmpd_verbose_traverse) {
335 syslog(LOG_DEBUG,
336 "m(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
337 (uint_t)estp->st_ino, (uint_t)estp->st_mtime,
338 (uint_t)ddate);
339 syslog(LOG_DEBUG, "\"%s/%s\"",
340 pnp->tn_path, enp->tn_path);
341 }
342 } else if (iscreated(nlp, NULL, tacl, ddate)) {
343 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
344 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
345 if (ndmpd_verbose_traverse) {
346 syslog(LOG_DEBUG,
347 "cr(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
348 (uint_t)estp->st_ino, (uint_t)estp->st_mtime,
349 (uint_t)ddate);
350 syslog(LOG_DEBUG, "\"%s/%s\"",
351 pnp->tn_path, enp->tn_path);
352 }
353 } else if (estp->st_ctime > ddate) {
354 if (!NLP_IGNCTIME(nlp)) {
355 (void) dbm_setone(bmd, (u_longlong_t)estp->st_ino);
356 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
357 }
358 if (ndmpd_verbose_traverse) {
359 if (NLP_IGNCTIME(nlp)) {
360 syslog(LOG_DEBUG,
361 "ign c(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
362 (uint_t)estp->st_ino,
363 (uint_t)estp->st_ctime, (uint_t)ddate);
364 } else {
365 syslog(LOG_DEBUG,
366 "c(%u,%u,%u,%u)", (uint_t)pstp->st_ino,
367 (uint_t)estp->st_ino,
368 (uint_t)estp->st_ctime, (uint_t)ddate);
369 }
370 syslog(LOG_DEBUG, "\"%s/%s\"",
371 pnp->tn_path, enp->tn_path);
372 }
373 } else if (S_ISDIR(estp->st_mode) &&
374 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) {
375 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
376 }
377
378 return (0);
379 }
380
381
382 /*
383 * mark_inodes_v2
384 *
385 * Traverse the file system in post-order and mark
386 * all the modified objects and also directories leading
387 * to them.
388 *
389 * Parameters:
390 * session (input) - pointer to the session
391 * nlp (input) - pointer to the nlp structure
392 * path (input) - the physical path to traverse
393 *
394 * Returns:
395 * 0: on success.
396 * != 0: on error.
397 */
398 int
399 mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
400 {
401 fs_traverse_t ft;
402 mark_param_t mp;
403
404 if (!session || !nlp || !path || !*path) {
405 syslog(LOG_ERR, "Invalid argument in mark_inodes_v2");
406 return (-1);
407 }
408
409 syslog(LOG_DEBUG, "path \"%s\"", path);
410
411 mp.mp_bmd = nlp->nlp_bkmap;
412 mp.mp_ddate = nlp->nlp_ldate;
413 mp.mp_session = session;
414 mp.mp_nlp = nlp;
415
416 ft.ft_path = path;
417 ft.ft_lpath = nlp->nlp_backup_path;
418 ft.ft_callbk = mark_cb;
419 ft.ft_arg = ∓
420 ft.ft_logfp = (ft_log_t)syslog;
421 ft.ft_flags = ndmpd_mark_flags;
422
423 return (traverse(session, nlp, &ft));
424 }
425
426
427 /*
428 * create_bitmap
429 *
430 * Create a dbitmap and return its descriptor.
431 *
432 * Parameters:
433 * nlp (input) - pointer to the nlp structure
434 * value (input) - the initial value for the bitmap
435 *
436 * Returns:
437 * the dbitmap descriptor
438 */
439 static int
440 create_bitmap(ndmp_lbr_params_t *nlp, int value)
441 {
442 char bm_fname[PATH_MAX];
443 char *livepath;
444 ulong_t ninode;
445
446 livepath = NLP_ISCHKPNTED(nlp) ?
447 nlp->nlp_mountpoint : nlp->nlp_backup_path;
448
449 ninode = 1024 * 1024 * 1024;
450 if (ninode == 0)
451 return (-1);
452 (void) ndmpd_mk_temp(nlp->nlp_job_name, bm_fname);
453
454 syslog(LOG_DEBUG, "path \"%s\" ninode %u bm_fname \"%s\"",
455 livepath, ninode, bm_fname);
456
457 return (dbm_alloc(bm_fname, (u_longlong_t)ninode, value));
458 }
459
460
461 /*
462 * create_allset_bitmap
463 *
464 * A helper function to create a bitmap with all the
465 * values set to 1.
466 *
467 * Parameters:
468 * nlp (input) - pointer to the nlp structure
469 *
470 * Returns:
471 * the dbitmap descriptor
472 */
473 static int
474 create_allset_bitmap(ndmp_lbr_params_t *nlp)
475 {
476 int rv;
477
478 nlp->nlp_bkmap = create_bitmap(nlp, 1);
479
480 if (nlp->nlp_bkmap < 0) {
481 syslog(LOG_ERR,
482 "Failed to allocate bitmap in create_allset_bitmap");
483 rv = -1;
484 } else
485 rv = 0;
486
487 return (rv);
488 }
489
490
491 /*
492 * mark_common_v2
493 *
494 * Create the inode bitmap. If last date of the the
495 * backup is epoch, then all the objects should be backed
496 * up; there is no need to traverse the backup hierarchy
497 * and mark the inodes. All the bits should be marked.
498 *
499 * Otherwise, the backup hierarchy should be traversed and
500 * the objects should be marked.
501 *
502 * Parameters:
503 * session (input) - pointer to the session
504 * nlp (input) - pointer to the nlp structure
505 *
506 * Returns:
507 * 0: on success.
508 * != 0: on error.
509 */
510 static int
511 mark_common_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
512 {
513 char buf[TLM_MAX_PATH_NAME], *chkpath;
514 int rv;
515
516 /*
517 * Everything is needed for full backup.
518 */
519 if (nlp->nlp_ldate == (time_t)0)
520 return (create_allset_bitmap(nlp));
521
522 rv = 0;
523 nlp->nlp_bkmap = create_bitmap(nlp, 0);
524
525 if (nlp->nlp_bkmap < 0) {
526 syslog(LOG_ERR, "Failed to allocate bitmap in mark_common_v2");
527 rv = -1;
528 } else {
529 if (fs_is_chkpntvol(nlp->nlp_backup_path))
530 chkpath = nlp->nlp_backup_path;
531 else
532 chkpath = tlm_build_snapshot_name(
533 nlp->nlp_backup_path, buf,
534 nlp->nlp_jstat->js_job_name);
535 rv = mark_inodes_v2(session, nlp, chkpath);
536 (void) dbm_setone(nlp->nlp_bkmap, (u_longlong_t)ROOT_INODE);
537 }
538
539 return (rv);
540 }
541
542
543 /*
544 * mark_tar_inodes_v2
545 *
546 * Create the bitmap for tar backup format.
589
590 /*
591 * ndmpd_mark_inodes_v2
592 *
593 * Mark the inodes of the backup hierarchy if necessary.
594 *
595 * Parameters:
596 * session (input) - pointer to the session
597 * nlp (input) - pointer to the nlp structure
598 *
599 * Returns:
600 * 0: on success.
601 * != 0: on error.
602 */
603 int
604 ndmpd_mark_inodes_v2(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
605 {
606 int rv;
607
608 if (ndmp_skip_traverse) {
609 syslog(LOG_INFO, "Skip processing directories \"%s\"",
610 nlp->nlp_backup_path);
611 rv = create_allset_bitmap(nlp);
612 } else {
613 if (NLP_ISTAR(nlp))
614 rv = mark_tar_inodes_v2(session, nlp);
615 else if (NLP_ISDUMP(nlp))
616 rv = mark_dump_inodes_v2(session, nlp);
617 else {
618 syslog(LOG_ERR, "Unknown backup type for \"%s\"",
619 nlp->nlp_backup_path);
620 rv = -1;
621 }
622 }
623
624 return (rv);
625 }
626
627
628 /*
629 * ndmpd_abort_making_v2
630 *
631 * Abort the process of marking inodes.
632 *
633 * Parameters:
634 * session (input) - pointer to the session
635 *
636 * Returns:
637 * void
638 */
653 * Traverse the backup hierarchy and mark the bits for the
654 * modified objects of directories leading to a modified
655 * object for the token-based backup.
656 *
657 * Parameters:
658 * session (input) - pointer to the session
659 * nlp (input) - pointer to the nlp structure
660 * path (input) - the physical path to traverse
661 *
662 * Returns:
663 * 0: on success
664 * != 0: otherwise
665 */
666 int
667 mark_tokv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
668 {
669 fs_traverse_t ft;
670 mark_param_t mp;
671
672 if (!session || !nlp || !path || !*path) {
673 syslog(LOG_ERR, "Invalid argument in mark_tokv3");
674 return (-1);
675 }
676 if (nlp->nlp_tokdate == (time_t)0)
677 return (create_allset_bitmap(nlp));
678
679 nlp->nlp_bkmap = create_bitmap(nlp, 0);
680 if (nlp->nlp_bkmap < 0) {
681 syslog(LOG_ERR, "Failed to allocate bitmap in mark_tokv3");
682 return (-1);
683 }
684
685 mp.mp_bmd = nlp->nlp_bkmap;
686 mp.mp_ddate = nlp->nlp_tokdate;
687 mp.mp_session = session;
688 mp.mp_nlp = nlp;
689
690 ft.ft_path = path;
691 ft.ft_lpath = nlp->nlp_backup_path;
692 ft.ft_callbk = mark_cb;
693 ft.ft_arg = ∓
694 ft.ft_logfp = (ft_log_t)syslog;
695 ft.ft_flags = ndmpd_mark_flags;
696
697 return (traverse(session, nlp, &ft));
698 }
699
700
701 /*
702 * marklbrv3_cb
703 *
704 * The callback function, called by traverse_post to mark
705 * bits in the bitmap.
706 *
707 * It's so much like mark_cb for time-based (token-based
708 * and level-type) backup types, except that it looks at
709 * the archive bit of the objects instead of their timestamp.
710 *
711 * Parameters:
712 * arg (input) - pointer to the mark parameter
713 * pnp (input) - pointer to the path node
714 * enp (input) - pointer to the entry node
715 *
716 * Returns:
717 * 0: as long as traversing should continue
718 * != 0: if traversing should stop
719 */
720 int
721 marklbrv3_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
722 {
723 int bmd;
724 u_longlong_t bl;
725 fs_fhandle_t *pfhp, *efhp;
726 struct stat64 *pstp, *estp;
727 mark_param_t *mpp;
728 ndmp_lbr_params_t *nlp;
729
730 mpp = (mark_param_t *)arg;
731 if (!mpp) {
732 syslog(LOG_ERR, "NULL argument passed in marklbrv3");
733 return (-1);
734 }
735 nlp = ndmp_get_nlp(mpp->mp_session);
736 if (mpp->mp_session->ns_data.dd_abort ||
737 (nlp && NLP_ISSET(nlp, NLPF_ABORTED))) {
738 syslog(LOG_ERR, "Processing directories aborted.");
739 return (-1);
740 }
741
742 bmd = mpp->mp_bmd;
743 bl = dbm_getlen(bmd);
744
745 pfhp = pnp->tn_fh;
746 pstp = pnp->tn_st;
747
748 /* sanity check on fh and stat of the path passed */
749 if (pstp->st_ino > bl) {
750 syslog(LOG_ERR, "Invalid path inode #%u",
751 (uint_t)pstp->st_ino);
752 return (-1);
753 }
754 if (pstp->st_ino != pfhp->fh_fid) {
755 syslog(LOG_ERR, "Path ino mismatch %u %u",
756 (uint_t)pstp->st_ino, (uint_t)pfhp->fh_fid);
757 return (-1);
758 }
759
760 /*
761 * Always mark the backup path inode number.
762 */
763 if (!enp->tn_path) {
764 (void) dbm_setone(bmd, pstp->st_ino);
765 return (0);
766 }
767
768 efhp = enp->tn_fh;
769 estp = enp->tn_st;
770
771 /* sanity check on fh and stat of the entry passed */
772 if (estp->st_ino > bl) {
773 syslog(LOG_ERR, "Invalid entry inode #%u",
774 (uint_t)estp->st_ino);
775 return (-1);
776 }
777 if (estp->st_ino != efhp->fh_fid) {
778 syslog(LOG_ERR, "Entry ino mismatch %u %u", estp->st_ino,
779 (uint_t)pfhp->fh_fid);
780 return (-1);
781 }
782
783 if (S_ISDIR(estp->st_mode) &&
784 dbm_getone(bmd, (u_longlong_t)estp->st_ino)) {
785 (void) dbm_setone(bmd, (u_longlong_t)pstp->st_ino);
786 }
787
788 return (0);
789 }
790
791
792 /*
793 * mark_lbrv3
794 *
795 * Traverse the backup hierarchy and mark the bits for the
796 * modified objects of directories leading to a modified
797 * object for the LBR-type backup.
798 *
799 * Parameters:
800 * session (input) - pointer to the session
801 * nlp (input) - pointer to the nlp structure
802 * path (input) - the physical path to traverse
803 *
804 * Returns:
805 * 0: on success
806 * != 0: otherwise
807 */
808 int
809 mark_lbrv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
810 {
811 char c;
812 fs_traverse_t ft;
813 mark_param_t mp;
814
815 if (!session || !nlp || !path || !*path) {
816 syslog(LOG_ERR, "Invalid argument in mark_lbrv3");
817 return (-1);
818 }
819 /* full and archive backups backup everything */
820 c = toupper(nlp->nlp_clevel);
821 if (c == 'F' || c == 'A')
822 return (create_allset_bitmap(nlp));
823
824 nlp->nlp_bkmap = create_bitmap(nlp, 0);
825 if (nlp->nlp_bkmap < 0) {
826 syslog(LOG_ERR, "Failed to allocate bitmap in mark_lbrv3");
827 return (-1);
828 }
829
830 mp.mp_bmd = nlp->nlp_bkmap;
831 mp.mp_ddate = 0;
832 mp.mp_session = session;
833 mp.mp_nlp = nlp;
834
835 ft.ft_path = path;
836 ft.ft_lpath = nlp->nlp_backup_path;
837 ft.ft_callbk = marklbrv3_cb;
838 ft.ft_arg = ∓
839 ft.ft_logfp = (ft_log_t)syslog;
840 ft.ft_flags = ndmpd_mark_flags;
841
842 return (traverse(session, nlp, &ft));
843 }
844
845
846 /*
847 * mark_levelv3
848 *
849 * Traverse the backup hierarchy and mark the bits for the
850 * modified objects of directories leading to a modified
851 * object for the level-type backup.
852 *
853 * Parameters:
854 * session (input) - pointer to the session
855 * nlp (input) - pointer to the nlp structure
856 * path (input) - the physical path to traverse
857 *
858 * Returns:
859 * 0: on success
860 * != 0: otherwise
861 */
862 int
863 mark_levelv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp, char *path)
864 {
865 fs_traverse_t ft;
866 mark_param_t mp;
867 tlm_acls_t traverse_acl;
868
869 if (!session || !nlp || !path || !*path) {
870 syslog(LOG_ERR, "Invalid argument in mark_levelv3");
871 return (-1);
872 }
873 if (nlp->nlp_ldate == (time_t)0)
874 return (create_allset_bitmap(nlp));
875
876 nlp->nlp_bkmap = create_bitmap(nlp, 0);
877 if (nlp->nlp_bkmap < 0) {
878 syslog(LOG_ERR, "Failed to allocate bitmap in mark_levelv3");
879 return (-1);
880 }
881
882 /*
883 * We do not want to allocate memory for acl every time we
884 * process a file.
885 */
886 (void) memset(&traverse_acl, 0, sizeof (traverse_acl));
887 mp.mp_tacl = &traverse_acl;
888
889 mp.mp_bmd = nlp->nlp_bkmap;
890 mp.mp_ddate = nlp->nlp_ldate;
891 mp.mp_session = session;
892 mp.mp_nlp = nlp;
893
894 ft.ft_path = path;
895 ft.ft_lpath = nlp->nlp_backup_path;
896 ft.ft_callbk = mark_cb;
897 ft.ft_arg = ∓
898 ft.ft_logfp = (ft_log_t)syslog;
899 ft.ft_flags = ndmpd_mark_flags;
900
901 return (traverse(session, nlp, &ft));
902 }
903
904
905 /*
906 * mark_commonv3
907 *
908 * Create the inode bitmap. If last date of the the
909 * backup is epoch, then all the objects should be backed
910 * up; there is no need to traverse the backup hierarchy
911 * and mark the inodes. All the bits should be marked.
912 *
913 * Otherwise, the backup hierarchy should be traversed and
914 * the objects should be marked.
915 *
916 * Parameters:
917 * session (input) - pointer to the session
918 * nlp (input) - pointer to the nlp structure
924 int
925 mark_commonv3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
926 {
927 char buf[TLM_MAX_PATH_NAME], *chkpath;
928 int rv;
929
930 if (NLP_ISCHKPNTED(nlp))
931 chkpath = nlp->nlp_backup_path;
932 else
933 chkpath = tlm_build_snapshot_name(nlp->nlp_backup_path, buf,
934 nlp->nlp_jstat->js_job_name);
935
936 if (NLP_ISSET(nlp, NLPF_TOKENBK))
937 rv = mark_tokv3(session, nlp, chkpath);
938 else if (NLP_ISSET(nlp, NLPF_LBRBK))
939 rv = mark_lbrv3(session, nlp, chkpath);
940 else if (NLP_ISSET(nlp, NLPF_LEVELBK)) {
941 rv = mark_levelv3(session, nlp, chkpath);
942 } else {
943 rv = -1;
944 syslog(LOG_ERR, "Unknown backup type for \"%s\"",
945 nlp->nlp_backup_path);
946 }
947
948 return (rv);
949 }
950
951
952 /*
953 * mark_tar_inodesv3
954 *
955 * Mark bits for tar backup format of V3. Normally, the
956 * backup hierarchy is not traversed for tar format
957 * unless it's forced by setting the ndmp_tar_force_traverse
958 * to a non-zero value.
959 *
960 * Parameters:
961 * session (input) - pointer to the session
962 * nlp (input) - pointer to the nlp structure
963 *
964 * Returns:
981
982 /*
983 * ndmpd_mark_inodes_v3
984 *
985 * Mark the inodes of the backup hierarchy if necessary.
986 *
987 * Parameters:
988 * session (input) - pointer to the session
989 * nlp (input) - pointer to the nlp structure
990 *
991 * Returns:
992 * 0: on success.
993 * != 0: on error.
994 */
995 int
996 ndmpd_mark_inodes_v3(ndmpd_session_t *session, ndmp_lbr_params_t *nlp)
997 {
998 int rv;
999
1000 if (ndmp_skip_traverse) {
1001 syslog(LOG_INFO, "Skip processing directories \"%s\"",
1002 nlp->nlp_backup_path);
1003 rv = create_allset_bitmap(nlp);
1004 } else {
1005 if (NLP_ISTAR(nlp))
1006 rv = mark_tar_inodesv3(session, nlp);
1007 else if (NLP_ISDUMP(nlp)) {
1008 rv = mark_commonv3(session, nlp);
1009 } else {
1010 syslog(LOG_ERR, "Unknown backup type for \"%s\"",
1011 nlp->nlp_backup_path);
1012 rv = -1;
1013 }
1014 }
1015
1016 return (rv);
1017 }
|