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