LINUX.ORG.RU

FUSE Development

 , ,


1

1

Приветствую. Разбираюсь с ФС. Спроектировал свою FAT подобную систему, использую FUSE.

Библиотека основных функций ФС уже написана. Но... Не получается до конца прикрутить FUSE. И я даже как-то в недоумении, как отлаживать, это и не Kernel object, где можно использовать kprintf, и обычное логирование у меня почему-то не вышло, хотя по идее должно работать. Возможно, потому что ошибка сегметации возникает раньше того, как я вывожу сообщение в лог.

Код fuse модуля:

#define _USE_GNU
#define _POSIX_C_SOURCE 199309
#define FUSE_USE_VERSION  26
#define USERDATA ((struct user_data*)(fuse_get_context()->private_data))
#define LOGFILE USERDATA->logfile

#include <fuse.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdarg.h>
#include "libdfat.h"

/******************************************************/
struct user_data {
  FILE *logfile;
};

FILE* log_open()
{
  FILE *logfile = fopen("fusedfat.log", "w");
  setvbuf(logfile, NULL, _IOLBF, 0);;
  return logfile;
}

void log_msg(const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    vfprintf( LOGFILE, format, ap);
    fflush(LOGFILE);
}


/******************************************************/

int dfuse_usage()
{
    printf("dfuse_fuse <device> <mountpoint>\n\n");
    return 0;
}

void *dfuse_init(struct fuse_conn_info *conn)
{   
    return NULL;
}

void dfuse_destroy(void *userdata)
{
    fflush(LOGFILE);
    fclose(LOGFILE);
    dfat_close();
}

static int dfuse_getattr(const char *path, struct stat *stbuf)
{
  int res = 0; /* temporary result */
  memset(stbuf, 0, sizeof(struct stat));
  dir_record_t r;
  
  if( !dfat_find_dir_record(path, &r) )
    return -ENOENT;

  if(r.flags & 0x80 == 1) {
    stbuf->st_mode = 0x4000 | 0777;
    stbuf->st_size = 0;
  }
  else {
    stbuf->st_mode = 0777;
    stbuf->st_size = r.size;
  }

}

static int dfuse_error(char *str)
{
    int ret = -errno;
    
    log_msg("    ERROR %s: %s\n", str, strerror(errno));
    
    return ret;
}

int dfuse_mkdir(const char *path, mode_t mode)
{
    int retstat = 0;
    
    log_msg("\ndfuse_mkdir(path=\"%s\", mode=0%3o)\n", path, mode);

    retstat = dfat_create(path, 0x80, NULL);

    if (retstat < 0)
      retstat = dfuse_error("dfuse_mkdir mkdir");
    
    return retstat;
}

int dfuse_unlink(const char *path)
{
    int retstat = 0;
    
    log_msg("dfuse_unlink(path=\"%s\")\n", path);
    
    retstat = dfat_unlink(path);

    if (retstat < 0)
    
    retstat = dfuse_error("unlink");
    
    return retstat;
}

int dfuse_rmdir(const char *path)
{
    int retstat = 0;
    log_msg("dfuse_rmdir(path=\"%s\")\n", path);
    retstat = dfat_unlink(path);
    if (retstat < 0)   
      retstat = dfuse_error("rmdir");
    
    return retstat;
}

int dfuse_rename(const char *path, const char *newpath)
{
    return dfat_rename(path, newpath);
}

int dfuse_open(const char *path, struct fuse_file_info *fi)
{
  if(!dfat_exist(path)) 
  {
    return -ENOENT;
  }
  
  return 0;
}

int dfuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
    int readed = 0;
    return readed;
}

int dfuse_write(const char *path, const char *buf, size_t size, off_t offset,
       struct fuse_file_info *fi)
{
  int writed = 0;
  return writed = 0;
}


int dfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
               struct fuse_file_info *fi)
{
    log_msg("dfuse_readdir()\n");
    int retstat = 0;
    struct list l;
    list_clear(&l);
    dfat_read_folder_by_path(path, &l);

    filler(buf, "." , NULL, 0);
    filler(buf, ".." , NULL, 0);
    for(unsigned int i=0; i<l.count; i++) {
        filler(buf, l.array[i].name , NULL, 0);
        log_msg("\t%s\n", l.array[i].name);
    }
    
    fflush(stderr);

    return retstat;
}

/******************************************************************/
/* The fuse struct for storing FS operations functions addresses */
struct fuse_operations dfuse_oper = {
  .getattr = dfuse_getattr,
  .mkdir = dfuse_mkdir,
  .unlink = dfuse_unlink,
  .readdir = dfuse_readdir,
  .rmdir = dfuse_rmdir,
  .rename = dfuse_rename,
  .open = dfuse_open,
  .read = dfuse_read,
  .write = dfuse_write,
  .destroy = dfuse_destroy,
};

int main(int argc, char *argv[])
{
    if ((argc < 3))
        return dfuse_usage();

    struct user_data *data = (struct user_data*) malloc(sizeof(struct user_data));
    data->logfile = log_open();

    dfat_load(argv[1]);

    argv[1] = argv[2];
    argv[2] = NULL;
    argc--;

    
    return fuse_main(argc, argv, &dfuse_oper, data);  
}

Все собирается. Монтируется без ошибок. Но:

dmesg | tail
[101513.954108] fusedfat[21784]: segfault at c000c20 ip 00007f9312f72137 sp 00007f9312a458f8 error 4 in libc-2.16.so[7f9312e55000+19d000]
[101514.754521] systemd-journald[127]: Failed to write entry, ignoring: Argument list too long

А при попытке прочитать содержимое дирректории:

% ls mountpoint/*
ls: cannot access mountpoint/*: Transport endpoint is not connected

Поддтолкните в нужное направление пожалуйста.

Запускай с параметрами -f и -s. Под gdb. Как раз и увидишь, где падает.

Сейчас он у тебя в фон уходит, и там падает.

i-rinat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.