Chinaunix首页 | 论坛 | 博客
  • 博客访问: 76373
  • 博文数量: 172
  • 博客积分: 2047
  • 博客等级: 大尉
  • 技术积分: 1745
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-19 15:23
文章分类

全部博文(172)

文章存档

2011年(72)

2010年(100)

我的朋友

分类: LINUX

2010-05-20 11:14:13

 在上文对操作的跟踪中,对于vfs提供的接口。fuse填充的静态情形知道了。其中主要是针对inode。那么inode初始化的整个情景如何.首先跟踪到直接相关的初始化函数。
 

static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
{
    inode->i_mode = attr->mode & S_IFMT;
    inode->i_size = attr->size;
    if (S_ISREG(inode->i_mode)) {
        fuse_init_common(inode);
        fuse_init_file_inode(inode);
    } else if (S_ISDIR(inode->i_mode))
        fuse_init_dir(inode);
    else if (S_ISLNK(inode->i_mode))
        fuse_init_symlink(inode);
    else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
         S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
        fuse_init_common(inode);
        init_special_inode(inode, inode->i_mode,
                 new_decode_dev(attr->rdev));
    } else
        BUG();
}

以上代码很清楚的表明针对inode的不同类型进行各种不同的初始化化过程。
有一般文件,目录,链接,其他文件(字符设备,块设备,管道,套接字)
可以看到基本上包含了我们一般使用的文件。
fuse_init_file_inode(inode) 和 fuse_init_dir(inode); 上文已经介绍过。
可以看出。该部分的初始化实际上是对inode操作接口的实例化。

函数被唯一调用


struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
            int generation, struct fuse_attr *attr)
{
    struct inode *inode;
    struct fuse_inode *fi;
    struct fuse_conn *fc = get_fuse_conn_super(sb);

 retry:
    inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
    if (!inode)
        return NULL;

    if ((inode->i_state & I_NEW)) {
        inode->i_flags |= S_NOATIME|S_NOCMTIME;
        inode->i_generation di;
        fuse_init_inode(inode, attr);
        unlock_new_inode(inode)
= generation;
        inode->i_data.backing_dev_info = &fc->b
;
    } else if ((inode->i_mode ^ attr->mode) & S_IFMT) {
        /* Inode has changed type, any I/O on the old should fail */
        make_bad_inode(inode);
        iput(inode);
        goto retry;
    }

    fi = get_fuse_inode(inode);
    spin_lock(&fc->lock);
    fi->nlookup ++;
    spin_unlock(&fc->lock);
    fuse_change_attributes(inode, attr);
    return inode;


顺序分析:
fuse_conn 是对fuse整个系统的一个控制结构。它把地址存放于super_block中。
用这种方式来把用户的某些数据存放到系统提供的结构中。可以在很多地方使用。

static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
{
    return sb->s_fs_info;
}


是系统内核的函数,用于从挂载的文件系统获取一个inode节点。

static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
{
    return container_of(inode, struct fuse_inode, inode);
}


container_of()
通过该宏可以获取到指向inode 结构的fuse_inode地址。

spin_lock(&fc->lock);
fi->nlookup ++;
spin_unlock(&fc->lock);
该处是典型的引用计数的增加。代表在该节点上搜索的次数。那么这是否可以代表该节点增在被使用。

fuse_change_attributes,该函数是对inode节点属性的填充,如节点号,用户id,组id等。

分析fuse_lookup

    该函数应该是相当关键的。该函数如何作用,要从vfs的调用来看。借助某位仁兄对vfs的分析一起来看该处的作用,先看:。然后就明白该函数在系统中的位置了。这样vfs 和fuse就对应起来了。首先弄清楚fuse_lookup 使用的上下文情景。
   从 


static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
                 struct nameidata *nd)
{
    int err;
    struct fuse_entry_out outarg;
    struct inode *inode = NULL;
    struct dentry *newent;
    struct fuse_conn *fc = get_fuse_conn(dir);
    struct fuse_req *req;
    struct fuse_req *forget_req;

    if (entry->d_name.len > FUSE_NAME_MAX)
        return ERR_PTR(-ENAMETOOLONG);

    req = fuse_get_req(fc);
    if (IS_ERR(req))
        return ERR_PTR(PTR_ERR(req));

    forget_req = fuse_get_req(fc);
    if (IS_ERR(forget_req)) {
        fuse_put_request(fc, req);
        return ERR_PTR(PTR_ERR(forget_req));
    }

    fuse_lookup_init(req, dir, entry, &outarg);
    request_send(fc, req);
    err = req->out.h.error;
    fuse_put_request(fc, req);
    /* Zero nodeid is same as -ENOENT, but with valid timeout */
    if (!err && outarg.nodeid &&
     (invalid_nodeid(outarg.nodeid) ||
     !fuse_valid_type(outarg.attr.mode)))
        err = -EIO;
    if (!err && outarg.nodeid) {
        inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
                 &outarg.attr);
        if (!inode) {
            fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
            return ERR_PTR(-ENOMEM);
        }
    }
    fuse_put_request(fc, forget_req);
    if (err && err != -ENOENT)
        return ERR_PTR(err);

    if (inode && S_ISDIR(inode->i_mode)) {
        mutex_lock(&fc->inst_mutex);
        newent = fuse_d_add_directory(entry, inode);
        mutex_unlock(&fc->inst_mutex);
        if (IS_ERR(newent)) {
            iput(inode);
            return newent;
        }
    } else
        newent = d_splice_alias(inode, entry);

    entry = newent ? newent : entry;
    entry->d_op = &fuse_dentry_operations;
    if (!err)
        fuse_change_timeout(entry, &outarg);
    else
        fuse_invalidate_entry_cache(entry);
    return newent;
}


fuse_get_req


    dentry = d_lookup(parent, name);
    if (!dentry) {
        struct dentry *new;

        /* Don't create child dentry for a dead directory. */
        dentry = ERR_PTR(-ENOENT);
        if (IS_DEADDIR(dir))
            goto out_unlock;

        new = d_alloc(parent, name);
        dentry = ERR_PTR(-ENOMEM);
        if (new) {
            dentry = dir->i_op->lookup(dir, new, nd);
            if (dentry)
                dput(new);
            else
                dentry = new;
        }
out_unlock:
        mutex_unlock(&dir->i_mutex);
        if (IS_ERR(dentry))
            goto fail;
        goto done;
    }


阅读(1455) | 评论(0) | 转发(0) |
0

上一篇:随记

下一篇:fuse struct

给主人留下些什么吧!~~