[ftl][logging] Propogate file and line to logging backend

Change-Id: Iede9dd688af8067ecaffd34f95fc9f200fe5c87c
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/455164
Reviewed-by: Gianfranco Valentino <gevalentino@google.com>
Testability-Review: Gianfranco Valentino <gevalentino@google.com>
Testability-Review: Suraj Malhotra <surajmalhotra@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Fuchsia-Auto-Submit: Suraj Malhotra <surajmalhotra@google.com>
diff --git a/src/devices/block/drivers/ftl/nand_driver.cc b/src/devices/block/drivers/ftl/nand_driver.cc
index 77facf3..a66263c 100644
--- a/src/devices/block/drivers/ftl/nand_driver.cc
+++ b/src/devices/block/drivers/ftl/nand_driver.cc
@@ -31,43 +31,38 @@
   return static_cast<uint32_t>(strtoul(value, nullptr, 0));
 }
 
-__PRINTFLIKE(1, 2) void LogTrace(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogTrace(const char* file, int line, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  // TODO: Propogate file and line via caller.
-  zxlogvf(TRACE, __FILE__, __LINE__, format, args);
+  zxlogvf(TRACE, file, line, format, args);
   va_end(args);
 }
 
-__PRINTFLIKE(1, 2) void LogDebug(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogDebug(const char* file, int line, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  // TODO: Propogate file and line via caller.
-  zxlogvf(DEBUG, __FILE__, __LINE__, format, args);
+  zxlogvf(DEBUG, file, line, format, args);
   va_end(args);
 }
 
-__PRINTFLIKE(1, 2) void LogInfo(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogInfo(const char* file, int line, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  // TODO: Propogate file and line via caller.
-  zxlogvf(INFO, __FILE__, __LINE__, format, args);
+  zxlogvf(INFO, file, line, format, args);
   va_end(args);
 }
 
-__PRINTFLIKE(1, 2) void LogWarning(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogWarning(const char* file, int line, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  // TODO: Propogate file and line via caller.
-  zxlogvf(WARNING, __FILE__, __LINE__, format, args);
+  zxlogvf(WARNING, file, line, format, args);
   va_end(args);
 }
 
-__PRINTFLIKE(1, 2) void LogError(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogError(const char* file, int line, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  // TODO: Propogate file and line via caller.
-  zxlogvf(ERROR, __FILE__, __LINE__, format, args);
+  zxlogvf(ERROR, file, line, format, args);
   va_end(args);
 }
 
diff --git a/zircon/system/ulib/ftl/ftl.h b/zircon/system/ulib/ftl/ftl.h
index 778439a..7741d27 100644
--- a/zircon/system/ulib/ftl/ftl.h
+++ b/zircon/system/ulib/ftl/ftl.h
@@ -189,7 +189,7 @@
 typedef struct ndm* NDM;
 typedef const struct ndm* CNDM;
 
-typedef void (*LogFunction)(const char*, ...) __PRINTFLIKE(1, 2);
+typedef void (*LogFunction)(const char*, int, const char*, ...) __PRINTFLIKE(3, 4);
 
 typedef struct {
   // Logger interface for different log levels.
diff --git a/zircon/system/ulib/ftl/ftln/ftln_init.c b/zircon/system/ulib/ftl/ftln/ftln_init.c
index db5c2b1..dd9131d 100644
--- a/zircon/system/ulib/ftl/ftln/ftln_init.c
+++ b/zircon/system/ulib/ftl/ftln/ftln_init.c
@@ -60,13 +60,15 @@
 
       // Verify block is unused and not a map block.
       if (NUM_USED(ftl->bdata[b])) {
-        ftl->logger.error("FTL block %u in erase list is invalid. Block contains %u used pages.", b,
+        ftl->logger.error(__FILE__, __LINE__,
+                          "FTL block %u in erase list is invalid. Block contains %u used pages.", b,
                           NUM_USED(ftl->bdata[b]));
         return NDM_PAGE_INVALID;
       }
 
       if (IS_MAP_BLK(ftl->bdata[b])) {
-        ftl->logger.error("FTL block %u in erase list is invalid. Block is marked as a map block.",
+        ftl->logger.error(__FILE__, __LINE__,
+                          "FTL block %u in erase list is invalid. Block is marked as a map block.",
                           b);
         return NDM_PAGE_INVALID;
       }
@@ -103,7 +105,7 @@
   ++ftl->stats.page_check;
   status = ndmCheckPage(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm);
   if (status < 0) {
-    ftl->logger.error("Failed to check map page at %u page contents.", apn);
+    ftl->logger.error(__FILE__, __LINE__, "Failed to check map page at %u page contents.", apn);
     return FtlnFatErr(ftl);
   }
 
@@ -116,6 +118,7 @@
   mpn = GET_SA_VPN(ftl->spare_buf);
   if (mpn >= ftl->num_map_pgs) {
     ftl->logger.error(
+        __FILE__, __LINE__,
         "Map page at %u page is not valid. Contains %u map page number with a maximum page number "
         "of %u.",
         apn, mpn, ftl->num_map_pgs);
@@ -137,6 +140,7 @@
         for (n = 2; n < ftl->page_size / sizeof(ui32); ++n)
           if (RD32_LE(&ppns[n]) != (ui32)-1) {
             ftl->logger.error(
+                __FILE__, __LINE__,
                 "Found meta page with type |CONT_FORMAT|, but rest of contents where not 0xFF.");
             return NDM_PAGE_INVALID;
           }
@@ -144,7 +148,7 @@
         // If enabled, resume the format.
         if (process)
           if (FtlnFormat(ftl, (apn - ftl->start_pn) / ftl->pgs_per_blk)) {
-            ftl->logger.error("Failed to resume FTL format from meta page.");
+            ftl->logger.error(__FILE__, __LINE__, "Failed to resume FTL format from meta page.");
             return -1;
           }
       }
@@ -166,7 +170,7 @@
             // Verify and apply elist page. Return if page invalid.
             status = proc_elist(ftl);
             if (status != NDM_PAGE_VALID) {
-              ftl->logger.error("Failed to process erase block list.");
+              ftl->logger.error(__FILE__, __LINE__, "Failed to process erase block list.");
               return status;
             }
 
@@ -193,26 +197,28 @@
             ++ftl->stats.page_check;
             status = ndmCheckPage(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm);
             if (status < 0) {
-              ftl->logger.error("Page check at %u failed for map page.", apn);
+              ftl->logger.error(__FILE__, __LINE__, "Page check at %u failed for map page.", apn);
               return FtlnFatErr(ftl);
             }
 
             // If page is erased or invalid, return its status.
             if (status != NDM_PAGE_VALID) {
-              ftl->logger.warning("Erased or Invalid page found in erase block list.");
+              ftl->logger.warning(__FILE__, __LINE__,
+                                  "Erased or Invalid page found in erase block list.");
               return status;
             }
 
             // Verify the metadata version is correct.
             if (RD32_LE(&ppns[0]) != FTLN_META_VER1) {
-              ftl->logger.error("Meta page contains invalid version. Found %u, expected %u.",
+              ftl->logger.error(__FILE__, __LINE__,
+                                "Meta page contains invalid version. Found %u, expected %u.",
                                 *(uint32_t*)(&ppns[0]), FTLN_META_VER1);
               return NDM_PAGE_INVALID;
             }
 
             // Verify the metadata type is correct.
             if (RD32_LE(&ppns[1]) != ERASED_LIST) {
-              ftl->logger.error("Meta page of type |ERASED_LIST|.");
+              ftl->logger.error(__FILE__, __LINE__, "Meta page of type |ERASED_LIST|.");
               return NDM_PAGE_INVALID;
             }
           }
@@ -244,6 +250,7 @@
       // Invalid page if entry is neither valid nor the unmapped value.
       if (pn >= ftl->num_pages && pn != UNMAPPED_PN) {
         ftl->logger.error(
+            __FILE__, __LINE__,
             "Mapped page number %u in map page %u mapping number %u exceeds maximum page number  "
             "%u.",
             pn, apn, n, ftl->num_pages);
@@ -339,8 +346,8 @@
         bc = GET_SA_BC(ftl->spare_buf);
       } else if (bc != GET_SA_BC(ftl->spare_buf)) {
 #if FTLN_DEBUG > 1
-        ftl->logger.debug("build_map: b = %u, po = %u, i_bc = %u vs 0_bc = %u", b, po,
-                          GET_SA_BC(ftl->spare_buf), bc);
+        ftl->logger.debug(__FILE__, __LINE__, "build_map: b = %u, po = %u, i_bc = %u vs 0_bc = %u",
+                          b, po, GET_SA_BC(ftl->spare_buf), bc);
 #endif
 
         // Should not be, but page is invalid. Break to skip block.
@@ -358,8 +365,8 @@
       mpn = GET_SA_VPN(ftl->spare_buf);
       if (mpn > ftl->num_map_pgs) {
 #if FTLN_DEBUG > 1
-        ftl->logger.debug("build_map: b = %u, po = %u, mpn = %u, max = %u", b, po, mpn,
-                          ftl->num_map_pgs);
+        ftl->logger.debug(__FILE__, __LINE__, "build_map: b = %u, po = %u, mpn = %u, max = %u", b,
+                          po, mpn, ftl->num_map_pgs);
 #endif
 
         // Should not be, but page is invalid. Break to skip block.
@@ -386,8 +393,8 @@
           INC_USED(ftl->bdata[b]);
         }
 #if FTLN_DEBUG > 1
-        ftl->logger.debug("build_map: mpn = %u, old_pn = %d, new_pn = %u", mpn, ftl->mpns[mpn],
-                          b * ftl->pgs_per_blk + po);
+        ftl->logger.debug(__FILE__, __LINE__, "build_map: mpn = %u, old_pn = %d, new_pn = %u", mpn,
+                          ftl->mpns[mpn], b * ftl->pgs_per_blk + po);
 #endif
 
         // Save the map page number and (temporarily) the block count.
@@ -418,7 +425,7 @@
       continue;
 
 #if FTLN_DEBUG > 1
-    ftl->logger.debug("  -> MPN[%2u] = %u", mpn, pn);
+    ftl->logger.debug(__FILE__, __LINE__, "  -> MPN[%2u] = %u", mpn, pn);
 #endif
 
     // Read map page. Return -1 if error.
@@ -441,6 +448,7 @@
 
       if (IS_FREE(ftl->bdata[b])) {
         ftl->logger.error(
+            __FILE__, __LINE__,
             "Map Page %u at %u contains maping offset %u mapped to physical %u. But physical block "
             "%u looks free.",
             mpn, map_block, mpn * ftl->mappings_per_mpg + n, pn, b);
@@ -449,6 +457,7 @@
 
       if (IS_MAP_BLK(ftl->bdata[b])) {
         ftl->logger.error(
+            __FILE__, __LINE__,
             "Map Page %u at %u contains maping offset %u mapped to physical %u. But physical block "
             "%u looks like a map block.",
             mpn, map_block, mpn * ftl->mappings_per_mpg + n, pn, b);
@@ -482,8 +491,8 @@
     }
   }
 #if FTLN_DEBUG > 1
-  ftl->logger.debug("volume block %d has lowest used page offset (%d)\n", ftl->resume_vblk,
-                    ftl->resume_po);
+  ftl->logger.debug(__FILE__, __LINE__, "volume block %d has lowest used page offset (%d)\n",
+                    ftl->resume_vblk, ftl->resume_po);
 #endif
 
   // Clean temporary use of vol block read-wear field for page offset.
@@ -558,7 +567,7 @@
     ++ftl->stats.read_spare;
     rc = ndmReadSpare(pn, ftl->spare_buf, ftl->ndm);
     if (rc == -2) {
-      ftl->logger.error("Failed to obtain spare area contents for page %u", pn);
+      ftl->logger.error(__FILE__, __LINE__, "Failed to obtain spare area contents for page %u", pn);
       return FtlnFatErr(ftl);
     }
 
@@ -592,7 +601,8 @@
             ++ftl->stats.read_spare;
             rc = ndmReadSpare(pn + n, ftl->spare_buf, ftl->ndm);
             if (rc == -2) {
-              ftl->logger.error("Failed to obtain spare area contents for page %u", pn);
+              ftl->logger.error(__FILE__, __LINE__,
+                                "Failed to obtain spare area contents for page %u", pn);
               return FtlnFatErr(ftl);
             }
 
@@ -631,7 +641,7 @@
       ++ftl->stats.page_check;
       rc = ndmCheckPage(pn, ftl->main_buf, ftl->spare_buf, ftl->ndm);
       if (rc < 0) {
-        ftl->logger.error("Failed to check physical page %u contents.", pn);
+        ftl->logger.error(__FILE__, __LINE__, "Failed to check physical page %u contents.", pn);
         return FtlnFatErr(ftl);
       }
 
@@ -655,7 +665,8 @@
         ++ftl->stats.read_spare;
         rc = ndmReadSpare(pn + n, ftl->spare_buf, ftl->ndm);
         if (rc == -2) {
-          ftl->logger.error("Failed to read spare data for physical page %u.", pn + n);
+          ftl->logger.error(__FILE__, __LINE__, "Failed to read spare data for physical page %u.",
+                            pn + n);
           return FtlnFatErr(ftl);
         }
         if (rc)
@@ -675,7 +686,8 @@
           ++ftl->stats.page_check;
           rc = ndmCheckPage(pn + n, ftl->main_buf, ftl->spare_buf, ftl->ndm);
           if (rc < 0) {
-            ftl->logger.error("Failed to check page contents for physical page %u.", pn + n);
+            ftl->logger.error(__FILE__, __LINE__,
+                              "Failed to check page contents for physical page %u.", pn + n);
             return FtlnFatErr(ftl);
           }
 
@@ -701,7 +713,8 @@
               filler = "map block.";
             }
 
-            ftl->logger.debug("Resume_vblk=%d bdata=0x%X %s", vb, ftl->bdata[vb], filler);
+            ftl->logger.debug(__FILE__, __LINE__, "Resume_vblk=%d bdata=0x%X %s", vb,
+                              ftl->bdata[vb], filler);
           }
 #endif
 
@@ -716,7 +729,8 @@
       if (!ftl->copy_end_found) {
         // Return if doing a read-only initialization.
         if (ftl->flags & FSF_READ_ONLY_INIT) {
-          ftl->logger.error("FTL format cannot be applied on read only initialization.");
+          ftl->logger.error(__FILE__, __LINE__,
+                            "FTL format cannot be applied on read only initialization.");
           return FsError2(FTL_VOL_BLK_XFR, EINVAL);
         }
 
@@ -732,7 +746,7 @@
       // Check block's first map page for validity. Return -1 if error.
       rc = map_page_check(ftl, pn, FALSE);
       if (rc < 0) {
-        ftl->logger.error("Map page check failed on physical page %u.", pn);
+        ftl->logger.error(__FILE__, __LINE__, "Map page check failed on physical page %u.", pn);
         return -1;
       }
 
@@ -764,7 +778,8 @@
         else if (ftl->high_bc == bc && ftl->high_bc_mblk != (ui32)-1) {
           // Return if doing a read-only initialization.
           if (ftl->flags & FSF_READ_ONLY_INIT) {
-            ftl->logger.error("FTL format cannot be applied on read only initialization.");
+            ftl->logger.error(__FILE__, __LINE__,
+                              "FTL format cannot be applied on read only initialization.");
             return FsError2(FTL_MAP_BLK_XFR, EINVAL);
           }
 
@@ -783,7 +798,7 @@
 
   // If volume is unformatted, return FALSE.
   if (formatted == FALSE) {
-    ftl->logger.info("No FTL Volume found.");
+    ftl->logger.info(__FILE__, __LINE__, "No FTL Volume found.");
     return FALSE;
   }
 
@@ -809,18 +824,19 @@
     ++wear_lag_histogram[ftl->blk_wc_lag[b]];
   }
 
-  ftl->logger.info("Wear Count Range [%u, %u]", low_wc, ftl->high_bc);
-  ftl->logger.info("Wear Count Average %u", ftl->high_bc - avg_lag);
-  ftl->logger.info("Blocks with Wear Count[=%u]: %u", ftl->high_wc - 255,
+  ftl->logger.info(__FILE__, __LINE__, "Wear Count Range [%u, %u]", low_wc, ftl->high_bc);
+  ftl->logger.info(__FILE__, __LINE__, "Wear Count Average %u", ftl->high_bc - avg_lag);
+  ftl->logger.info(__FILE__, __LINE__, "Blocks with Wear Count[=%u]: %u", ftl->high_wc - 255,
                    ftl->wear_data.max_wc_over);
-  ftl->logger.info("Blocks with estimated wear count: %u", set_to_avg);
-  ftl->logger.info("Wear Lag Histogram: ");
+  ftl->logger.info(__FILE__, __LINE__, "Blocks with estimated wear count: %u", set_to_avg);
+  ftl->logger.info(__FILE__, __LINE__, "Wear Lag Histogram: ");
 
   // 8 numbers per row, 5 characters per number = 40;
   char* line_buffer = FsCalloc(1, 40 + 1);
 
   if (line_buffer == NULL) {
-    ftl->logger.error("Failed to allocate memory for FTL histogram line buffer.");
+    ftl->logger.error(__FILE__, __LINE__,
+                      "Failed to allocate memory for FTL histogram line buffer.");
     return -1;
   }
 
@@ -828,7 +844,7 @@
     uint32_t column = i % 8;
     sprintf(line_buffer + 5 * column, "%5u", wear_lag_histogram[255 - i]);
     if (column == 7) {
-      ftl->logger.info(line_buffer);
+      ftl->logger.info(__FILE__, __LINE__, line_buffer);
     }
   }
 
@@ -865,7 +881,8 @@
 
   // Read meta page. check/process its contents. Return -1 if error.
   if (map_page_check(ftl, ftl->start_pn + pn, TRUE) < 0) {
-    ftl->logger.error("FTL map page check failed on meta page at %u.", ftl->start_pn + pn);
+    ftl->logger.error(__FILE__, __LINE__, "FTL map page check failed on meta page at %u.",
+                      ftl->start_pn + pn);
     return -1;
   }
 
@@ -944,7 +961,8 @@
     // Invoke page transfer routine. If error, return -1.
     ++ftl->stats.transfer_page;
     if (ndmTransferPage(src_pg0 + po, dst_pg0 + po, ftl->main_buf, ftl->spare_buf, ftl->ndm)) {
-      ftl->logger.error("FTL failed to transfer page %u to page %u.", src_pg0 + po, dst_pg0 + po);
+      ftl->logger.error(__FILE__, __LINE__, "FTL failed to transfer page %u to page %u.",
+                        src_pg0 + po, dst_pg0 + po);
       return FtlnFatErr(ftl);
     }
   }
@@ -966,7 +984,7 @@
   // Analyze volume to see if it is formatted. Return -1 if error.
   formatted = format_status(ftl);
   if (formatted < 0) {
-    ftl->logger.error("Failed to verify FTL format status.");
+    ftl->logger.error(__FILE__, __LINE__, "Failed to verify FTL format status.");
     return -1;
   }
 
@@ -974,7 +992,7 @@
   if (formatted == FALSE) {
     // Return if doing a read-only initialization.
     if (ftl->flags & FSF_READ_ONLY_INIT) {
-      ftl->logger.error("FTL format aborted on read only initialization.");
+      ftl->logger.error(__FILE__, __LINE__, "FTL format aborted on read only initialization.");
       return FsError2(FTL_NO_MAP_BLKS, EINVAL);
     }
 
@@ -990,7 +1008,7 @@
 
   // Look for all the valid map pages on all the map blocks.
   if (build_map(ftl)) {
-    ftl->logger.error("FTL failed to initialize mapping from media.");
+    ftl->logger.error(__FILE__, __LINE__, "FTL failed to initialize mapping from media.");
     return -1;
   }
 
@@ -1006,7 +1024,7 @@
 
   // Read and process meta page, if any. Return -1 if error.
   if (meta_read(ftl) < 0) {
-    ftl->logger.error("FTL failed to read meta page.");
+    ftl->logger.error(__FILE__, __LINE__, "FTL failed to read meta page.");
     return -1;
   }
 
@@ -1015,13 +1033,13 @@
     if (IS_MAP_BLK(ftl->bdata[b]) && (NUM_USED(ftl->bdata[b]) == 0)) {
       // Return if doing a read-only initialization.
       if (ftl->flags & FSF_READ_ONLY_INIT) {
-        ftl->logger.error("FTL format aborted on read only initialization.");
+        ftl->logger.error(__FILE__, __LINE__, "FTL format aborted on read only initialization.");
         return FsError2(FTL_UNUSED_MBLK, EINVAL);
       }
 
       // Erase unused map block.
       if (FtlnEraseBlk(ftl, b)) {
-        ftl->logger.error("FTL failed to clean up unused map blocks.");
+        ftl->logger.error(__FILE__, __LINE__, "FTL failed to clean up unused map blocks.");
         return -1;
       }
     }
@@ -1035,17 +1053,18 @@
   // interrupted by a power failure, no free blocks are lost.
   if (ftl->num_free_blks < FTLN_MIN_FREE_BLKS) {
 #if DEBUG_RESUME
-    ftl->logger.debug("Resuming: %u free blocks", ftl->num_free_blks);
-    ftl->logger.debug("Map Block %u has used page offset of %u/%u", ftl->high_bc_mblk,
-                      ftl->high_bc_mblk_po, ftl->pgs_per_blk);
-    ftl->logger.debug("vol block %u has used page offset of %u/%u", ftl->resume_vblk,
-                      ftl->resume_po, ftl->pgs_per_blk);
+    ftl->logger.debug(__FILE__, __LINE__, "Resuming: %u free blocks", ftl->num_free_blks);
+    ftl->logger.debug(__FILE__, __LINE__, "Map Block %u has used page offset of %u/%u",
+                      ftl->high_bc_mblk, ftl->high_bc_mblk_po, ftl->pgs_per_blk);
+    ftl->logger.debug(__FILE__, __LINE__, "vol block %u has used page offset of %u/%u",
+                      ftl->resume_vblk, ftl->resume_po, ftl->pgs_per_blk);
 #endif
 
     // Resume needs one free block and should have it.
     PfAssert(ftl->num_free_blks >= 1);
     if (ftl->num_free_blks < 1) {
-      ftl->logger.error("FTL initialization aborted due to lack of free blocks.");
+      ftl->logger.error(__FILE__, __LINE__,
+                        "FTL initialization aborted due to lack of free blocks.");
       return -1;
     }
 
@@ -1057,7 +1076,7 @@
 
       // Return if doing a read-only initialization.
       if (ftl->flags & FSF_READ_ONLY_INIT) {
-        ftl->logger.error("FTL format aborted on read only initialization.");
+        ftl->logger.error(__FILE__, __LINE__, "FTL format aborted on read only initialization.");
         return FsError2(FTL_VBLK_RESUME, EINVAL);
       }
 
@@ -1076,7 +1095,8 @@
         // Find free block w/highest wear count. Error if none free.
         b = FtlnHiWcFreeBlk(ftl);
         if (b == (ui32)-1) {
-          ftl->logger.error("FTL did not find any free blocks with high wear count.");
+          ftl->logger.error(__FILE__, __LINE__,
+                            "FTL did not find any free blocks with high wear count.");
           return -1;
         }
 
@@ -1091,14 +1111,15 @@
 
         // Copy used pages to temp block.
         if (resume_copy(ftl, ftl->resume_vblk, b, COPY_BLK_MARK)) {
-          ftl->logger.error("FTL failed to resume copy of block %u to temp block %u.",
+          ftl->logger.error(__FILE__, __LINE__,
+                            "FTL failed to resume copy of block %u to temp block %u.",
                             ftl->resume_vblk, b);
           return -1;
         }
 
         // Write "end of copy" mark on next temp block page.
         if (copy_end_mark(ftl, b)) {
-          ftl->logger.error("FTL failed write copy end mark at block %u.", b);
+          ftl->logger.error(__FILE__, __LINE__, "FTL failed write copy end mark at block %u.", b);
           return -1;
         }
       }
@@ -1110,7 +1131,8 @@
 
       // Copy the temp block's contents back to the volume block.
       if (resume_copy(ftl, b, ftl->resume_vblk, 0xFFFFFFFF)) {
-        ftl->logger.error("FTL failed to copy from temp block %u to final block %u.", b,
+        ftl->logger.error(__FILE__, __LINE__,
+                          "FTL failed to copy from temp block %u to final block %u.", b,
                           ftl->resume_vblk);
         return -1;
       }
@@ -1135,21 +1157,22 @@
 
       // Return if doing a read-only initialization.
       if (ftl->flags & FSF_READ_ONLY_INIT) {
-        ftl->logger.error("FTL format aborted on read only initialization.");
+        ftl->logger.error(__FILE__, __LINE__, "FTL format aborted on read only initialization.");
         return FsError2(FTL_MBLK_RESUME, EINVAL);
       }
 
       // Find free block with lowest wear count. Error if none free.
       b = FtlnLoWcFreeBlk(ftl);
       if (b == (ui32)-1) {
-        ftl->logger.error("FTL did not find any free blocks with low wear count.");
+        ftl->logger.error(__FILE__, __LINE__,
+                          "FTL did not find any free blocks with low wear count.");
         return -1;
       }
 
       // If the block is unerased, erase it now. Return -1 if error.
       if ((ftl->bdata[b] & ERASED_BLK_FLAG) == 0)
         if (FtlnEraseBlk(ftl, b)) {
-          ftl->logger.error("FTL failed to erase free block at %u.", b);
+          ftl->logger.error(__FILE__, __LINE__, "FTL failed to erase free block at %u.", b);
           return -1;
         }
 
@@ -1172,7 +1195,8 @@
 
       // Copy the used pages to a free block, then erase the original.
       if (FtlnRecycleMapBlk(ftl, ftl->high_bc_mblk)) {
-        ftl->logger.error("FTL failed to recycle block at %u to free up unused pages.",
+        ftl->logger.error(__FILE__, __LINE__,
+                          "FTL failed to recycle block at %u to free up unused pages.",
                           ftl->high_bc_mblk);
         return -1;
       }
@@ -1181,6 +1205,7 @@
 
 #if FTLN_DEBUG > 1
   ftl->logger.debug(
+      __FILE__, __LINE__,
       "FTL formatted successfully. [Current Generation Number = %u  Highest Wear Count = %u",
       ftl->high_bc, ftl->high_wc);
 #endif
@@ -1265,14 +1290,16 @@
 
   // If number of blocks less than 7, FTL-NDM cannot work.
   if (ftl_cfg->num_blocks < 7) {
-    ftl_cfg->logger.error("Invalid Arguments. FTL requires at least 7 blocks to work.");
+    ftl_cfg->logger.error(__FILE__, __LINE__,
+                          "Invalid Arguments. FTL requires at least 7 blocks to work.");
     FsError2(FTL_CFG_ERR, EINVAL);
     return NULL;
   }
 
   // Ensure FTL flags are valid.
   if (ftl_cfg->flags & ~(FSF_EXTRA_FREE | FSF_READ_WEAR_LIMIT | FSF_READ_ONLY_INIT)) {
-    ftl_cfg->logger.error("Invalid Arguments. FTL config contains unknown flags.");
+    ftl_cfg->logger.error(__FILE__, __LINE__,
+                          "Invalid Arguments. FTL config contains unknown flags.");
     FsError2(FTL_CFG_ERR, EINVAL);
     return NULL;
   }
@@ -1280,7 +1307,8 @@
 #if CACHE_LINE_SIZE
   // Ensure driver page size is a multiple of the CPU cache line size.
   if (ftl_cfg->page_size % CACHE_LINE_SIZE) {
-    ftl_cfg->logger.error("Invalid Arguments. Page size is not a multiple of the cache line size.");
+    ftl_cfg->logger.error(__FILE__, __LINE__,
+                          "Invalid Arguments. Page size is not a multiple of the cache line size.");
     FsError2(FTL_CFG_ERR, EINVAL);
     return NULL;
   }
@@ -1291,6 +1319,7 @@
   if (ftl_cfg->page_size % 512 || ftl_cfg->page_size == 0 ||
       ftl_cfg->page_size > ftl_cfg->block_size) {
     ftl_cfg->logger.error(
+        __FILE__, __LINE__,
         "Invalid Arguments. Page size must a multiple of 512 and not bigger than the device block "
         "size.");
     FsError2(FTL_CFG_ERR, EINVAL);
@@ -1300,7 +1329,8 @@
   // Allocate memory for FTL control block. Return NULL if unable.
   ftl = FsCalloc(1, sizeof(struct ftln));
   if (ftl == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     FsError2(FTL_ENOMEM, ENOMEM);
     return NULL;
   }
@@ -1323,7 +1353,8 @@
 
   // Ensure pages per block doesn't exceed allotted metadata field width.
   if (ftl->pgs_per_blk > PGS_PER_BLK_MAX) {
-    ftl->logger.error("Pages per block exceed maximum allowed. Expected at most %u, found %u.",
+    ftl->logger.error(__FILE__, __LINE__,
+                      "Pages per block exceed maximum allowed. Expected at most %u, found %u.",
                       PGS_PER_BLK_MAX, ftl->pgs_per_blk);
     FsError2(FTL_CFG_ERR, EINVAL);
     goto FtlnAddV_err;
@@ -1332,7 +1363,8 @@
 #if !FTLN_LEGACY && FTLN_3B_PN
   // Verify number of pages doesn't exceed 3B field width.
   if (ftl->num_pages > 0x1000000) {
-    ftl->logger.error("Pages exceed maximum allowed. Expected at most %u, found %u.", 0x10000000,
+    ftl->logger.error(__FILE__, __LINE__,
+                      "Pages exceed maximum allowed. Expected at most %u, found %u.", 0x10000000,
                       ftl->num_pages);
     FsError2(FTL_CFG_ERR, EINVAL);
     goto FtlnAddV_err;
@@ -1421,8 +1453,8 @@
   PfAssert(ftl->num_vpages / ftl->mappings_per_mpg < ftl->num_map_pgs);
 
 #if FTLN_DEBUG > 1
-  ftl->logger.debug("Volume Pages = %u. FTL pages = %u. %u%% usage", ftl->num_vpages,
-                    ftl->num_pages, (ftl->num_vpages * 100) / ftl->num_pages);
+  ftl->logger.debug(__FILE__, __LINE__, "Volume Pages = %u. FTL pages = %u. %u%% usage",
+                    ftl->num_vpages, ftl->num_pages, (ftl->num_vpages * 100) / ftl->num_pages);
 #endif
 
   // Allocate one or two main data pages and spare buffers. Max spare
@@ -1430,7 +1462,8 @@
   n = ftl->page_size + ftl->eb_size * ftl->pgs_per_blk;
   buf = FsAalloc(n);
   if (buf == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     FsError2(FTL_ENOMEM, ENOMEM);
     goto FtlnAddV_err;
   }
@@ -1440,13 +1473,15 @@
   // Allocate memory for the block data and wear count lag arrays.
   ftl->bdata = FsCalloc(ftl->num_blks, sizeof(ui32));
   if (ftl->bdata == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     FsError2(FTL_ENOMEM, ENOMEM);
     goto FtlnAddV_err;
   }
   ftl->blk_wc_lag = FsCalloc(ftl->num_blks, sizeof(ui8));
   if (ftl->blk_wc_lag == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     FsError2(FTL_ENOMEM, ENOMEM);
     goto FtlnAddV_err;
   }
@@ -1455,7 +1490,8 @@
   // Allocate memory for map pages array (holds physical page numbers).
   ftl->mpns = FsMalloc(ftl->num_map_pgs * sizeof(ui32));
   if (ftl->mpns == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     FsError2(FTL_ENOMEM, ENOMEM);
     goto FtlnAddV_err;
   }
@@ -1475,7 +1511,8 @@
   // Allocate map page cache for new volume.
   ftl->map_cache = ftlmcNew(ftl, ftl_cfg->cached_map_pages, FtlnMapWr, rd_map_pg, ftl->page_size);
   if (ftl->map_cache == NULL) {
-    ftl_cfg->logger.error("Failed to allocated memory for FTL at %s:%d", __FILE_NAME__, __LINE__);
+    ftl_cfg->logger.error(__FILE__, __LINE__, "Failed to allocated memory for FTL at %s:%d",
+                          __FILE_NAME__, __LINE__);
     goto FtlnAddV_err;
   }
 
@@ -1491,6 +1528,7 @@
   }
   if (ftl->max_rc > RC_MASK) {
     ftl->logger.error(
+        __FILE__, __LINE__,
         "Maximum read count in volume, exceeds max supported value. Expected %u found %u.", RC_MASK,
         ftl->max_rc);
     FsError2(FTL_CFG_ERR, EINVAL);
@@ -1530,7 +1568,7 @@
   xfs->vol = ftl;
 
 #if FTLN_DEBUG > 1
-  ftl->logger.debug("[XFS] num_pages       = %u\n\n", xfs->num_pages);
+  ftl->logger.debug(__FILE__, __LINE__, "[XFS] num_pages       = %u\n\n", xfs->num_pages);
 #endif
 
   // Register FTL volume with user.
@@ -1560,7 +1598,7 @@
 //     Returns: 0 if success, -1 if error
 //
 int FtlnDelVol(FTLN ftl) {
-  ftl->logger.debug("Deleting FTL volume.");
+  ftl->logger.debug(__FILE__, __LINE__, "Deleting FTL volume.");
   // Remove volume from list of volumes.
   CIRC_NODE_REMOVE(&ftl->link);
   // Delete FTL and return success.
diff --git a/zircon/system/ulib/ftl/ftln/ftln_intrnl.c b/zircon/system/ulib/ftl/ftln/ftln_intrnl.c
index e3bdc2e..8d6646d 100644
--- a/zircon/system/ulib/ftl/ftln/ftln_intrnl.c
+++ b/zircon/system/ulib/ftl/ftln/ftln_intrnl.c
@@ -270,7 +270,8 @@
   // If list of erased blocks/wear counts exists, erase it now.
   if (ftl->elist_blk != (ui32)-1)
     if (FtlnEraseBlk(ftl, ftl->elist_blk)) {
-      ftl->logger.error("Failed to erase block list at block %u.", ftl->elist_blk);
+      ftl->logger.error(__FILE__, __LINE__, "Failed to erase block list at block %u.",
+                        ftl->elist_blk);
       return -1;
     }
 #endif
@@ -278,7 +279,7 @@
   // Allocate next free volume page. Return -1 if error.
   ppn = next_free_vpg(ftl);
   if (ppn == (ui32)-1) {
-    ftl->logger.error("Failed to allocate a volume page.");
+    ftl->logger.error(__FILE__, __LINE__, "Failed to allocate a volume page.");
     return -1;
   }
 
@@ -306,7 +307,8 @@
 
   // Return -1 for any error. Any write error is fatal.
   if (rc) {
-    ftl->logger.error("Failed to write volume page %u at %u.", vpn, ftl->start_pn + ppn);
+    ftl->logger.error(__FILE__, __LINE__, "Failed to write volume page %u at %u.", vpn,
+                      ftl->start_pn + ppn);
     return FtlnFatErr(ftl);
   }
 
@@ -604,7 +606,8 @@
     // Return -1 if fatal error, skip page if ECC error on spare read.
     if (rc) {
       if (rc == -2) {
-        ftl->logger.error("Failed to read spare area from block %u.", recycle_b);
+        ftl->logger.error(__FILE__, __LINE__, "Failed to read spare area from block %u.",
+                          recycle_b);
         return FtlnFatErr(ftl);
       } else
         continue;
@@ -625,14 +628,15 @@
 
     // Write page to new flash block. Return -1 if error.
     if (wr_vol_page(ftl, vpn, NULL, pn)) {
-      ftl->logger.error("Failed to transfer page %u to physical page %u.", vpn, pn);
+      ftl->logger.error(__FILE__, __LINE__, "Failed to transfer page %u to physical page %u.", vpn,
+                        pn);
       return -1;
     }
   }
 
   // Save MPGs modified by volume page transfers. Return -1 if error.
   if (ftlmcFlushMap(ftl->map_cache)) {
-    ftl->logger.error("Failed to flush map cache.");
+    ftl->logger.error(__FILE__, __LINE__, "Failed to flush map cache.");
     return -1;
   }
 
@@ -716,7 +720,7 @@
   ftl->stats.write_page += staged->cnt;
   if (ndmWritePages(ftl->start_pn + staged->ppn0, staged->cnt, staged->buf, ftl->spare_buf,
                     ftl->ndm)) {
-    ftl->logger.error("Failed to stage writes.");
+    ftl->logger.error(__FILE__, __LINE__, "Failed to stage writes.");
     return FtlnFatErr(ftl);
   }
 
@@ -998,7 +1002,7 @@
   // Issue meta page write.
   int result = FtlnMapWr(ftl, ftl->num_map_pgs - 1, ftl->main_buf);
   if (result < 0) {
-    ftl->logger.error("FTL failed to write meta map page.");
+    ftl->logger.error(__FILE__, __LINE__, "FTL failed to write meta map page.");
   }
   return result;
 }
diff --git a/zircon/system/ulib/ftl/ftln/ftln_rd.c b/zircon/system/ulib/ftl/ftln/ftln_rd.c
index c6998f9..a2434f9 100644
--- a/zircon/system/ulib/ftl/ftln/ftln_rd.c
+++ b/zircon/system/ulib/ftl/ftln/ftln_rd.c
@@ -73,7 +73,7 @@
 
   // Ensure request is within volume's range of provided pages.
   if (vpn + count > ftl->num_vpages) {
-    ftl->logger.error("FTL Read failed. Attempting to read page %u is out of range(max %u).",
+    ftl->logger.error(__FILE__, __LINE__, "FTL Read failed. Attempting to read page %u is out of range(max %u).",
                       vpn + count - 1, ftl->num_pages - 1);
     return FsError2(FTL_ASSERT, ENOSPC);
   }
@@ -85,7 +85,7 @@
   // If there's at least a block with a maximum read count, recycle.
   if (ftl->max_rc_blk != (ui32)-1)
     if (FtlnRecCheck(ftl, 0)) {
-      ftl->logger.error("FTL read recycle failed for page %u.");
+      ftl->logger.error(__FILE__, __LINE__, "FTL read recycle failed for page %u.");
       return -1;
     }
 
@@ -116,13 +116,13 @@
 
     // Prepare to potentially write one map page. Return -1 if error.
     if (FtlnRecCheck(ftl, -1)) {
-      ftl->logger.error("Failed to obtain free pages through block recycling.");
+      ftl->logger.error(__FILE__, __LINE__, "Failed to obtain free pages through block recycling.");
       return -1;
     }
 
     // Convert the virtual page number to its physical page number.
     if (FtlnMapGetPpn(ftl, vpn, &ppn) < 0) {
-      ftl->logger.error("Failed to obtain map physical page number.");
+      ftl->logger.error(__FILE__, __LINE__, "Failed to obtain map physical page number.");
       return -1;
     }
 
diff --git a/zircon/system/ulib/ftl/ftln/ftln_util.c b/zircon/system/ulib/ftl/ftln/ftln_util.c
index 53197f1..f6ea88c 100644
--- a/zircon/system/ulib/ftl/ftln/ftln_util.c
+++ b/zircon/system/ulib/ftl/ftln/ftln_util.c
@@ -125,7 +125,7 @@
     case FS_FORMAT_RESET_WC: {
       // Format volume. Return -1 if error.
       if (format_ftl(ftl)) {
-        ftl->logger.error("FTL format failed.");
+        ftl->logger.error(__FILE__, __LINE__, "FTL format failed.");
         return -1;
       }
 
@@ -477,7 +477,7 @@
   // Call driver to erase block. Return -1 if error.
   ++ftl->stats.erase_block;
   if (ndmEraseBlock(ftl->start_pn + b * ftl->pgs_per_blk, ftl->ndm)) {
-    ftl->logger.error("FTL failed to erase block %u.", ftl->start_pn / ftl->pgs_per_blk + b);
+    ftl->logger.error(__FILE__, __LINE__, "FTL failed to erase block %u.", ftl->start_pn / ftl->pgs_per_blk + b);
     return FtlnFatErr(ftl);
   }
 
diff --git a/zircon/system/ulib/ftl/ftln/ndm-driver.cc b/zircon/system/ulib/ftl/ftln/ndm-driver.cc
index 38eb943..ddc1609 100644
--- a/zircon/system/ulib/ftl/ftln/ndm-driver.cc
+++ b/zircon/system/ulib/ftl/ftln/ndm-driver.cc
@@ -142,7 +142,7 @@
   return kNdmOk;
 }
 
-__PRINTFLIKE(1, 2) void LogTrace(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogTrace(const char* file, int line, const char* format, ...) {
   fprintf(stderr, "[FTL] TRACE: ");
   va_list args;
   va_start(args, format);
@@ -151,7 +151,7 @@
   fprintf(stderr, "\n");
 }
 
-__PRINTFLIKE(1, 2) void LogDebug(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogDebug(const char* file, int line, const char* format, ...) {
   fprintf(stderr, "[FTL] DEBUG: ");
   va_list args;
   va_start(args, format);
@@ -160,7 +160,7 @@
   fprintf(stderr, "\n");
 }
 
-__PRINTFLIKE(1, 2) void LogInfo(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogInfo(const char* file, int line, const char* format, ...) {
   fprintf(stderr, "[FTL] INFO: ");
   va_list args;
   va_start(args, format);
@@ -169,7 +169,7 @@
   fprintf(stderr, "\n");
 }
 
-__PRINTFLIKE(1, 2) void LogWarning(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogWarning(const char* file, int line, const char* format, ...) {
   fprintf(stderr, "[FTL] WARNING: ");
   va_list args;
   va_start(args, format);
@@ -178,7 +178,7 @@
   fprintf(stderr, "\n");
 }
 
-__PRINTFLIKE(1, 2) void LogError(const char* format, ...) {
+__PRINTFLIKE(3, 4) void LogError(const char* file, int line, const char* format, ...) {
   fprintf(stderr, "[FTL] ERROR: ");
   va_list args;
   va_start(args, format);
diff --git a/zircon/system/ulib/ftl/include/lib/ftl/ndm-driver.h b/zircon/system/ulib/ftl/include/lib/ftl/ndm-driver.h
index 395d515..1d0d12a 100644
--- a/zircon/system/ulib/ftl/include/lib/ftl/ndm-driver.h
+++ b/zircon/system/ulib/ftl/include/lib/ftl/ndm-driver.h
@@ -42,11 +42,11 @@
 
 // Helper for overriding default logging routines.
 struct LoggerProxy {
-  __PRINTFLIKE(1, 2) void (*trace)(const char*, ...) = nullptr;
-  __PRINTFLIKE(1, 2) void (*debug)(const char*, ...) = nullptr;
-  __PRINTFLIKE(1, 2) void (*info)(const char*, ...) = nullptr;
-  __PRINTFLIKE(1, 2) void (*warn)(const char*, ...) = nullptr;
-  __PRINTFLIKE(1, 2) void (*error)(const char*, ...) = nullptr;
+  __PRINTFLIKE(3, 4) void (*trace)(const char*, int, const char*, ...) = nullptr;
+  __PRINTFLIKE(3, 4) void (*debug)(const char*, int, const char*, ...) = nullptr;
+  __PRINTFLIKE(3, 4) void (*info)(const char*, int, const char*, ...) = nullptr;
+  __PRINTFLIKE(3, 4) void (*warn)(const char*, int, const char*, ...) = nullptr;
+  __PRINTFLIKE(3, 4) void (*error)(const char*, int, const char*, ...) = nullptr;
 };
 
 // Encapsulates the lower layer TargetFtl-Ndm driver.
diff --git a/zircon/system/ulib/ftl/ndm/ndm_init.c b/zircon/system/ulib/ftl/ndm/ndm_init.c
index effeecf..2932960 100644
--- a/zircon/system/ulib/ftl/ndm/ndm_init.c
+++ b/zircon/system/ulib/ftl/ndm/ndm_init.c
@@ -127,7 +127,7 @@
       // If control info found, device is formatted. Return TRUE.
       if (status == NDM_CTRL_BLOCK) {
 #if NDM_DEBUG
-        ndm->logger.debug("NDM formatted - block #%u has control info!", b);
+        ndm->logger.debug(__FILE__, __LINE__, "NDM formatted - block #%u has control info!", b);
 #endif
         PfAssert(ndm->ctrl_blk0 == (ui32)-1);
         ndm->ctrl_blk0 = b;
@@ -227,8 +227,8 @@
       // Add block to initial bad blocks array and increment bad count.
       ndm->init_bad_blk[ndm->num_bad_blks] = b;
 #if NDM_DEBUG
-      ndm->logger.debug("init_ibad_lis: adding block #%u to init_bad_blk[%u]", b,
-                        ndm->num_bad_blks);
+      ndm->logger.debug(__FILE__, __LINE__, "init_ibad_lis: adding block #%u to init_bad_blk[%u]",
+                        b, ndm->num_bad_blks);
 #endif
       ++ndm->num_bad_blks;
     }
@@ -237,8 +237,8 @@
   // Set the last initial bad block entry to the device block count.
   ndm->init_bad_blk[ndm->num_bad_blks] = ndm->num_dev_blks;
 #if NDM_DEBUG
-  ndm->logger.debug("init_ibad_lis: LAST init_bad_blk[%u] = %u", ndm->num_bad_blks,
-                    ndm->num_dev_blks);
+  ndm->logger.debug(__FILE__, __LINE__, "init_ibad_lis: LAST init_bad_blk[%u] = %u",
+                    ndm->num_bad_blks, ndm->num_dev_blks);
 #endif
 
   // Return success.
@@ -287,7 +287,8 @@
   if (ndm->ctrl_blk1 == (ui32)-1)
     return FsError2(NDM_NO_FREE_BLK, ENOSPC);
 #if NDM_DEBUG
-  ndm->logger.debug("NDM ctrl_blk0=%u, ctrl_blk1=%u", ndm->ctrl_blk0, ndm->ctrl_blk1);
+  ndm->logger.debug(__FILE__, __LINE__, "NDM ctrl_blk0=%u, ctrl_blk1=%u", ndm->ctrl_blk0,
+                    ndm->ctrl_blk1);
 #endif
 
   // Begin the first control write on ctrl_blk0.
@@ -401,10 +402,10 @@
           last_ctrl_p = p;
           ctrl_pages = last_p;
 #if NDM_DEBUG
-          ndm->logger.debug(
-              "find_ctrl: seq #%u, last = %u (block = %u), "
-              "# pages = %u",
-              high_seq, last_ctrl_p, last_ctrl_p / ndm->pgs_per_blk, ctrl_pages);
+          ndm->logger.debug(__FILE__, __LINE__,
+                            "find_ctrl: seq #%u, last = %u (block = %u), "
+                            "# pages = %u",
+                            high_seq, last_ctrl_p, last_ctrl_p / ndm->pgs_per_blk, ctrl_pages);
 #endif
         }
 
@@ -445,7 +446,8 @@
 
     if (curr_p == 1 && curr_seq == high_seq && last_p == ctrl_pages) {
 #if NDM_DEBUG
-      ndm->logger.debug("find_ctrl: first = %u (block = %u)", p, p / ndm->pgs_per_blk);
+      ndm->logger.debug(__FILE__, __LINE__, "find_ctrl: first = %u (block = %u)", p,
+                        p / ndm->pgs_per_blk);
 #endif
       ndm->frst_ctrl_page = p;
       return 0;
@@ -477,7 +479,8 @@
 
       if (curr_p == 1 && curr_seq == high_seq && last_p == ctrl_pages) {
 #if NDM_DEBUG
-        ndm->logger.debug("find_ctrl: first = %u (block = %u)", p, p / ndm->pgs_per_blk);
+        ndm->logger.debug(__FILE__, __LINE__, "find_ctrl: first = %u (block = %u)", p,
+                          p / ndm->pgs_per_blk);
 #endif
         ndm->frst_ctrl_page = p;
         return 0;
@@ -612,7 +615,7 @@
       return FsError2(NDM_EIO, EIO);
 
 #if NDM_DEBUG
-    ndm->logger.debug("read_ctrl: READ page #%u", *pn);
+    ndm->logger.debug(__FILE__, __LINE__, "read_ctrl: READ page #%u", *pn);
 #endif
   }
 
@@ -641,7 +644,7 @@
   if (ndm->read_page(p, ndm->main_buf, ndm->spare_buf, ndm->dev) < 0)
     return FsError2(NDM_EIO, EIO);
 #if NDM_DEBUG
-  ndm->logger.debug("read_ctrl: READ page #%u", p);
+  ndm->logger.debug(__FILE__, __LINE__, "read_ctrl: READ page #%u", p);
 #endif
 
   // Ensure the number of blocks and block size are correct.
@@ -667,12 +670,12 @@
   curr_loc += sizeof(ui32);
 
 #if NDM_DEBUG
-  ndm->logger.debug("read_ctrl info:");
-  ndm->logger.debug("  -> ctrl_seq    = %u", ndm->ctrl_seq);
-  ndm->logger.debug("  -> ctrl_blk0   = %u", ndm->ctrl_blk0);
-  ndm->logger.debug("  -> ctrl_blk1   = %u", ndm->ctrl_blk1);
-  ndm->logger.debug("  -> free_virt_blk = %u", ndm->free_virt_blk);
-  ndm->logger.debug("  -> free_ctrl_blk = %u", ndm->free_ctrl_blk);
+  ndm->logger.debug(__FILE__, __LINE__, "read_ctrl info:");
+  ndm->logger.debug(__FILE__, __LINE__, "  -> ctrl_seq    = %u", ndm->ctrl_seq);
+  ndm->logger.debug(__FILE__, __LINE__, "  -> ctrl_blk0   = %u", ndm->ctrl_blk0);
+  ndm->logger.debug(__FILE__, __LINE__, "  -> ctrl_blk1   = %u", ndm->ctrl_blk1);
+  ndm->logger.debug(__FILE__, __LINE__, "  -> free_virt_blk = %u", ndm->free_virt_blk);
+  ndm->logger.debug(__FILE__, __LINE__, "  -> free_ctrl_blk = %u", ndm->free_ctrl_blk);
 #endif
 
   // Retrieve the transfer to block (if any).
@@ -700,15 +703,15 @@
     }
 
 #if NDM_DEBUG
-    ndm->logger.debug("  -> xfr_tblk       = %u", ndm->xfr_tblk);
-    ndm->logger.debug("  -> xfr_fblk       = %u", ndm->xfr_fblk);
-    ndm->logger.debug("  -> xfr_bad_po     = %u", ndm->xfr_bad_po);
+    ndm->logger.debug(__FILE__, __LINE__, "  -> xfr_tblk       = %u", ndm->xfr_tblk);
+    ndm->logger.debug(__FILE__, __LINE__, "  -> xfr_fblk       = %u", ndm->xfr_fblk);
+    ndm->logger.debug(__FILE__, __LINE__, "  -> xfr_bad_po     = %u", ndm->xfr_bad_po);
 #endif
   }
 
 #if NDM_DEBUG
   if (ndm->xfr_tblk == (ui32)-1) {
-    ndm->logger.debug("  -> xfr_tblk       = -1");
+    ndm->logger.debug(__FILE__, __LINE__, "  -> xfr_tblk       = -1");
   }
 #endif
 
@@ -716,8 +719,8 @@
   ndm->num_partitions = RD32_LE(&ndm->main_buf[curr_loc]);
   curr_loc += sizeof(ui32);
 #if NDM_DEBUG
-  ndm->logger.debug("  -> num_partitions = %u", ndm->num_partitions);
-  ndm->logger.debug("read_ctrl: init_bad_blk[]");
+  ndm->logger.debug(__FILE__, __LINE__, "  -> num_partitions = %u", ndm->num_partitions);
+  ndm->logger.debug(__FILE__, __LINE__, "read_ctrl: init_bad_blk[]");
 #endif
 
   // Retrieve the initial bad blocks map.
@@ -735,7 +738,7 @@
     curr_loc += sizeof(ui32);
 
 #if NDM_DEBUG
-    ndm->logger.debug("    [%u] = %u", i, bn);
+    ndm->logger.debug(__FILE__, __LINE__, "    [%u] = %u", i, bn);
 #endif
 
     // Store block in initial bad block map and check for end of map.
@@ -748,7 +751,7 @@
   }
 
 #if NDM_DEBUG
-  ndm->logger.debug("read_ctrl: run_bad_blk[]");
+  ndm->logger.debug(__FILE__, __LINE__, "read_ctrl: run_bad_blk[]");
 #endif
 
   // Retrieve running bad blocks map.
@@ -776,7 +779,7 @@
     ndm->run_bad_blk[ndm->num_rbb].val = bn;
 
 #if NDM_DEBUG
-    ndm->logger.debug("    [%u] key = %u, val = %u\n", ndm->num_rbb, vbn, bn);
+    ndm->logger.debug(__FILE__, __LINE__, "    [%u] key = %u, val = %u\n", ndm->num_rbb, vbn, bn);
 #endif
 
     // Adjust running count of bad blocks to account for this one.
@@ -801,7 +804,7 @@
       return -1;
 
 #if NDM_DEBUG
-    ndm->logger.debug("read_ctrl: partitions[]");
+    ndm->logger.debug(__FILE__, __LINE__, "read_ctrl: partitions[]");
 #endif
 
     // Read partitions from the control information one at a time.
@@ -850,13 +853,15 @@
       }
 
 #if NDM_DEBUG
-      ndm->logger.debug(" partition[%2u]:", i);
-      ndm->logger.debug("   - name        = %s", ndm->partitions[i].name);
-      ndm->logger.debug("   - first block = %u", ndm->partitions[i].first_block);
-      ndm->logger.debug("   - num blocks  = %u", ndm->partitions[i].num_blocks);
+      ndm->logger.debug(__FILE__, __LINE__, " partition[%2u]:", i);
+      ndm->logger.debug(__FILE__, __LINE__, "   - name        = %s", ndm->partitions[i].name);
+      ndm->logger.debug(__FILE__, __LINE__, "   - first block = %u",
+                        ndm->partitions[i].first_block);
+      ndm->logger.debug(__FILE__, __LINE__, "   - num blocks  = %u", ndm->partitions[i].num_blocks);
 #if NDM_PART_USER
       for (j = 0; j < NDM_PART_USER; ++j)
-        ndm->logger.debug("   - user[%u]     = %u", j, ndm->partitions[i].user[j]);
+        ndm->logger.debug(__FILE__, __LINE__, "   - user[%u]     = %u", j,
+                          ndm->partitions[i].user[j]);
 #endif
 #endif  // NDM_DEBUG
     }
@@ -883,28 +888,32 @@
 
   // Ensure the 'transfer from' block value is valid.
   if (ndm->xfr_fblk >= ndm->num_dev_blks) {
-    ndm->logger.error("Failed to recover NDM Bad Block. Invalid |transfer_from| block %u.",
+    ndm->logger.error(__FILE__, __LINE__,
+                      "Failed to recover NDM Bad Block. Invalid |transfer_from| block %u.",
                       ndm->xfr_fblk);
     return FsError2(NDM_BAD_META_DATA, EINVAL);
   }
 
   // Ensure the 'transfer to' block value is valid.
   if (ndm->xfr_tblk < ndm->frst_reserved || ndm->xfr_tblk >= ndm->free_virt_blk) {
-    ndm->logger.error("Failed to recover NDM Bad Block. Invalid |transfer_to| block %u.",
+    ndm->logger.error(__FILE__, __LINE__,
+                      "Failed to recover NDM Bad Block. Invalid |transfer_to| block %u.",
                       ndm->xfr_tblk);
     return FsError2(NDM_BAD_META_DATA, EINVAL);
   }
 
   // Return error if doing a read-only initialization.
   if (ndm->flags & FSF_READ_ONLY_INIT) {
-    ndm->logger.error("Failed to recover NDM Bad Block. NDM in read-only mode.");
+    ndm->logger.error(__FILE__, __LINE__,
+                      "Failed to recover NDM Bad Block. NDM in read-only mode.");
     return FsError2(NDM_BAD_BLK_RECOV, EINVAL);
   }
 
   // Erase the 'transfer to' block. Return if fatal error.
   rc = ndm->erase_block(ndm->xfr_tblk * ndm->pgs_per_blk, ndm->dev);
   if (rc == -2) {
-    ndm->logger.error("Failed to recover NDM Bad Block. Failed to erase |transfer_to_block|.");
+    ndm->logger.error(__FILE__, __LINE__,
+                      "Failed to recover NDM Bad Block. Failed to erase |transfer_to_block|.");
     return FsError2(NDM_EIO, EIO);
   }
 
@@ -917,9 +926,9 @@
     // Find running list entry with this 'transfer from/to' block pair.
     for (i = 0;; ++i) {
       if (i == ndm->num_rbb) {
-        ndm->logger.error(
-            "Failed to recover NDM Bad Block. Failed to obtain run bad block for "
-            "|transfer_to/from| block.");
+        ndm->logger.error(__FILE__, __LINE__,
+                          "Failed to recover NDM Bad Block. Failed to obtain run bad block for "
+                          "|transfer_to/from| block.");
         return FsError2(NDM_ASSERT, EINVAL);
       }
       if (ndm->run_bad_blk[i].key == ndm->xfr_fblk && ndm->run_bad_blk[i].val == ndm->xfr_tblk)
@@ -963,11 +972,11 @@
 
   // See if device is formatted with NDM metadata. Check for error.
   if (format_status(ndm) != 0) {
-    ndm->logger.info("No NDM control block found.");
+    ndm->logger.info(__FILE__, __LINE__, "No NDM control block found.");
     // If no metadata was found and initialization is not being done
     // in read-only mode, format the device. Else return -1.
     if ((GetFsErrCode() == NDM_NO_META_BLK) && FLAG_IS_CLR(ndm->flags, FSF_READ_ONLY_INIT)) {
-      ndm->logger.info("No meta block found. Initializing NDM Volume.");
+      ndm->logger.info(__FILE__, __LINE__, "No meta block found. Initializing NDM Volume.");
       return ndm_format(ndm);
     }
     return -1;
@@ -975,14 +984,14 @@
 
   // Else device is NDM formatted. Find latest control information.
   if (find_last_ctrl_info(ndm)) {
-    ndm->logger.warning("Failed to obtain valid NDM Control Block.");
+    ndm->logger.warning(__FILE__, __LINE__, "Failed to obtain valid NDM Control Block.");
     return -1;
   }
 
   // Read the control information. Return -1 if error.
   PfAssert(ndm->ctrl_blk1 == (ui32)-1);
   if (read_ctrl_info(ndm)) {
-    ndm->logger.info("Failed to read contents NDM Control Block.");
+    ndm->logger.info(__FILE__, __LINE__, "Failed to read contents NDM Control Block.");
     return -1;
   }
 
@@ -1002,13 +1011,14 @@
   else {
     // Fail start-up if image's running bad block count is non-zero.
     if (ndm->num_rbb) {
-      ndm->logger.error("Failed to initialize NDM. |num_rbb| must be zero, found %d", ndm->num_rbb);
+      ndm->logger.error(__FILE__, __LINE__,
+                        "Failed to initialize NDM. |num_rbb| must be zero, found %d", ndm->num_rbb);
       return FsError2(NDM_IMAGE_RBB_CNT, ENXIO);
     }
 
     // Redo the initial bad block list for our device.
     if (init_ibad_list(ndm)) {
-      ndm->logger.error("Failed to initialize NDM bad block list.");
+      ndm->logger.error(__FILE__, __LINE__, "Failed to initialize NDM bad block list.");
       return -1;
     }
 
@@ -1026,6 +1036,7 @@
   // Ensure even lowest running bad block lies in reserved area.
   if (ndm->run_bad_blk[0].val < ndm->frst_reserved) {
     ndm->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialize NDM. First bad block in unexpected location. First bad block at %d, "
         "reservation starts at %d.",
         ndm->run_bad_blk[0].val, ndm->frst_reserved);
@@ -1034,7 +1045,7 @@
 
   // If in the middle of transferring a bad block, continue transfer.
   if (ndm->xfr_tblk != (ui32)-1) {
-    ndm->logger.info("Resuming bad block transfer.");
+    ndm->logger.info(__FILE__, __LINE__, "Resuming bad block transfer.");
     return recover_bad_blk(ndm);
   }
 
@@ -1042,7 +1053,8 @@
   if (wr_metadata) {
     // Return error if doing a read-only initialization.
     if (ndm->flags & FSF_READ_ONLY_INIT) {
-      ndm->logger.info("Failed to Initialize NDM, attempted to write metadata on READ-ONLY mode.");
+      ndm->logger.info(__FILE__, __LINE__,
+                       "Failed to Initialize NDM, attempted to write metadata on READ-ONLY mode.");
       return FsError2(NDM_META_WR_REQ, EINVAL);
     }
 
@@ -1080,11 +1092,11 @@
   // Error check: return 1 for ECC decode error, else -2 fatal error.
   if (status < 0) {
     if (status == -1) {
-      ndm->logger.error("Failed to read page %d. ECC decode error.", old_pn);
+      ndm->logger.error(__FILE__, __LINE__, "Failed to read page %d. ECC decode error.", old_pn);
       FsError2(NDM_RD_ECC_FAIL, EIO);
       return 1;
     }
-    ndm->logger.error("Failed to read page %d. IO Error.");
+    ndm->logger.error(__FILE__, __LINE__, "Failed to read page %d. IO Error.");
     FsError2(NDM_EIO, EIO);
     return -2;
   }
@@ -1146,7 +1158,7 @@
   // Ensure NDM driver flags are valid.
   if (dvr->flags & ~(FSF_MULTI_ACCESS | FSF_TRANSFER_PAGE | FSF_FREE_SPARE_ECC |
                      FSF_NDM_INIT_WRITE | FSF_READ_ONLY_INIT)) {
-    dvr->logger.error("Failed to initialized NDM. Invalid flag.");
+    dvr->logger.error(__FILE__, __LINE__, "Failed to initialized NDM. Invalid flag.");
     FsError2(NDM_CFG_ERR, EINVAL);
     return NULL;
   }
@@ -1154,6 +1166,7 @@
   // Check for valid number of blocks.
   if (dvr->num_blocks <= dvr->max_bad_blocks + NDM_META_BLKS) {
     dvr->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialized NDM. Not enough blocks for reservation and control blocks, found %d "
         "but required %d.",
         dvr->num_blocks, (dvr->max_bad_blocks + NDM_META_BLKS));
@@ -1164,6 +1177,7 @@
   // Check for valid page size (multiple of 512).
   if (dvr->page_size == 0 || dvr->page_size % 512) {
     dvr->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialized NDM. Invalid page size, must positive multiple of 512, but found "
         "%d.",
         dvr->page_size);
@@ -1174,6 +1188,7 @@
   // Check for valid spare bytes size.
   if (dvr->eb_size > dvr->page_size || dvr->eb_size < 16) {
     dvr->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialized NDM. Invalid page oob size, must at least 16 bytes, but found %d.",
         dvr->eb_size);
     FsError2(NDM_CFG_ERR, EINVAL);
@@ -1183,7 +1198,7 @@
   // Allocate space for TargetNDM control block.
   ndm = FsCalloc(1, sizeof(struct ndm));
   if (ndm == NULL) {
-    dvr->logger.error("Failed to initialized NDM. Memory allocation failed.");
+    dvr->logger.error(__FILE__, __LINE__, "Failed to initialized NDM. Memory allocation failed.");
     FsError2(NDM_ENOMEM, ENOMEM);
     return NULL;
   }
@@ -1205,6 +1220,7 @@
   ndm->init_bad_blk = FsMalloc((ndm->max_bad_blks + 1) * sizeof(ui32));
   if (ndm->init_bad_blk == NULL) {
     ndm->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialize NDM. Failed to allocated memory for factory bad block table.");
     FsError2(NDM_ENOMEM, ENOMEM);
     goto ndmAddDe_err;
@@ -1212,6 +1228,7 @@
   ndm->run_bad_blk = FsMalloc((ndm->max_bad_blks + 1) * sizeof(Pair));
   if (ndm->run_bad_blk == NULL) {
     ndm->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialized NDM. Failed to allocated memory for runtime bad block table.");
     FsError2(NDM_ENOMEM, ENOMEM);
     goto ndmAddDe_err;
@@ -1225,7 +1242,7 @@
   snprintf(sem_name, sizeof(sem_name), "NDM_S%03d", NdmSemCount++);
   ndm->sem = semCreate(sem_name, 1, OS_FIFO);
   if (ndm->sem == NULL) {
-    ndm->logger.error("Failed to initialize NDM. Failed to created semaphore.");
+    ndm->logger.error(__FILE__, __LINE__, "Failed to initialize NDM. Failed to created semaphore.");
     FsError2(NDM_SEM_CRE_ERR, errno);
     goto ndmAddDe_err;
   }
@@ -1240,6 +1257,7 @@
   ndm->main_buf = FsAalloc(ndm->page_size + 2 * eb_alloc_sz);
   if (ndm->main_buf == NULL) {
     ndm->logger.error(
+        __FILE__, __LINE__,
         "Failed to initialied NDM. Failed to allocate memory for page content staging buffer.");
     FsError2(NDM_ENOMEM, ENOMEM);
     goto ndmAddDe_err;
@@ -1275,13 +1293,13 @@
 
   // If driver supplies transfer page function, use it.
   if (FLAG_IS_SET(dvr->flags, FSF_TRANSFER_PAGE)) {
-    ndm->logger.info("Using driver page transfer routine.");
+    ndm->logger.info(__FILE__, __LINE__, "Using driver page transfer routine.");
     ndm->dev_ndm = ndm->dev;
     ndm->xfr_page = dvr->transfer_page;
 
     // Else use internal read-page/write-page substitute.
   } else {
-    ndm->logger.info("Using software page transfer routine.");
+    ndm->logger.info(__FILE__, __LINE__, "Using software page transfer routine.");
     ndm->dev_ndm = ndm;
     ndm->xfr_page = ndm_xfr_page;
   }
@@ -1294,7 +1312,7 @@
 
   // Initialize the NDM.
   if (init_ndm(ndm)) {
-    ndm->logger.error("Failed to initialized NDM layer.");
+    ndm->logger.error(__FILE__, __LINE__, "Failed to initialized NDM layer.");
     goto ndmAddDe_err;
   }
 
@@ -1339,13 +1357,13 @@
 
   // Acquire exclusive access to global NDM semaphore.
   semPend(NdmSem, WAIT_FOREVER);
-  ndm->logger.info("Removing NDM device.");
+  ndm->logger.info(__FILE__, __LINE__, "Removing NDM device.");
 
   // Ensure the device is on the device list.
   for (circ = CIRC_LIST_HEAD(&NdmDevs);; circ = circ->next_bck) {
     // If the device was not found, return error.
     if (CIRC_LIST_AT_END(circ, &NdmDevs)) {
-      ndm->logger.info("failed to remove ndm device. device not found.");
+      ndm->logger.info(__FILE__, __LINE__, "failed to remove ndm device. device not found.");
       semPostBin(NdmSem);
       return FsError2(NDM_NOT_FOUND, ENOENT);
     }
diff --git a/zircon/system/ulib/ftl/test/ndm_test.cc b/zircon/system/ulib/ftl/test/ndm_test.cc
index 2e5c484..9967155 100644
--- a/zircon/system/ulib/ftl/test/ndm_test.cc
+++ b/zircon/system/ulib/ftl/test/ndm_test.cc
@@ -472,7 +472,9 @@
 
   class LoggerHelper {
    public:
-    static void Log(const char* _, ...) __PRINTFLIKE(1, 2) { logger_called = true; }
+    static void Log(const char*, int, const char* _, ...) __PRINTFLIKE(3, 4) {
+      logger_called = true;
+    }
   };
 
   ftl::LoggerProxy logger;