新文件系统的通信机制

fuse在内核中通过设备号 /dev/fuse来进行内核与用户空间之间通信,其中内核代码(/fs/fuse),通信之间采用协议方式。内核发送到用户态时就会发送一个头fuse_in_head(用户数据进入端):

struct fuse_in_header

{

__u32 len;

__u32 opcode;

__u64 unique;

__u32 nodeid;

__u32 uid;

__u32 gid;

__u32 pid;

__u32 padding;

}

各个字段含义如下:

字段名称

数据类型

含义

len

uint32_t

本次请求数据包的长度

opcode

uint32_t

操作码

unique

uint64_t

请求的uid,回复包需要

nodeid

uint32_t

本次操作涉及的文件系统 node id

uid

uint32_t

调用者的id

gid

uint32_t

调用者所在组id

padding

uint32_t

未使用,填充至64字节倍数

其中操作码即为文件系统的所有涉及操作:

操作码

回复函数(正确情况)

reply数据类型

相应函数

备注

FUSE_LOOKUP

fuse_reply_entry

fuse_entry_out

0

do_lookup

取属性

FUSE_FORGET



1

do_forget


FUSE_GETATTR

fuse_reply_attr

fuse_attr_out

2

do_getattr

取属性

FUSE_SETATTR

fuse_reply_attr

fuse_attr_out

3

do_setattr


FUSE_READLINK

fuse_reply_readlink

string

4

do_readlink


FUSE_SYMLINK

fuse_reply_entry

fuse_entry_out

5

do_symlink


FUSE_MKNOD

fuse_reply_entry

fuse_entry_out

6

do_mknod


FUSE_MKDIR

fuse_reply_entry

fuse_entry_out

7

do_mkdir


FUSE_UNLINK

fuse_reply_err

errcode

8

do_unlink


FUSE_RMDIR

fuse_reply_err

errcode

9

do_rmdir


FUSE_RENAME

fuse_reply_err

errcode

10

do_rename


FUSE_LINK

fuse_reply_entry

fuse_entry_out

11

do_link


FUSE_OPEN

fuse_reply_open

fuse_open_out

12

do_open


FUSE_READ

fuse_reply_buf,

fuse_reply_iov

char[]

13

do_read


FUSE_WRITE

fuse_reply_write

int

14

do_write


FUSE_STATFS

fuse_reply_statfs

fuse_statfs_out

15

do_statfs


FUSE_RELEASE

fuse_reply_err

errcode

16

do_release


FUSE_FSYNC

fuse_reply_err

errcode

17

do_fsync


FUSE_SETXATTR

fuse_reply_err

errcode

18

do_setxattr


FUSE_GETXATTR

fuse_reply_buf

fuse_reply_xattr

fuse_getxattr_out

19

do_getxattr


FUSE_LISTATTR

fuse_reply_xattr

fuse_getxattr_out

20

do_listxattr


FUSE_REMOVEXATTR

fuse_reply_err

errcode

21

do_removexattr


FUSE_FLUSH

fuse_reply_err

errcode

22

do_flush


FUSE_INIT

No

No

23

do_init

系统实现

FUSE_OPENDIR

fuse_reply_open

fuse_open_out

24

do_opendir


FUSE_READDIR

fuse_reply_buf

char*[]

25

do_readdir


FUSE_RELEASEDIR

fuse_reply_err

errcode

26

do_releasedir


FUSE_FSYNCDIR

fuse_reply_err

errcode

27

do_fsyncdir


FUSE_GETLK

fuse_reply_lock

fuse_lk_out

28

do_getlk


FUSE_SETLK

fuse_reply_err

errcode

29

do_setlk


FUSE_SETLKW


fuse_lk_out

30

do_setlkw

setlk实现

FUSE_ACCESS

fuse_reply_err

errcode

31

do_access


FUSE_CREATE

fuse_reply_create

fuse_open_out??

32

do_create


FUSE_INTERRUPT



33

do_interrupt

系统实现

FUSE_BMAP

fuse_reply_bmap


34

do_bmap


FUSE_IOCTL

fuse_reply_ioctl

fuse_reply_ioctl_retry


35

do_ioctl


FUSE_POLL

fuse_reply_poll


36

do_poll


FUSE_DESTROY

NULL


37

do_destroy


CUSE_INIT

38

do_lowlevel_init


参考资料:

 

 

这里主要分析一下fuse的内核态用户态通信机制。fuse的主要运行流程如下图所示:

当用户态程序执行了POSIX的文件系统操作,经过glibc,变换为系统调用传递给vfs,vfs再将其传给FUSE的内核模块,FUSE的内核模块根据系统调用的类型,将请求发送到用户态的FUSE进程,并等待用户态进程的应答。FUSE内核模块再收到应答后,将其发送给vfs,把最终运行结果呈现到用户态程序。

那FUSE是如何让用户态与内核态通信的呢?这个在源代码中可以看得比较清楚。

首先在,内核代码fs/fuse/dev.c中,

 
  1. /* 为fuse定义一个misc设备 */  
  2. static struct miscdevice fuse_miscdevice = {  
  3.     .minor = FUSE_MINOR,  
  4.     .name  = "fuse",                  /* 生产的misc设备将会出现在/dev/fuse */  
  5.     .fops = &fuse_dev_operations,  
  6. };  
  7.   
  8. int __init fuse_dev_init(void)  
  9. {  
  10.     int err = -ENOMEM;  
  11.     fuse_req_cachep = kmem_cache_create("fuse_request",  
  12.                         sizeof(struct fuse_req),  
  13.                         0, 0, NULL);  
  14.     if (!fuse_req_cachep)  
  15.         goto out;  
  16.   
  17.     err = misc_register(&fuse_miscdevice);   /* 注册成misc设备,misc设备的主设备号为10 */  
  18.     if (err)  
  19.         goto out_cache_clean;  
  20.   
  21.     return 0;  
  22.   
  23.  out_cache_clean:  
  24.     kmem_cache_destroy(fuse_req_cachep);  
  25.  out:  
  26.     return err;  
  27. }  
/* 为fuse定义一个misc设备 */
static struct miscdevice fuse_miscdevice = {
    .minor = FUSE_MINOR,
    .name  = "fuse",                  /* 生产的misc设备将会出现在/dev/fuse */
    .fops = &fuse_dev_operations,
};

int __init fuse_dev_init(void)
{
    int err = -ENOMEM;
    fuse_req_cachep = kmem_cache_create("fuse_request",
                        sizeof(struct fuse_req),
                        0, 0, NULL);
    if (!fuse_req_cachep)
        goto out;

    err = misc_register(&fuse_miscdevice);   /* 注册成misc设备,misc设备的主设备号为10 */
    if (err)
        goto out_cache_clean;

    return 0;

 out_cache_clean:
    kmem_cache_destroy(fuse_req_cachep);
 out:
    return err;
}
通过调用fuse_dev_init函数,将会生成一个misc设备(类似字符设备,但主设备号为10,并且会在/dev/目录下根据设备名,自动生成设备文件)在/dev/fuse下。用户态代码在通过open这个设备文件,并且通过如下函数,注册向fuse内核态通信的函数:
  1. struct fuse_chan *fuse_kern_chan_new(int fd)  
  2. {  
  3.     struct fuse_chan_ops op = {  
  4.         .receive = fuse_kern_chan_receive,  
  5.         .send = fuse_kern_chan_send,  
  6.         .destroy = fuse_kern_chan_destroy,  
  7.     };  
  8.     size_t bufsize = getpagesize() + 0x1000;  
  9.     bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;  
  10.     return fuse_chan_new(&op, fd, bufsize, NULL);  
  11. }  
struct fuse_chan *fuse_kern_chan_new(int fd)
{
	struct fuse_chan_ops op = {
		.receive = fuse_kern_chan_receive,
		.send = fuse_kern_chan_send,
		.destroy = fuse_kern_chan_destroy,
	};
	size_t bufsize = getpagesize() + 0x1000;
	bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
	return fuse_chan_new(&op, fd, bufsize, NULL);
}
fuse_kern_chan_receive函数,通过res = read(fuse_chan_fd(ch), buf, size);从/dev/fuse中读取内核发来的情求,再通过fuse_kern_chan_send函数中的ssize_t res = writev(fuse_chan_fd(ch), iov, count);将数据发送到内核模块。

再回到内核模块,还是fs/fuse/dev.c文件中,FUSE通过为/dev/fuse设备文件注册以下操作回调来支持用户态的对其的读写操作:

  1. const struct file_operations fuse_dev_operations = {  
  2.     .owner      = THIS_MODULE,  
  3.     .llseek     = no_llseek,    /* 不支持seek操作 */  
  4.     .read       = do_sync_read,   /* 使用通用的同步读函数 */  
  5.     .aio_read   = fuse_dev_read,   /* fuse为用户态读取提供的异步函数 */  
  6.     .write      = do_sync_write,  /* 使用通用的同步写函授 */  
  7.     .aio_write  = fuse_dev_write,  /* fuse为用户态读取提供的异步函授 */  
  8.     .poll       = fuse_dev_poll,   /* 检查是否在一个文件上有操作发生,如果没有则睡眠,直到该文件上有操作发生*/  
  9.     .release    = fuse_dev_release,   /* 用户态close该设备文件对应的fd */  
  10.     .fasync     = fuse_dev_fasync,    /* 通过信号来启用或禁止I/O事件通告*/  
  11. };  
const struct file_operations fuse_dev_operations = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,    /* 不支持seek操作 */
	.read		= do_sync_read,   /* 使用通用的同步读函数 */
	.aio_read	= fuse_dev_read,   /* fuse为用户态读取提供的异步函数 */
	.write		= do_sync_write,  /* 使用通用的同步写函授 */
	.aio_write	= fuse_dev_write,  /* fuse为用户态读取提供的异步函授 */
	.poll		= fuse_dev_poll,   /* 检查是否在一个文件上有操作发生,如果没有则睡眠,直到该文件上有操作发生*/
	.release	= fuse_dev_release,   /* 用户态close该设备文件对应的fd */
	.fasync		= fuse_dev_fasync,    /* 通过信号来启用或禁止I/O事件通告*/
};
其中,do_sync_read中,调用了ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos),同样do_sync_write函数中,也调用了ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos),所以他们不用单独实现。

在FUSE内核中,存在一个fuse_conn结构体,为用户态、内核态通信服务,其结构为:

  1. /** 
  2.  * A Fuse connection. 
  3.  * 
  4.  * This structure is created, when the filesystem is mounted, and is 
  5.  * destroyed, when the client device is closed and the filesystem is 
  6.  * unmounted. 
  7.  */  
  8. struct fuse_conn {  
  9.     /** Lock protecting accessess to  members of this structure */  
  10.     spinlock_t lock;  
  11.   
  12.     /** Mutex protecting against directory alias creation */  
  13.     struct mutex inst_mutex;  
  14.   
  15.     /** Refcount 结构体的引用计数*/  
  16.     atomic_t count;  
  17.   
  18.     /** The user id for this mount 用户ID*/  
  19.     uid_t user_id;  
  20.   
  21.     /** The group id for this mount 组ID*/  
  22.     gid_t group_id;  
  23.   
  24.     /** The fuse mount flags for this mount  挂载参数*/  
  25.     unsigned flags;  
  26.   
  27.     /** Maximum read size 最大读取字节数*/  
  28.     unsigned max_read;  
  29.   
  30.     /** Maximum write size 最大写入字节数*/  
  31.     unsigned max_write;  
  32.   
  33.     /** Readers of the connection are waiting on this 读取请求的等待队列*/  
  34.     wait_queue_head_t waitq;  
  35.   
  36.     /** The list of pending requests 正在等待的队列*/  
  37.     struct list_head pending;  
  38.   
  39.     /** The list of requests being processed 正在处理的队列*/  
  40.     struct list_head processing;  
  41.   
  42.     /** The list of requests under I/O 正在进行IO操作的队列*/  
  43.     struct list_head io;  
  44.   
  45.     /** The next unique kernel file handle */  
  46.     u64 khctr;  
  47.   
  48.     /** rbtree of fuse_files waiting for poll events indexed by ph */  
  49.     struct rb_root polled_files;  
  50.   
  51.     /** Maximum number of outstanding background requests 最大后台请求数*/  
  52.     unsigned max_background;  
  53.   
  54.     /** Number of background requests at which congestion starts */  
  55.     unsigned congestion_threshold;  
  56.   
  57.     /** Number of requests currently in the background 后台请求数*/  
  58.     unsigned num_background;  
  59.   
  60.     /** Number of background requests currently queued for userspace 正在执行的后台请求数*/  
  61.     unsigned active_background;  
  62.   
  63.     /** The list of background requests set aside for later queuing */  
  64.     struct list_head bg_queue;  
  65.   
  66.     /** Pending interrupts 中断请求队列*/  
  67.     struct list_head interrupts;  
  68.   
  69.     /** Flag indicating if connection is blocked.  This will be 
  70.         the case before the INIT reply is received, and if there 
  71.         are too many outstading backgrounds requests 阻塞标志*/  
  72.     int blocked;  
  73.   
  74.     /** waitq for blocked connection 阻塞等待队列*/  
  75.     wait_queue_head_t blocked_waitq;  
  76.   
  77.     /** waitq for reserved requests 等待服务的队列*/  
  78.     wait_queue_head_t reserved_req_waitq;  
  79.   
  80.     /** The next unique request id */  
  81.     u64 reqctr;  
  82.   
  83.     /** Connection established, cleared on umount, connection 
  84.         abort and device release 连接标志*/  
  85.     unsigned connected;  
  86.   
  87.     /** Connection failed (version mismatch).  Cannot race with 
  88.         setting other bitfields since it is only set once in INIT 
  89.         reply, before any other request, and never cleared */  
  90.     unsigned conn_error:1;  
  91.   
  92.     /** Connection successful.  Only set in INIT */  
  93.     unsigned conn_init:1;  
  94.   
  95.     /** Do readpages asynchronously?  Only set in INIT */  
  96.     unsigned async_read:1;  
  97.   
  98.     /** Do not send separate SETATTR request before open(O_TRUNC)  */  
  99.     unsigned atomic_o_trunc:1;  
  100.   
  101.     /** Filesystem supports NFS exporting.  Only set in INIT */  
  102.     unsigned export_support:1;  
  103.   
  104.     /** Set if bdi is valid */  
  105.     unsigned bdi_initialized:1;  
  106.   
  107.     /* 
  108.      * The following bitfields are only for optimization purposes 
  109.      * and hence races in setting them will not cause malfunction 
  110.      */  
  111.   
  112.     /** Is fsync not implemented by fs? */  
  113.     unsigned no_fsync:1;  
  114.   
  115.     /** Is fsyncdir not implemented by fs? */  
  116.     unsigned no_fsyncdir:1;  
  117.   
  118.     /** Is flush not implemented by fs? */  
  119.     unsigned no_flush:1;  
  120.   
  121.     /** Is setxattr not implemented by fs? */  
  122.     unsigned no_setxattr:1;  
  123.   
  124.     /** Is getxattr not implemented by fs? */  
  125.     unsigned no_getxattr:1;  
  126.   
  127.     /** Is listxattr not implemented by fs? */  
  128.     unsigned no_listxattr:1;  
  129.   
  130.     /** Is removexattr not implemented by fs? */  
  131.     unsigned no_removexattr:1;  
  132.   
  133.     /** Are file locking primitives not implemented by fs? */  
  134.     unsigned no_lock:1;  
  135.   
  136.     /** Is access not implemented by fs? */  
  137.     unsigned no_access:1;  
  138.   
  139.     /** Is create not implemented by fs? */  
  140.     unsigned no_create:1;  
  141.   
  142.     /** Is interrupt not implemented by fs? */  
  143.     unsigned no_interrupt:1;  
  144.   
  145.     /** Is bmap not implemented by fs? */  
  146.     unsigned no_bmap:1;  
  147.   
  148.     /** Is poll not implemented by fs? */  
  149.     unsigned no_poll:1;  
  150.   
  151.     /** Do multi-page cached writes */  
  152.     unsigned big_writes:1;  
  153.   
  154.     /** Don't apply umask to creation modes */  
  155.     unsigned dont_mask:1;  
  156.   
  157.     /** The number of requests waiting for completion */  
  158.     atomic_t num_waiting;  
  159.   
  160.     /** Negotiated minor version */  
  161.     unsigned minor;  
  162.   
  163.     /** Backing dev info */  
  164.     struct backing_dev_info bdi;  
  165.   
  166.     /** Entry on the fuse_conn_list */  
  167.     struct list_head entry;  
  168.   
  169.     /** Device ID from super block 超级块的设备id*/  
  170.     dev_t dev;  
  171.   
  172.     /** Dentries in the control filesystem */  
  173.     struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];  
  174.   
  175.     /** number of dentries used in the above array */  
  176.     int ctl_ndents;  
  177.   
  178.     /** O_ASYNC requests */  
  179.     struct fasync_struct *fasync;  
  180.   
  181.     /** Key for lock owner ID scrambling */  
  182.     u32 scramble_key[4];  
  183.   
  184.     /** Reserved request for the DESTROY message */  
  185.     struct fuse_req *destroy_req;  
  186.   
  187.     /** Version counter for attribute changes 文件属性的版本*/  
  188.     u64 attr_version;  
  189.   
  190.     /** Called on final put */  
  191.     void (*release)(struct fuse_conn *);  
  192.   
  193.     /** Super block for this connection. */  
  194.     struct super_block *sb;  
  195.   
  196.     /** Read/write semaphore to hold when accessing sb. 访问超级块的信号量*/  
  197.     struct rw_semaphore killsb;  
  198. };  
/**
 * A Fuse connection.
 *
 * This structure is created, when the filesystem is mounted, and is
 * destroyed, when the client device is closed and the filesystem is
 * unmounted.
 */
struct fuse_conn {
	/** Lock protecting accessess to  members of this structure */
	spinlock_t lock;

	/** Mutex protecting against directory alias creation */
	struct mutex inst_mutex;

	/** Refcount 结构体的引用计数*/
	atomic_t count;

	/** The user id for this mount 用户ID*/
	uid_t user_id;

	/** The group id for this mount 组ID*/
	gid_t group_id;

	/** The fuse mount flags for this mount  挂载参数*/
	unsigned flags;

	/** Maximum read size 最大读取字节数*/
	unsigned max_read;

	/** Maximum write size 最大写入字节数*/
	unsigned max_write;

	/** Readers of the connection are waiting on this 读取请求的等待队列*/
	wait_queue_head_t waitq;

	/** The list of pending requests 正在等待的队列*/
	struct list_head pending;

	/** The list of requests being processed 正在处理的队列*/
	struct list_head processing;

	/** The list of requests under I/O 正在进行IO操作的队列*/
	struct list_head io;

	/** The next unique kernel file handle */
	u64 khctr;

	/** rbtree of fuse_files waiting for poll events indexed by ph */
	struct rb_root polled_files;

	/** Maximum number of outstanding background requests 最大后台请求数*/
	unsigned max_background;

	/** Number of background requests at which congestion starts */
	unsigned congestion_threshold;

	/** Number of requests currently in the background 后台请求数*/
	unsigned num_background;

	/** Number of background requests currently queued for userspace 正在执行的后台请求数*/
	unsigned active_background;

	/** The list of background requests set aside for later queuing */
	struct list_head bg_queue;

	/** Pending interrupts 中断请求队列*/
	struct list_head interrupts;

	/** Flag indicating if connection is blocked.  This will be
	    the case before the INIT reply is received, and if there
	    are too many outstading backgrounds requests 阻塞标志*/
	int blocked;

	/** waitq for blocked connection 阻塞等待队列*/
	wait_queue_head_t blocked_waitq;

	/** waitq for reserved requests 等待服务的队列*/
	wait_queue_head_t reserved_req_waitq;

	/** The next unique request id */
	u64 reqctr;

	/** Connection established, cleared on umount, connection
	    abort and device release 连接标志*/
	unsigned connected;

	/** Connection failed (version mismatch).  Cannot race with
	    setting other bitfields since it is only set once in INIT
	    reply, before any other request, and never cleared */
	unsigned conn_error:1;

	/** Connection successful.  Only set in INIT */
	unsigned conn_init:1;

	/** Do readpages asynchronously?  Only set in INIT */
	unsigned async_read:1;

	/** Do not send separate SETATTR request before open(O_TRUNC)  */
	unsigned atomic_o_trunc:1;

	/** Filesystem supports NFS exporting.  Only set in INIT */
	unsigned export_support:1;

	/** Set if bdi is valid */
	unsigned bdi_initialized:1;

	/*
	 * The following bitfields are only for optimization purposes
	 * and hence races in setting them will not cause malfunction
	 */

	/** Is fsync not implemented by fs? */
	unsigned no_fsync:1;

	/** Is fsyncdir not implemented by fs? */
	unsigned no_fsyncdir:1;

	/** Is flush not implemented by fs? */
	unsigned no_flush:1;

	/** Is setxattr not implemented by fs? */
	unsigned no_setxattr:1;

	/** Is getxattr not implemented by fs? */
	unsigned no_getxattr:1;

	/** Is listxattr not implemented by fs? */
	unsigned no_listxattr:1;

	/** Is removexattr not implemented by fs? */
	unsigned no_removexattr:1;

	/** Are file locking primitives not implemented by fs? */
	unsigned no_lock:1;

	/** Is access not implemented by fs? */
	unsigned no_access:1;

	/** Is create not implemented by fs? */
	unsigned no_create:1;

	/** Is interrupt not implemented by fs? */
	unsigned no_interrupt:1;

	/** Is bmap not implemented by fs? */
	unsigned no_bmap:1;

	/** Is poll not implemented by fs? */
	unsigned no_poll:1;

	/** Do multi-page cached writes */
	unsigned big_writes:1;

	/** Don't apply umask to creation modes */
	unsigned dont_mask:1;

	/** The number of requests waiting for completion */
	atomic_t num_waiting;

	/** Negotiated minor version */
	unsigned minor;

	/** Backing dev info */
	struct backing_dev_info bdi;

	/** Entry on the fuse_conn_list */
	struct list_head entry;

	/** Device ID from super block 超级块的设备id*/
	dev_t dev;

	/** Dentries in the control filesystem */
	struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];

	/** number of dentries used in the above array */
	int ctl_ndents;

	/** O_ASYNC requests */
	struct fasync_struct *fasync;

	/** Key for lock owner ID scrambling */
	u32 scramble_key[4];

	/** Reserved request for the DESTROY message */
	struct fuse_req *destroy_req;

	/** Version counter for attribute changes 文件属性的版本*/
	u64 attr_version;

	/** Called on final put */
	void (*release)(struct fuse_conn *);

	/** Super block for this connection. */
	struct super_block *sb;

	/** Read/write semaphore to hold when accessing sb. 访问超级块的信号量*/
	struct rw_semaphore killsb;
};


fuse_conn结构体的指针将会保存在file->private_data中,每次内核态向用户态发送情求时都会用到fuse_conn结构体。在fuse_dev_read函数的处理流程主要入下:

  1. static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,  
  2.                   unsigned long nr_segs, loff_t pos)  
  3. {  
  4.         struct fuse_in *<SPAN style="COLOR: rgb(255,102,102)">in</SPAN>; /* 用来表示用户态读入的内核 */  
  5.     //省略变量定义   
  6.     struct fuse_conn *fc = fuse_get_conn(file);   /* 获得fuse_conn结构体的指针 */  
  7.     if (!fc)  
  8.         return -EPERM;  
  9.   
  10.  restart:  
  11.     spin_lock(&fc->lock);  
  12.     err = -EAGAIN;  
  13.     if ((file->f_flags & O_NONBLOCK) && fc->connected &&  
  14.         !request_pending(fc))  //如果是非阻塞方式,则判断队列中有无等待处理请求,无请求则直接返回  
  15.         goto err_unlock;  
  16.   
  17.     request_wait(fc);        //阻塞等待内核态的请求到了  
  18.         ......  
  19.     if (!list_empty(&fc->interrupts)) {  //判断是否有中断请求需要发送,有则先发中断请求  
  20.         req = list_entry(fc->interrupts.next, struct fuse_req,  
  21.                  intr_entry);  
  22.         return fuse_read_interrupt(fc, req, iov, nr_segs);  
  23.     }  
  24.   
  25.     req = list_entry(fc->pending.next, struct fuse_req, list);  //从pending队列中获得下一个要发生的请求  
  26.     req->state = FUSE_REQ_READING;  
  27.     list_move(&req->list, &fc->io);  //将请求移动到正在进行IO的队列中  
  28.   
  29.     <SPAN style="COLOR: rgb(255,102,102)">in = &req->in</SPAN>;  
  30.     <SPAN style="COLOR: rgb(255,102,102)">reqsize = in->h.len;</SPAN>  
  31.     /* If request is too large, reply with an error and restart the read */  
  32.     ........  
  33.       
  34.     spin_unlock(&fc->lock);  
  35.     fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);  //为将请求拷贝到用户态做准备  
  36.     err = fuse_copy_one(&cs, &in->h, sizeof(in->h));   //将请求的包头拷贝到用户态  
  37.     if (!err)  
  38.         err = fuse_copy_args(&cs, in->numargs, in->argpages,  
  39.                      (struct fuse_arg *) in->args, 0);  //将请求的包体拷贝到用户态,如果包中有多个参数,则需要循环将参数拷完  
  40.     fuse_copy_finish(&cs);  //完成拷贝,释放内存   
  41.     spin_lock(&fc->lock);  
  42.     req->locked = 0;  
  43.     //对发送过程进行错误判断,省略   
  44.     ....  
  45.     if (!req->isreply)   //如果没有返回值,则结束请求  
  46.         request_end(fc, req);  
  47.     else {  
  48.         req->state = FUSE_REQ_SENT;  //如果这个请求需要用户态返回执行结果  
  49.         list_move_tail(&req->list, &fc->processing);  //则将请求转到processing队列中,交给fuse_dev_write来处理  
  50.         if (req->interrupted)  
  51.             queue_interrupt(fc, req);  
  52.         spin_unlock(&fc->lock);  
  53.     }  
  54.     return reqsize;  
  55.   
  56.  err_unlock:  
  57.     spin_unlock(&fc->lock);  
  58.     return err;  
  59. }  
static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
			      unsigned long nr_segs, loff_t pos)
{
        struct fuse_in *in; /* 用来表示用户态读入的内核 */
	//省略变量定义
	struct fuse_conn *fc = fuse_get_conn(file);   /* 获得fuse_conn结构体的指针 */
	if (!fc)
		return -EPERM;

 restart:
	spin_lock(&fc->lock);
	err = -EAGAIN;
	if ((file->f_flags & O_NONBLOCK) && fc->connected &&
	    !request_pending(fc))  //如果是非阻塞方式,则判断队列中有无等待处理请求,无请求则直接返回
		goto err_unlock;

	request_wait(fc);        //阻塞等待内核态的请求到了
        ......
	if (!list_empty(&fc->interrupts)) {  //判断是否有中断请求需要发送,有则先发中断请求
		req = list_entry(fc->interrupts.next, struct fuse_req,
				 intr_entry);
		return fuse_read_interrupt(fc, req, iov, nr_segs);
	}

	req = list_entry(fc->pending.next, struct fuse_req, list);  //从pending队列中获得下一个要发生的请求
	req->state = FUSE_REQ_READING;
	list_move(&req->list, &fc->io);  //将请求移动到正在进行IO的队列中

	in = &req->in;
	reqsize = in->h.len;
	/* If request is too large, reply with an error and restart the read */
	........
	
	spin_unlock(&fc->lock);
	fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);  //为将请求拷贝到用户态做准备
	err = fuse_copy_one(&cs, &in->h, sizeof(in->h));   //将请求的包头拷贝到用户态
	if (!err)
		err = fuse_copy_args(&cs, in->numargs, in->argpages,
				     (struct fuse_arg *) in->args, 0);  //将请求的包体拷贝到用户态,如果包中有多个参数,则需要循环将参数拷完
	fuse_copy_finish(&cs);  //完成拷贝,释放内存
	spin_lock(&fc->lock);
	req->locked = 0;
	//对发送过程进行错误判断,省略
	....
	if (!req->isreply)   //如果没有返回值,则结束请求
		request_end(fc, req);
	else {
		req->state = FUSE_REQ_SENT;  //如果这个请求需要用户态返回执行结果
		list_move_tail(&req->list, &fc->processing);  //则将请求转到processing队列中,交给fuse_dev_write来处理
		if (req->interrupted)
			queue_interrupt(fc, req);
		spin_unlock(&fc->lock);
	}
	return reqsize;

 err_unlock:
	spin_unlock(&fc->lock);
	return err;
}


 其中fuse_in结构体如下所示:

  1. /** The request input */  
  2. struct fuse_in {  
  3.     /** The request header  指令的头部*/  
  4.     struct fuse_in_header h;  
  5.       
  6.     /** True if the data for the last argument is in req->pages */  
  7.     unsigned argpages:1;  
  8.   
  9.     /** Number of arguments 这条指令中包含的参数个数*/  
  10.     unsigned numargs;  
  11.   
  12.     /** Array of arguments 参数的数组*/  
  13.     struct fuse_in_arg args[3];  
  14. };  
/** The request input */
struct fuse_in {
	/** The request header  指令的头部*/
	struct fuse_in_header h;
    
	/** True if the data for the last argument is in req->pages */
	unsigned argpages:1;

	/** Number of arguments 这条指令中包含的参数个数*/
	unsigned numargs;

	/** Array of arguments 参数的数组*/
	struct fuse_in_arg args[3];
};

此结构体中,包含的另外两个结构体

  1. struct fuse_in_header {  
  2.     __u32   len;      //包的长度   
  3.     __u32   opcode;  //操作码,用来表示操作类型  
  4.     __u64   unique;   //此包的唯一编号   
  5.     __u64   nodeid;   //表示操作文件节点的id,类似ino  
  6.     __u32   uid;  
  7.     __u32   gid;  
  8.     __u32   pid;  
  9.     __u32   padding;  //是否处于挂起状态 ???  
  10. };  
struct fuse_in_header {
	__u32	len;      //包的长度
	__u32	opcode;  //操作码,用来表示操作类型
	__u64	unique;   //此包的唯一编号
	__u64	nodeid;   //表示操作文件节点的id,类似ino
	__u32	uid;
	__u32	gid;
	__u32	pid;
	__u32	padding;  //是否处于挂起状态 ???
};

  1. /** One input argument of a request */  
  2. struct fuse_in_arg {  
  3.     unsigned size;    //参数的长度   
  4.     const void *value;  //参数的指针  
  5. };  
/** One input argument of a request */
struct fuse_in_arg {
	unsigned size;    //参数的长度
	const void *value;  //参数的指针
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值