Changeset 268
- Timestamp:
- 05/03/14 04:14:58 (11 years ago)
- Location:
- ksyslog/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
ksyslog/trunk/compat.h
r264 r268 13 13 pos != (head); \ 14 14 pos = rcu_dereference_raw(list_next_rcu(pos))) 15 #endif 16 17 #ifndef list_first_or_null_rcu 18 #define list_first_or_null_rcu(ptr, type, member) \ 19 ({ \ 20 struct list_head *__ptr = (ptr); \ 21 struct list_head *__next = ACCESS_ONCE(__ptr->next); \ 22 likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \ 23 }) 15 24 #endif 16 25 -
ksyslog/trunk/ksyslog.c
r264 r268 38 38 static ulong ksyslog_flush_interval = 45; /* milliseconds */ 39 39 40 static DEFINE_SPINLOCK(ksyslog_write_lock); 41 40 42 module_param(ksyslog_host, charp, 0444); 41 43 module_param(ksyslog_port, ushort, 0444); … … 135 137 ksyslog_drop_warning(const struct ksyslog_entry *entry) 136 138 { 137 pr_warn("ksyslog: dropped: %llu %s.%s %u.%u.%u.%u %.*s\n", 138 timeval_to_ns(&entry->tv) / 1000 / 1000 / 1000, 139 ksyslog_facility_str(entry->facility), 140 ksyslog_severity_str(entry->severity), 141 entry->saddr.addr8[0], entry->saddr.addr8[1], 142 entry->saddr.addr8[2], entry->saddr.addr8[3], 143 (int)entry->length, entry->data); 144 } 145 146 static int 147 ksyslog_format(char **buf, const struct ksyslog_entry *entry) 139 net_warn_ratelimited("ksyslog: dropped: %llu %s.%s %u.%u.%u.%u %.*s\n", 140 timeval_to_ns(&entry->tv) / 1000 / 1000 / 1000, 141 ksyslog_facility_str(entry->facility), 142 ksyslog_severity_str(entry->severity), 143 entry->saddr.addr8[0], entry->saddr.addr8[1], 144 entry->saddr.addr8[2], entry->saddr.addr8[3], 145 (int)entry->length, entry->data); 146 } 147 148 static struct ksyslog_entry * 149 ksyslog_entry_create(const struct sk_buff *skb, 150 const struct iphdr *iph, const struct udphdr *udph) 151 { 152 struct ksyslog_entry *entry; 153 unsigned int priority, facility, severity, month, day, hour, minute, second; 154 unsigned char *start, month_s[4]; 155 struct tm tm; 156 int length, i; 157 158 if (sscanf(skb->data, "<%3u>%3s %2u %2u:%2u:%2u ", 159 &priority, month_s, &day, &hour, &minute, &second) != 6) 160 return ERR_PTR(-EINVAL); 161 162 start = memchr(skb->data, '>', 5); 163 if (start == NULL) 164 return ERR_PTR(-EINVAL); 165 start++; 166 167 facility = priority >> 3; 168 severity = priority & 7; 169 170 if (facility >= __KSYSLOG_F_MAX) 171 return ERR_PTR(-EINVAL); 172 if (severity >= __KSYSLOG_S_MAX) 173 return ERR_PTR(-EINVAL); 174 175 month = ksyslog_month_num(month_s); 176 if (!month) 177 return ERR_PTR(-EINVAL); 178 if (day > 31) 179 return ERR_PTR(-EINVAL); 180 if (hour > 23) 181 return ERR_PTR(-EINVAL); 182 if (minute > 59) 183 return ERR_PTR(-EINVAL); 184 if (second > 59) 185 return ERR_PTR(-EINVAL); 186 187 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 188 if (unlikely(entry == NULL)) 189 return ERR_PTR(-ENOMEM); 190 191 length = skb->len - (start - skb->data); 192 entry->data = kzalloc(length, GFP_ATOMIC); 193 if (unlikely(entry->data == NULL)) { 194 kfree(entry); 195 return ERR_PTR(-ENOMEM); 196 } 197 198 if (skb->tstamp.tv64) 199 entry->tv = ktime_to_timeval(skb->tstamp); 200 else 201 do_gettimeofday(&entry->tv); 202 203 time_to_tm(entry->tv.tv_sec, 0, &tm); 204 entry->time = mktime(tm.tm_year + 1900, month, day, hour, minute, second); 205 206 entry->priority = priority; 207 entry->facility = facility; 208 entry->severity = severity; 209 210 entry->daddr.addr32 = iph->daddr; 211 entry->saddr.addr32 = iph->saddr; 212 213 entry->dport = udph->dest; 214 entry->sport = udph->source; 215 216 entry->length = length; 217 memcpy(entry->data, start, length); 218 219 for (i = 0; i < length; i++) 220 if (unlikely(entry->data[i] == '\n')) 221 entry->data[i] = ' '; 222 223 return entry; 224 } 225 226 static void 227 ksyslog_entry_free(struct rcu_head *head) 228 { 229 struct ksyslog_entry *entry = container_of(head, struct ksyslog_entry, rcu); 230 kfree(entry->data); 231 kfree(entry); 232 } 233 234 static int 235 ksyslog_entry_add(struct ksyslog_queue *queue, struct ksyslog_entry *entry) 236 { 237 if (unlikely(atomic64_read(&queue->size) >= ksyslog_queue_size_max)) 238 return -ENOBUFS; 239 list_add_tail_rcu(&entry->list, &queue->head); 240 WARN_ON(atomic64_inc_return(&queue->size) > ksyslog_queue_size_max); 241 return 0; 242 } 243 244 static void 245 ksyslog_entry_del(struct ksyslog_queue *queue, struct ksyslog_entry *entry, bool free) 246 { 247 WARN_ON(atomic64_dec_return(&queue->size) < 0); 248 list_del_rcu(&entry->list); 249 if (free) 250 call_rcu(&entry->rcu, ksyslog_entry_free); 251 } 252 253 static void 254 ksyslog_entry_destroy(struct ksyslog_queue *queue) 255 { 256 struct ksyslog_entry *entry, *next; 257 258 list_for_each_entry_safe(entry, next, &queue->head, list) 259 ksyslog_entry_del(queue, entry, true); 260 } 261 262 static int 263 ksyslog_entry_format(char **buf, const struct ksyslog_entry *entry) 148 264 { 149 265 *buf = kzalloc(54 + entry->length + 2, GFP_ATOMIC); … … 160 276 } 161 277 162 static struct ksyslog_entry * 163 ksyslog_entry_create(const struct sk_buff *skb, 164 const struct iphdr *iph, const struct udphdr *udph) 165 { 278 static bool 279 ksyslog_entry_write(struct file *file, struct ksyslog_entry *entry) 280 { 281 int length; 282 char *buf; 283 284 length = ksyslog_entry_format(&buf, entry); 285 286 if (unlikely(length < 0)) 287 return false; 288 289 if (unlikely(ksyslog_write(file, buf, length) != length)) { 290 kfree(buf); 291 return false; 292 } 293 294 kfree(buf); 295 return true; 296 } 297 298 static void 299 ksyslog_work_register(unsigned long timer) 300 { 301 queue_delayed_work(ksyslog_wq, &ksyslog_work, timer * HZ / 1000); 302 } 303 304 static void 305 ksyslog_work_unregister(void) 306 { 307 cancel_delayed_work_sync(&ksyslog_work); 308 } 309 310 static void 311 ksyslog_work_handler(struct work_struct *work) 312 { 313 struct file *file = NULL; 166 314 struct ksyslog_entry *entry; 167 unsigned int priority, facility, severity, month, day, hour, minute, second; 168 unsigned char *start, month_s[4]; 169 struct tm tm; 170 int length, i; 171 172 if (sscanf(skb->data, "<%3u>%3s %2u %2u:%2u:%2u ", 173 &priority, month_s, &day, &hour, &minute, &second) != 6) 174 return ERR_PTR(-EINVAL); 175 176 start = memchr(skb->data, '>', 5); 177 if (start == NULL) 178 return ERR_PTR(-EINVAL); 179 start++; 180 181 facility = priority >> 3; 182 severity = priority & 7; 183 184 if (facility >= __KSYSLOG_F_MAX) 185 return ERR_PTR(-EINVAL); 186 if (severity >= __KSYSLOG_S_MAX) 187 return ERR_PTR(-EINVAL); 188 189 month = ksyslog_month_num(month_s); 190 if (!month) 191 return ERR_PTR(-EINVAL); 192 if (day > 31) 193 return ERR_PTR(-EINVAL); 194 if (hour > 23) 195 return ERR_PTR(-EINVAL); 196 if (minute > 59) 197 return ERR_PTR(-EINVAL); 198 if (second > 59) 199 return ERR_PTR(-EINVAL); 200 201 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 202 if (unlikely(entry == NULL)) 203 return ERR_PTR(-ENOMEM); 204 205 length = skb->len - (start - skb->data); 206 entry->data = kzalloc(length, GFP_ATOMIC); 207 if (unlikely(entry->data == NULL)) { 208 kfree(entry); 209 return ERR_PTR(-ENOMEM); 210 } 211 212 if (skb->tstamp.tv64) 213 entry->tv = ktime_to_timeval(skb->tstamp); 214 else 215 do_gettimeofday(&entry->tv); 216 217 time_to_tm(entry->tv.tv_sec, 0, &tm); 218 entry->time = mktime(tm.tm_year + 1900, month, day, hour, minute, second); 219 220 entry->priority = priority; 221 entry->facility = facility; 222 entry->severity = severity; 223 224 entry->daddr.addr32 = iph->daddr; 225 entry->saddr.addr32 = iph->saddr; 226 227 entry->dport = udph->dest; 228 entry->sport = udph->source; 229 230 entry->length = length; 231 memcpy(entry->data, start, length); 232 233 for (i = 0; i < length; i++) 234 if (unlikely(entry->data[i] == '\n')) 235 entry->data[i] = ' '; 236 237 return entry; 238 } 239 240 static void 241 ksyslog_entry_free(struct rcu_head *head) 242 { 243 struct ksyslog_entry *entry = container_of(head, struct ksyslog_entry, rcu); 244 kfree(entry->data); 245 kfree(entry); 246 } 247 248 static int 249 ksyslog_entry_add(struct ksyslog_queue *queue, struct ksyslog_entry *entry) 250 { 251 if (unlikely(atomic64_read(&queue->size) >= ksyslog_queue_size_max)) 252 return -ENOBUFS; 253 list_add_tail_rcu(&entry->list, &queue->head); 254 WARN_ON(atomic64_inc_return(&queue->size) > ksyslog_queue_size_max); 255 return 0; 256 } 257 258 static void 259 ksyslog_entry_del(struct ksyslog_queue *queue, struct ksyslog_entry *entry, bool free) 260 { 261 WARN_ON(atomic64_dec_return(&queue->size) < 0); 262 list_del_rcu(&entry->list); 263 if (free) 264 call_rcu(&entry->rcu, ksyslog_entry_free); 265 } 266 267 static void 268 ksyslog_entry_destroy(struct ksyslog_queue *queue) 269 { 270 struct ksyslog_entry *entry, *next; 271 272 list_for_each_entry_safe(entry, next, &queue->head, list) 273 ksyslog_entry_del(queue, entry, true); 274 } 275 276 static void 277 ksyslog_entry_migrate(struct ksyslog_queue *from, struct ksyslog_queue *to) 278 { 279 struct ksyslog_entry *entry, *next; 280 281 list_for_each_entry_safe(entry, next, &from->head, list) { 282 ksyslog_entry_del(from, entry, false); 283 if (unlikely(ksyslog_entry_add(to, entry))) { 284 ksyslog_stats_add_drop(from, entry->length); 285 ksyslog_stats_add_drop(to, entry->length); 286 ksyslog_drop_warning(entry); 287 call_rcu(&entry->rcu, ksyslog_entry_free); 315 316 file = ksyslog_open(ksyslog_path); 317 if (unlikely(IS_ERR(file))) 318 goto out; 319 320 while (true) { 321 bool write_ok; 322 323 spin_lock_bh(&ksyslog_queue.lock); 324 entry = list_first_or_null_rcu(&ksyslog_queue.head, 325 struct ksyslog_entry, list); 326 if (!entry) { 327 spin_unlock_bh(&ksyslog_queue.lock); 328 break; 288 329 } 289 } 290 } 291 292 static void 293 ksyslog_work_register(unsigned long timer) 294 { 295 queue_delayed_work(ksyslog_wq, &ksyslog_work, timer * HZ / 1000); 296 } 297 298 static void 299 ksyslog_work_unregister(void) 300 { 301 cancel_delayed_work_sync(&ksyslog_work); 302 } 303 304 static void 305 ksyslog_work_handler(struct work_struct *work) 306 { 307 struct file *file = NULL; 308 struct ksyslog_entry *entry, *next; 309 struct ksyslog_queue write_queue; 310 311 if (ksyslog_queue_init(&write_queue)) 312 goto out; 313 314 spin_lock_bh(&ksyslog_queue.lock); 315 ksyslog_entry_migrate(&ksyslog_queue, &write_queue); 316 spin_unlock_bh(&ksyslog_queue.lock); 317 318 if (atomic64_read(&write_queue.size) <= 0) 319 goto out; 320 321 file = ksyslog_open(ksyslog_path); 322 if (unlikely(IS_ERR(file))) { 323 spin_lock_bh(&ksyslog_queue.lock); 324 ksyslog_entry_migrate(&write_queue, &ksyslog_queue); 330 ksyslog_entry_del(&ksyslog_queue, entry, false); 325 331 spin_unlock_bh(&ksyslog_queue.lock); 326 goto out; 327 } 328 329 list_for_each_entry_safe(entry, next, &write_queue.head, list) { 330 int length; 331 char *buf; 332 333 ksyslog_entry_del(&write_queue, entry, false); 334 335 length = ksyslog_format(&buf, entry); 336 if (unlikely(length < 0)) 337 goto restore; 338 339 if (unlikely(ksyslog_write(file, buf, length) != length)) { 340 kfree(buf); 341 goto restore; 342 } 343 344 ksyslog_stats_add_write(&ksyslog_queue, entry->length); 345 kfree(buf); 346 call_rcu(&entry->rcu, ksyslog_entry_free); 347 continue; 348 349 restore: 350 spin_lock_bh(&ksyslog_queue.lock); 351 if (unlikely(ksyslog_entry_add(&ksyslog_queue, entry))) { 332 333 spin_lock(&ksyslog_write_lock); 334 write_ok = ksyslog_entry_write(file, entry); 335 spin_unlock(&ksyslog_write_lock); 336 337 if (likely(write_ok)) { 338 ksyslog_stats_add_write(&ksyslog_queue, entry->length); 339 } else { 352 340 ksyslog_stats_add_drop(&ksyslog_queue, entry->length); 353 341 ksyslog_drop_warning(entry); 354 call_rcu(&entry->rcu, ksyslog_entry_free);355 342 } 356 spin_unlock_bh(&ksyslog_queue.lock); 343 344 call_rcu(&entry->rcu, ksyslog_entry_free); 357 345 } 358 346 … … 360 348 361 349 out: 362 ksyslog_queue_uninit(&write_queue);363 350 ksyslog_work_register(ksyslog_flush_interval); 364 351 } … … 662 649 #endif 663 650 664 ksyslog_wq = create_ singlethread_workqueue("ksyslog");651 ksyslog_wq = create_workqueue("ksyslog"); 665 652 if (ksyslog_wq == NULL) { 666 653 pr_err("ksyslog: create_workqueue failed\n");
Note: See TracChangeset
for help on using the changeset viewer.