title: Debugging a system call from FUSE
body: <p>I'm writing a FUSE filesystem that does some mapping through sqlite, then passes the calls through to the underlying filesystem (somewhat of an expansion on <a href="http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial/" rel="nofollow">bbfs</a>). It started giving me trouble when I tried to start making files. When I call mknod, it returns with ERANGE. Here's the tail of an strace (filesystem is mounted on test/):</p>
  
  <pre><code>$ ./p4fs test/
  $ strace touch test/kilo 2&gt; logs
  $ cat logs
  ...
  fstat(3, {st_mode=S_IFREG|0644, st_size=56467024, ...}) = 0
  mmap(NULL, 56467024, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fbf006bf000
  close(3)                                = 0
  close(0)                                = 0
  open("test/kilo", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = -1 ERANGE (Numerical result out of range)
  futimesat(AT_FDCWD, "test/kilo", NULL)  = 0
  close(1)                                = 0
  exit_group(0)                           = ?
  </code></pre>
  
  <p>and here's the relevant section from my internal logging:</p>
  
  <pre><code>getattr: database opened
  getattr: requesting attr for /kilo
  db_getrowid: statement executed: finding rowid of /kilo
  db_getrowid: mapped /kilo to rowid 0
  getattr: does not exist: /kilo
  mknod: database opened
  mknod: statement executed: checking for existing path
  mknod: calling db_mkdentry(db, /kilo, 100644, 0, 0)
  db_mkdentry: parent is /
  db_getrowid: statement executed: finding rowid of /
  db_getrowid: mapped / to rowid 1
  db_mkdentry: statement executed: creating dentry /kilo
  db_getrowid: statement executed: finding rowid of /kilo
  db_getrowid: mapped /kilo to rowid 3
  p4fs: calling system mknod(3, 100644, 0)
  p4fs: got errno 13
  </code></pre>
  
  <p>I'm looking for (1) the solution to this immediate problem and (2) a good way to debug FUSE in general. I have a sneaking suspicion that the ERANGE is coming from strtol(), but I don't know how to check. I wish I could make gdb pop up when it hits the callback...</p>
  
  <p>Thanks!</p>
  
  <p>EDIT: Oh, here's the source for my mknod() function:</p>
  
  <pre><code>static int p4_mknod(const char *path, mode_t mode, dev_t dev) {
          sqlite3 *db;
          sqlite3_stmt *statement;
          char query[MAX_QUERY_LENGTH];
          int rc;
          int return_value;
          int path_exists = -1;
  
          OPEN_LOG("mknod")
          OPEN_DB(db_path, db)
  
          /* check for existing filename */
          sprintf(query,
                  "SELECT COUNT(*) FROM dentry "
                  "WHERE name = '%s'",
                  path);
          sqlite3_prepare(db,
                  query,
                  -1,
                  &amp;statement,
                  NULL);
          rc = sqlite3_step(statement);
          SQLITE3_ERRCHK("checking for existing path")
          path_exists = sqlite3_column_int(statement, 0);
          sqlite3_finalize(statement);
  
          if (path_exists &lt;= 0) {
                  int physical_rowid;
                  char physical_name[MAX_QUERY_LENGTH];
  
                  /* path is not already in db */
                  syslog(LOG_DEBUG, "calling db_mkdentry(db, %s, %o, 0, 0)",
                          path, mode);
                  db_mkdentry(db, (char *) path, mode, 0, 0);
  
                  /* make the actual file */
                  physical_rowid = db_getrowid(db, (char *) path);
                  sprintf(physical_name, "%i", physical_rowid);
                  syslog(LOG_DEBUG, "calling system mknod(%s, %o, %li)",
                          physical_name, mode, dev);
                  return_value = mknod(physical_name, mode, dev);
          } else {
                  syslog(LOG_INFO, "called on existing path");
                  return_value = -EEXIST;
          }
  
          syslog(LOG_DEBUG, "errno %i", errno);
  
          return errno;
  }
  </code></pre>