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 <stdlib.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <sys/queue.h> 43 #include <sys/syslog.h> 44 #include "tlm.h" 45 #include "tlm_proto.h" 46 47 #define HL_DBG_INIT 0x0001 48 #define HL_DBG_CLEANUP 0x0002 49 #define HL_DBG_GET 0x0004 50 #define HL_DBG_ADD 0x0008 51 52 static int hardlink_q_dbg = -1; 53 54 55 struct hardlink_q * 56 hardlink_q_init() 57 { 58 struct hardlink_q *qhead; 59 60 qhead = (struct hardlink_q *)malloc(sizeof (struct hardlink_q)); 61 if (qhead) { 62 SLIST_INIT(qhead); 63 } 64 65 if (hardlink_q_dbg & HL_DBG_INIT) 66 NDMP_LOG(LOG_DEBUG, "qhead = %p", qhead); 67 68 return (qhead); 69 } 70 71 void 72 hardlink_q_cleanup(struct hardlink_q *hl_q) 73 { 74 struct hardlink_node *hl; 75 76 if (hardlink_q_dbg & HL_DBG_CLEANUP) 77 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p", hl_q); 78 79 if (!hl_q) 80 return; 81 82 while (!SLIST_EMPTY(hl_q)) { 83 hl = SLIST_FIRST(hl_q); 84 85 if (hardlink_q_dbg & HL_DBG_CLEANUP) 86 NDMP_LOG(LOG_DEBUG, "(2): remove node, inode = %lu", 87 hl->inode); 88 89 SLIST_REMOVE_HEAD(hl_q, next_hardlink); 90 91 /* remove the temporary file */ 92 if (hl->is_tmp) { 93 if (hl->path) { 94 NDMP_LOG(LOG_DEBUG, "(3): remove temp file %s", 95 hl->path); 96 if (remove(hl->path)) { 97 NDMP_LOG(LOG_DEBUG, 98 "error removing temp file"); 99 } 100 } else { 101 NDMP_LOG(LOG_DEBUG, "no link name, inode = %lu", 102 hl->inode); 103 } 104 } 105 106 if (hl->path) 107 free(hl->path); 108 free(hl); 109 } 110 111 free(hl_q); 112 } 113 114 /* 115 * Return 0 if a list node has the same inode, and initialize offset and path 116 * with the information in the list node. 117 * Return -1 if no matching node is found. 118 */ 119 int 120 hardlink_q_get(struct hardlink_q *hl_q, unsigned long inode, 121 unsigned long long *offset, char **path) 122 { 123 struct hardlink_node *hl; 124 125 if (hardlink_q_dbg & HL_DBG_GET) 126 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p, inode = %lu", 127 hl_q, inode); 128 129 if (!hl_q) 130 return (-1); 131 132 SLIST_FOREACH(hl, hl_q, next_hardlink) { 133 if (hardlink_q_dbg & HL_DBG_GET) 134 NDMP_LOG(LOG_DEBUG, "(2): checking, inode = %lu", 135 hl->inode); 136 137 if (hl->inode != inode) 138 continue; 139 140 if (offset) 141 *offset = hl->offset; 142 143 if (path) 144 *path = hl->path; 145 146 return (0); 147 } 148 149 return (-1); 150 } 151 152 /* 153 * Add a node to hardlink_q. Reject a duplicated entry. 154 * 155 * Return 0 if successful, and -1 if failed. 156 */ 157 int 158 hardlink_q_add(struct hardlink_q *hl_q, unsigned long inode, 159 unsigned long long offset, char *path, int is_tmp_file) 160 { 161 struct hardlink_node *hl; 162 163 if (hardlink_q_dbg & HL_DBG_ADD) 164 NDMP_LOG(LOG_DEBUG, 165 "(1): qhead = %p, inode = %lu, path = %p (%s)", 166 hl_q, inode, path, path? path : "(--)"); 167 168 if (!hl_q) 169 return (-1); 170 171 if (!hardlink_q_get(hl_q, inode, 0, 0)) { 172 NDMP_LOG(LOG_DEBUG, "hardlink (inode = %lu) exists in queue %p", 173 inode, hl_q); 174 return (-1); 175 } 176 177 hl = (struct hardlink_node *)malloc(sizeof (struct hardlink_node)); 178 if (!hl) 179 return (-1); 180 181 hl->inode = inode; 182 hl->offset = offset; 183 hl->is_tmp = is_tmp_file; 184 if (path) 185 hl->path = strdup(path); 186 else 187 hl->path = NULL; 188 189 if (hardlink_q_dbg & HL_DBG_ADD) 190 NDMP_LOG(LOG_DEBUG, 191 "(2): added node, inode = %lu, path = %p (%s)", 192 hl->inode, hl->path, hl->path? hl->path : "(--)"); 193 194 SLIST_INSERT_HEAD(hl_q, hl, next_hardlink); 195 196 return (0); 197 } 198 199 int 200 hardlink_q_dump(struct hardlink_q *hl_q) 201 { 202 struct hardlink_node *hl; 203 204 if (!hl_q) 205 return (0); 206 207 (void) printf("Dumping hardlink_q, head = %p:\n", (void *) hl_q); 208 209 SLIST_FOREACH(hl, hl_q, next_hardlink) 210 (void) printf( 211 "\t node = %lu, offset = %llu, path = %s, is_tmp = %d\n", 212 hl->inode, hl->offset, hl->path? hl->path : "--", 213 hl->is_tmp); 214 215 return (0); 216 } 217