2010-12-04 2 views
1

Я пишу файловую систему FUSE, которая выполняет некоторое сопоставление через sqlite, а затем передает вызовы в базовую файловую систему (что-то вроде расширения на bbfs). Это начало беспокоить меня, когда я пытался начать делать файлы. Когда я вызываю mknod, он возвращается с ERANGE. Вот хвост из Трассирования (файловая система смонтирована на тесте /):Отладка системного вызова от FUSE

$ ./p4fs test/ 
$ strace touch test/kilo 2> 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)       = ? 

и вот соответствующий раздел из моего внутреннего протоколирования:

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 

Я ищу (1) решение эта непосредственная проблема и (2) хороший способ отладки FUSE в целом. У меня есть подозрение, что ERANGE исходит от strtol(), но я не знаю, как проверить. Я бы хотел, чтобы gdb всплывал, когда он попадал на обратный вызов ...

Спасибо!

EDIT: Ах, вот источник для моего MKNOD функция():

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, 
       &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 <= 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; 
} 

ответ

0

Это не совсем ответ, но я столкнулся с проблемой, работая как root. Я подозреваю, что это имеет какое-то отношение к FUSE, потому что у меня была аналогичная проблема при попытке запустить sshfs как обычный пользователь несколько месяцев назад.

2

Несколько советов:

  • Не используйте Sprintf и друг, чтобы построить заявления SQL для sqlite3 , Рекомендуется использовать размещенные параметры в вашем заявлении и привязывать значения к ним с помощью функций sqlite3_bind.

  • Всегда предпочитайте snprintf вместо sprintf и проверяйте его выход. Это избавит вас от множества неприятностей.

  • Убедитесь, что вы запускаете процесс файловой системы FUSE на переднем плане - это облегчает отладку.

Вы пробовали точки останова в gdb? Или куча вызовов perror() в вашем коде, чтобы определить, откуда взялось значение errno, о котором вы говорили?

BTW нет вызова strtol() в фрагменте кода, который вы предоставили, и есть несколько макросов без их определений. Также IIRC 13 является кодом ошибки для EACCESS.

EDIT:

Что-то, что вы, возможно, пропустили из FUSE API:

Главным исключением является то, что вместо возвращается ошибка в «егто», то операция должна возвращать отрицается значение ошибки (-errno) напрямую.

Вы, кажется, возвращаете errno as-is.

+0

Спасибо за советы! Я довольно новичок в sqlite, поэтому я ценю их. Я не знаю, как заставить мои обратные вызовы запускаться в gdb, но если есть способ, я хотел бы услышать об этом. Я беспокоился о strtol, потому что я посмотрел на источник для нескольких реализаций mknod.c и увидел его. – Jay 2010-12-04 22:31:33

Смежные вопросы