Print this page
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Revert "NEX-5801 Snapshots left over after failed backups"
This reverts commit f182fb95f09036db71fbfc6f0a6b90469b761f21.
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@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_util.c
+++ new/usr/src/cmd/ndmpd/tlm/tlm_util.c
1 1 /*
2 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 * Copyright 2012 Milan Jurik. All rights reserved.
5 5 */
6 6
7 7 /*
8 8 * BSD 3 Clause License
9 9 *
10 10 * Copyright (c) 2007, The Storage Networking Industry Association.
11 11 *
12 12 * Redistribution and use in source and binary forms, with or without
13 13 * modification, are permitted provided that the following conditions
14 14 * are met:
15 15 * - Redistributions of source code must retain the above copyright
16 16 * notice, this list of conditions and the following disclaimer.
17 17 *
18 18 * - Redistributions in binary form must reproduce the above copyright
19 19 * notice, this list of conditions and the following disclaimer in
20 20 * the documentation and/or other materials provided with the
21 21 * distribution.
22 22 *
23 23 * - Neither the name of The Storage Networking Industry Association (SNIA)
24 24 * nor the names of its contributors may be used to endorse or promote
25 25 * products derived from this software without specific prior written
26 26 * permission.
27 27 *
28 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
30 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 38 * POSSIBILITY OF SUCH DAMAGE.
39 39 */
40 +/* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
41 +
42 +#include <syslog.h>
40 43 #include <stdio.h>
41 44 #include <stdlib.h>
42 45 #include <string.h>
43 46 #include <strings.h>
44 47 #include <cstack.h>
45 48 #include <ctype.h>
46 49 #include <tlm.h>
47 50 #include "tlm_proto.h"
48 51
49 52 /*
50 53 * Implementation of a list based stack class. The stack only holds
51 54 * pointers/references to application objects. The objects are not
52 55 * copied and the stack never attempts to dereference or access the
53 56 * data objects. Applications should treat cstack_t references as
54 57 * opaque handles.
55 58 */
56 59
57 60 /*
58 61 * cstack_new
59 62 *
60 63 * Allocate and initialize a new stack, which is just an empty cstack_t.
61 64 * A pointer to the new stack is returned. This should be treated as an
62 65 * opaque handle by the caller.
63 66 */
64 67 cstack_t *
65 68 cstack_new(void)
66 69 {
67 70 cstack_t *stk;
68 71
69 72 if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
70 73 return (NULL);
71 74
72 75 return (stk);
73 76 }
74 77
75 78
76 79 /*
77 80 * cstack_delete
78 81 *
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
79 82 * Deallocate the stack. This goes through the list freeing all of the
80 83 * cstack nodes but not the data because we don't know how the data was
81 84 * allocated. A stack really should be empty before it is deleted.
82 85 */
83 86 void
84 87 cstack_delete(cstack_t *stk)
85 88 {
86 89 cstack_t *tmp;
87 90
88 91 if (stk == NULL) {
89 - NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
90 92 return;
91 93 }
92 94
93 95 while ((tmp = stk->next) != NULL) {
94 96 stk->next = tmp->next;
95 - NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp);
96 97 free(tmp);
97 98 }
98 99
99 - NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
100 100 free(stk);
101 101 }
102 102
103 103
104 104 /*
105 105 * cstack_push
106 106 *
107 107 * Push an element onto the stack. Allocate a new node and assign the
108 108 * data and len values. We don't care what about the real values of
109 109 * data or len and we never try to access them. The stack head will
110 110 * point to the new node.
111 111 *
112 112 * Returns 0 on success. Otherwise returns -1 to indicate overflow.
113 113 */
114 114 int
115 115 cstack_push(cstack_t *stk, void *data, int len)
116 116 {
117 117 cstack_t *stk_node;
118 118
119 119 if (stk == NULL) {
120 - NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack");
121 120 return (-1);
122 121 }
123 122
124 123 if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
125 124 return (-1);
126 125
127 126 stk_node->data = data;
128 127 stk_node->len = len;
129 128 stk_node->next = stk->next;
130 129 stk->next = stk_node;
131 130
132 - NDMP_LOG(LOG_DEBUG, "cstack_push(0x%p): 0x%p", stk, stk_node);
133 131 return (0);
134 132 }
135 133
136 134
137 135 /*
138 136 * cstack_pop
139 137 *
140 138 * Pop an element off the stack. Set up the data and len references for
141 139 * the caller, advance the stack head and free the popped stack node.
142 140 *
143 141 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
144 142 */
145 143 int
146 144 cstack_pop(cstack_t *stk, void **data, int *len)
147 145 {
148 146 cstack_t *stk_node;
149 147
150 148 if (stk == NULL) {
151 - NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
152 149 return (-1);
153 150 }
154 151
155 152 if ((stk_node = stk->next) == NULL) {
156 - NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
157 153 return (-1);
158 154 }
159 155
160 156 if (data)
161 157 *data = stk_node->data;
162 158
163 159 if (len)
164 160 *len = stk_node->len;
165 161
166 162 stk->next = stk_node->next;
167 - NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node);
168 163
169 164 free(stk_node);
170 165 return (0);
171 166 }
172 167
173 168 /*
174 169 * cstack_top
175 170 *
176 171 * Returns the top data element on the stack without removing it.
177 172 *
178 173 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
179 174 */
180 175 int
181 176 cstack_top(cstack_t *stk, void **data, int *len)
182 177 {
183 178 if (stk == NULL) {
184 - NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
185 179 return (-1);
186 180 }
187 181
188 182 if (stk->next == NULL) {
189 - NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
190 183 return (-1);
191 184 }
192 185
193 186 if (data)
194 187 *data = stk->next->data;
195 188
196 189 if (len)
197 190 *len = stk->next->len;
198 191
199 192 return (0);
200 193 }
201 194
202 195 /*
203 196 * match
204 197 *
205 198 * Matching rules:
206 199 * c Any non-special character matches itslef
207 200 * ? Match any character
208 201 * ab character 'a' followed by character 'b'
209 202 * S Any string of non-special characters
210 203 * AB String 'A' followed by string 'B'
211 204 * * Any String, including the empty string
212 205 */
213 206 boolean_t
214 207 match(char *patn, char *str)
215 208 {
216 209 for (; ; ) {
217 210 switch (*patn) {
218 211 case 0:
219 212 return (*str == 0);
220 213
221 214 case '?':
222 215 if (*str != 0) {
223 216 str++;
224 217 patn++;
225 218 continue;
226 219 }
227 220 return (FALSE);
228 221
229 222 case '*':
230 223 patn++;
231 224 if (*patn == 0)
232 225 return (TRUE);
233 226
234 227 while (*str) {
235 228 if (match(patn, str))
236 229 return (TRUE);
237 230 str++;
238 231 }
239 232 return (FALSE);
240 233
241 234 default:
242 235 if (*str != *patn)
243 236 return (FALSE);
244 237 str++;
245 238 patn++;
246 239 continue;
247 240 }
248 241 }
249 242 }
250 243
251 244 /*
252 245 * Match recursive call
253 246 */
254 247 int
255 248 match_ci(char *patn, char *str)
256 249 {
257 250 /*
258 251 * "<" is a special pattern that matches only those names
259 252 * that do NOT have an extension. "." and ".." are ok.
260 253 */
261 254 if (strcmp(patn, "<") == 0) {
262 255 if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
263 256 return (TRUE);
264 257 if (strchr(str, '.') == 0)
265 258 return (TRUE);
266 259 return (FALSE);
267 260 }
268 261 for (; ; ) {
269 262 switch (*patn) {
270 263 case 0:
271 264 return (*str == 0);
272 265
273 266 case '?':
274 267 if (*str != 0) {
275 268 str++;
276 269 patn++;
277 270 continue;
278 271 }
279 272 return (FALSE);
280 273
281 274 case '*':
282 275 patn++;
283 276 if (*patn == 0)
284 277 return (TRUE);
285 278
286 279 while (*str) {
287 280 if (match_ci(patn, str))
288 281 return (TRUE);
289 282 str++;
290 283 }
291 284 return (FALSE);
292 285
293 286 default:
294 287 if (*str != *patn) {
295 288 int c1 = *str;
296 289 int c2 = *patn;
297 290
298 291 c1 = tolower(c1);
299 292 c2 = tolower(c2);
300 293 if (c1 != c2)
301 294 return (FALSE);
302 295 }
303 296 str++;
304 297 patn++;
305 298 continue;
306 299 }
307 300 }
308 301 /* NOT REACHED */
309 302 }
310 303
311 304 /*
312 305 * Linear matching against a list utility function
313 306 */
314 307 static boolean_t
315 308 parse_match(char line, char *seps)
316 309 {
317 310 char *sep = seps;
318 311
319 312 while (*sep != 0) {
320 313 /* compare this char with the seperator list */
321 314 if (*sep == line)
322 315 return (TRUE);
323 316 sep++;
324 317 }
325 318 return (FALSE);
326 319 }
327 320
328 321 /*
329 322 * Returns the next entry of the list after
330 323 * each separator
331 324 */
332 325 char *
333 326 parse(char **line, char *seps)
334 327 {
335 328 char *start = *line;
336 329
337 330 while (**line != 0) {
338 331 *line = *line + 1;
339 332 if (parse_match(**line, seps)) {
340 333 /* hit a terminator, skip trailing terminators */
341 334 while (parse_match(**line, seps)) {
342 335 **line = 0;
343 336 *line = *line + 1;
344 337 }
345 338 break;
346 339 }
347 340 }
348 341 return (start);
349 342 }
350 343
351 344 /*
352 345 * oct_atoi
353 346 *
354 347 * Convert an octal string to integer
355 348 */
356 349 int
357 350 oct_atoi(char *p)
358 351 {
359 352 int v = 0;
360 353 int c;
361 354
362 355 while (*p == ' ')
363 356 p++;
364 357
365 358 while ('0' <= (c = *p++) && c <= '7') {
366 359 v <<= 3;
367 360 v += c - '0';
368 361 }
369 362
370 363 return (v);
371 364 }
372 365
373 366 /*
374 367 * strupr
375 368 *
376 369 * Convert a string to uppercase using the appropriate codepage. The
377 370 * string is converted in place. A pointer to the string is returned.
378 371 * There is an assumption here that uppercase and lowercase values
379 372 * always result encode to the same length.
380 373 */
381 374 char *
382 375 strupr(char *s)
383 376 {
384 377 char c;
385 378 unsigned char *p = (unsigned char *)s;
386 379
387 380 while (*p) {
388 381 c = toupper(*p);
389 382 *p++ = c;
390 383 }
391 384 return (s);
392 385 }
393 386
394 387 /*
395 388 * trim_whitespace
396 389 *
397 390 * Trim leading and trailing whitespace chars(as defined by isspace)
398 391 * from a buffer. Example; if the input buffer contained " text ",
399 392 * it will contain "text", when we return. We assume that the buffer
400 393 * contains a null terminated string. A pointer to the buffer is
401 394 * returned.
402 395 */
403 396 char *
404 397 trim_whitespace(char *buf)
405 398 {
406 399 char *p = buf;
407 400 char *q = buf;
408 401
409 402 if (buf == 0)
410 403 return (0);
411 404
412 405 while (*p && isspace(*p))
413 406 ++p;
414 407
415 408 while ((*q = *p++) != 0)
416 409 ++q;
417 410
418 411 if (q != buf) {
419 412 while ((--q, isspace(*q)) != 0)
420 413 *q = '\0';
421 414 }
422 415
423 416 return (buf);
424 417 }
425 418
426 419 /*
427 420 * trim_name
428 421 *
429 422 * Trims the slash and dot slash from the beginning of the
430 423 * path name.
431 424 */
432 425 char *
433 426 trim_name(char *nm)
434 427 {
435 428 while (*nm) {
436 429 if (*nm == '/') {
437 430 nm++;
438 431 continue;
439 432 }
440 433 if (*nm == '.' && nm[1] == '/' && nm[2]) {
441 434 nm += 2;
442 435 continue;
443 436 }
444 437 break;
445 438 }
446 439 return (nm);
447 440 }
448 441
449 442 /*
450 443 * get_volname
451 444 *
452 445 * Extract the volume name from the path
453 446 */
454 447 char *
455 448 get_volname(char *path)
456 449 {
457 450 char *cp, *save;
458 451 int sp;
459 452
460 453 if (!path)
461 454 return (NULL);
462 455
463 456 if (!(save = strdup(path)))
464 457 return (NULL);
465 458
466 459 sp = strspn(path, "/");
467 460 if (*(path + sp) == '\0') {
468 461 free(save);
469 462 return (NULL);
470 463 }
471 464
472 465 if ((cp = strchr(save + sp, '/')))
473 466 *cp = '\0';
474 467
475 468 return (save);
476 469 }
477 470
478 471 /*
479 472 * fs_volexist
480 473 *
481 474 * Check if the volume exists
482 475 */
483 476 boolean_t
484 477 fs_volexist(char *path)
485 478 {
486 479 struct stat64 st;
487 480 char *p;
488 481
489 482 if ((p = get_volname(path)) == NULL)
490 483 return (FALSE);
491 484
492 485 if (stat64(p, &st) != 0) {
493 486 free(p);
494 487 return (FALSE);
495 488 }
496 489
497 490 free(p);
498 491 return (TRUE);
499 492 }
500 493
501 494 /*
502 495 * tlm_tarhdr_size
503 496 *
504 497 * Returns the size of the TLM_TAR_HDR structure.
505 498 */
506 499 int
507 500 tlm_tarhdr_size(void)
508 501 {
509 502 return (sizeof (tlm_tar_hdr_t));
510 503 }
511 504
512 505 /*
513 506 * dup_dir_info
514 507 *
515 508 * Make and return a copy of the directory info.
516 509 */
517 510 struct full_dir_info *
518 511 dup_dir_info(struct full_dir_info *old_dir_info)
519 512 {
520 513 struct full_dir_info *new_dir_info;
521 514 new_dir_info = ndmp_malloc(sizeof (struct full_dir_info));
522 515
523 516 if (new_dir_info) {
524 517 bcopy(old_dir_info, new_dir_info,
525 518 sizeof (struct full_dir_info));
526 519 }
527 520 return (new_dir_info);
528 521 }
529 522
530 523 /*
531 524 * tlm_new_dir_info
532 525 *
533 526 * Create a new structure, set fh field to what is specified and the path
534 527 * to the concatenation of directory and the component
535 528 */
536 529 struct full_dir_info *
|
↓ open down ↓ |
337 lines elided |
↑ open up ↑ |
537 530 tlm_new_dir_info(struct fs_fhandle *fhp, char *dir, char *nm)
538 531 {
539 532 struct full_dir_info *fdip;
540 533
541 534 if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
542 535 return (NULL);
543 536
544 537 (void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
545 538 if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
546 539 free(fdip);
547 - NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
540 + syslog(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
548 541 dir, nm);
549 542 return (NULL);
550 543 }
551 544 return (fdip);
552 545 }
553 546
554 547 /*
555 548 * sysattr_rdonly
556 549 *
557 550 * Check if the attribute file is one of the readonly system
558 551 * attributes.
559 552 */
560 553 int
561 554 sysattr_rdonly(char *name)
562 555 {
563 556 return (name && strcmp(name, SYSATTR_RDONLY) == 0);
564 557 }
565 558
566 559 /*
567 560 * sysattr_rw
568 561 *
569 562 * Check if the attribute file is one of the read/write system
570 563 * attributes.
571 564 */
572 565 int
573 566 sysattr_rw(char *name)
574 567 {
575 568 return (name && strcmp(name, SYSATTR_RW) == 0);
576 569 }
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX