gpt4 book ai didi

c - 从 FUSE 调试系统调用

转载 作者:太空宇宙 更新时间:2023-11-04 03:06:29 25 4
gpt4 key购买 nike

我正在编写一个 FUSE 文件系统,它通过 sqlite 进行一些映射,然后将调用传递给底层文件系统(在某种程度上是对 bbfs 的扩展)。当我试图开始制作文件时,它开始给我带来麻烦。当我调用 mknod 时,它返回 ERANGE。这是 strace 的尾部(文件系统挂载在 test/上):

$ ./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 在遇到回调时弹出...

谢谢!

编辑:哦,这是我的 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;
}

最佳答案

一些建议:

  • 不要使用 sprintf 和 friend 为 sqlite3 构建 SQL 语句。建议您在语句中使用托管参数并使用 sqlite3_bind 函数将值绑定(bind)到它们。

  • 总是更喜欢 snprintf 而不是 sprintf 并检查它的输出。它将为您省去很多麻烦。

  • 确保您在前台运行您的 FUSE 文件系统进程 - 它使调试更容易。

你试过gdb中的断点吗?或者在您的代码中调用一堆 perror() 来定位您提到的 errno 值的来源?

顺便说一句,您提供的代码片段中没有调用 strtol() 并且有一些宏没有定义。此外,IIRC 13 是 EACCESS 的错误代码。

编辑:

您可能错过了 FUSE API 中的内容:

A major exception is that instead of returning an error in 'errno', the operation should return the negated error value (-errno) directly.

您似乎按原样返回 errno。

关于c - 从 FUSE 调试系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4355550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com