Linux 无法在内核源中卸载块设备

Linux 无法在内核源中卸载块设备,linux,vfs,Linux,Vfs,我试图检查jffs2fs上的文件是否存在于内核空间中。我有一个带3.10.14Linux内核的Barrier BreakerOpenWrt。(有一个MTD子系统正在使用,因此我在NAND闪存上为分区使用了伪块设备(/dev/mtdblock1,…12) (我正在实现一些升级逻辑,需要在重新启动之间保持一些状态,为了存储这种状态,我使用文件。) 要检查文件是否存在,我只需尝试打开文件(没有O_create标志),并根据打开的结果做出决定。我将使用下一篇关于从内核中打开文件的文章: 我可以使用这种方

我试图检查
jffs2
fs上的文件是否存在于
内核
空间中。我有一个带
3.10.14
Linux
内核的
Barrier Breaker
OpenWrt
。(有一个
MTD
子系统正在使用,因此我在
NAND
闪存上为分区使用了伪块设备(
/dev/mtdblock1,…12

(我正在实现一些升级逻辑,需要在重新启动之间保持一些状态,为了存储这种状态,我使用文件。)

要检查文件是否存在,我只需尝试打开文件(没有
O_create
标志),并根据打开的结果做出决定。我将使用下一篇关于从内核中打开文件的文章:

我可以使用这种方法检查文件是否存在,但该文件不放在
rootfs
分区上,因此我必须先挂载该分区,然后才能在其上打开文件。 我能够挂载分区,打开文件(检查它是否存在)并关闭它,如果它已打开,但无法取消挂载:我得到一个错误
-16
EBUSY
,我猜,这意味着其他人继续使用这个块设备/挂载点。那么一个问题是谁可以在上面保留一个参考资料

我认为这是一个坏主意,但只是为了测试,我尝试使用
MNT_FORCE
强制卸载,但是,由于本文指出此选项仅适用于
NFS
fs,因此没有任何更改

这里有一个代码:

/* lool at https://stackoverflow.com/questions/1184274/read-write-files-within-a-linux-kernel-module */
static struct file *file_open( const char *path, int flags, int rights )
{
  struct file *filp = NULL;
  mm_segment_t oldfs;
  int err = 0;

  oldfs = get_fs();
  set_fs( get_ds() );

  filp = filp_open( path, flags, rights );

  set_fs( oldfs );

  if( IS_ERR( filp ) )
  {
    err = PTR_ERR( filp );
    return NULL;
  }

  return filp;
}

bool need_to_switch_to_me_upgrade_mode( void )
{
  struct file* me_upgrade_finished_file;
  dev_t me_upgrade_dev;
  char full_name[256] = { 0 };
  bool result;
  int err;

  const char* me_upgrade_dir = "/me_upgrade";
  const char* me_upgrade_dev_name = "/dev/me_upgrade";

  const char* me_upgrade_finished_flag = "/etc/me_upgrade_finished";

  // /dev/mtdblock6
  const char* me_upgrade_finished_flag_partition = "/dev/mtdblock" str( RECOVERY_ROOTFS_DATA_MTD_PART_NUM ); 

  err = sys_mkdir( (const char __user __force *) me_upgrade_dir, 0700 );
  if( err < 0 )
    panic( "fail to mkdir %s\n", me_upgrade_dir );

  me_upgrade_dev = name_to_dev_t( me_upgrade_finished_flag_partition );
  err = create_dev( me_upgrade_dev_name, me_upgrade_dev );
  if( err < 0 )
    panic( "fail to create_dev %s\n", me_upgrade_dev_name );

  err = sys_mount( me_upgrade_dev_name, me_upgrade_dir, "jffs2", MS_SILENT, NULL );
  if( err < 0 )
    panic( "fail to mount %s on to %s, err: %d\n", me_upgrade_dev_name, me_upgrade_dir, err );

  strlcat( full_name, me_upgrade_dir, sizeof( full_name ) );
  strlcat( full_name, me_upgrade_finished_flag, sizeof( full_name ) );

  me_upgrade_finished_file = file_open( full_name, O_RDONLY, 0 );
  if( !me_upgrade_finished_file )
  {
    printk( "fail to open a %s file\n", full_name );
    result = true;
  }
  else
  {
    printk( "success to open a file\n" );
    result = false;
  }

  if( me_upgrade_finished_file )
  {
    err = filp_close( me_upgrade_finished_file, NULL );
    printk( "filp_close returned: %d\n", err );
  }

  err = sys_umount( me_upgrade_dir, MNT_DETACH );
  printk( "sys_umount returned: %d\n", err );

  sys_unlink( me_upgrade_dev_name );  // destroy_dev( me_upgrade_dev_name );
  sys_rmdir( me_upgrade_dir );

  return result;
}
/*lool athttps://stackoverflow.com/questions/1184274/read-write-files-within-a-linux-kernel-module */
静态结构文件*文件\打开(常量字符*路径、整型标志、整型权限)
{
结构文件*filp=NULL;
mm_段_toldfs;
int err=0;
oldfs=get_fs();
set_fs(get_ds());
filp=filp_打开(路径、标志、权限);
set_fs(oldfs);
如果(是错误(filp))
{
err=PTR_err(filp);
返回NULL;
}
返回filp;
}
bool需要切换到升级模式(无效)
{
结构文件*me\u升级\u完成\u文件;
开发我升级开发;
字符全名[256]={0};
布尔结果;
INTERR;
const char*me\u upgrade\u dir=“/me\u upgrade”;
const char*me\u upgrade\u dev\u name=“/dev/me\u upgrade”;
const char*me\u upgrade\u finished\u flag=“/etc/me\u upgrade\u finished”;
///dev/mtdblock6
const char*me\u upgrade\u finished\u flag\u partition=“/dev/mtdblock”str(恢复\u ROOTFS\u数据\u MTD\u PART\u NUM);
err=sys\u mkdir((const char\u user\u force*)me\u upgrade\u dir,0700);
如果(误差<0)
死机(“mkdir%s\n失败”,me\u升级\u dir);
me\u upgrade\u dev=name\u to\u dev\t(me\u upgrade\u finished\u flag\u分区);
err=create_dev(me_upgrade_dev_name,me_upgrade_dev);
如果(误差<0)
恐慌(“无法创建\u开发%s\n”,me\u升级\u开发名称);
err=sys\u mount(me\u upgrade\u dev\u name,me\u upgrade\u dir,“jffs2”,MS\u SILENT,NULL);
如果(误差<0)
死机(“无法将%s装载到%s,错误:%d\n”,me\u upgrade\u dev\u name,me\u upgrade\u dir,错误);
strlcat(全名、me升级目录、sizeof(全名));
strlcat(全名、升级完成标志、sizeof(全名));
me_upgrade_finished_file=文件打开(全名,O_RDONLY,0);
如果(!me\u升级\u完成\u文件)
{
printk(“无法打开%s文件”,全名);
结果=真;
}
其他的
{
printk(“打开文件成功\n”);
结果=假;
}
如果(me\u升级\u完成\u文件)
{
err=filp\u close(me\u升级\u完成\u文件,空);
printk(“filp_close返回:%d\n”,错误);
}
err=sys\u umount(me\u upgrade\u dir,MNT\u DETACH);
printk(“返回的系统计数:%d\n”,错误);
sys_unlink(me_升级\开发\名称);//destroy \开发(me_升级\开发\名称);
系统rmdir(me\u升级\u dir);
返回结果;
}
在我们初始化了
MTD
子系统之后(在
do\u basic\u setup()
之后,在装载
rootfs
之前),从
kernel\u init\u freeable
函数(
init/main.c
)调用此代码

因此,问题是:

  • 在我关闭文件后,谁可以继续使用块设备/装入点
  • 是否有其他方法可以检查内核中是否存在文件
我有第二个选择,只是把我的状态放在一个没有任何fs的分区中,并通过对闪存执行原始访问来检查它,但这种方法需要对我现在拥有的用户代码进行重大更改,所以我试图避免它

另外,我试图通过
sys\u open/sys\u close
(使用相同的参数)更改对
file\u open/filp\u close
的调用,但没有任何更改