注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

widebright的个人空间

// 编程和生活

 
 
 

日志

 
 

linux 挂载文件系统mount操作和制作一个自定义文件系统的相关要点  

2011-11-09 13:25:39|  分类: linux相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

chinanunix 论坛上好像有人发了一篇文章
文件系统注册机mount过程分析 T-Bagwell


相关的函数有以下:

register_filesytem

file_system_type

do_mount 系统调用

do_new_mount 函数

do_kern_mount

do_add_mount

vfsmount结构

get_sb_bdev
ext4_fill_super 





----------------------------------------------------------
看一下内存文件系统
http://lxr.linux.no/linux+v3.1/Documentation/filesystems/tmpfs.txt

http://lxr.linux.no/linux+v3.1/drivers/base/devtmpfs.c
http://lxr.linux.no/linux+v3.1/mm/shmem.c



 427/*
 428 * Create devtmpfs instance, driver-core devices will add their device
 429 * nodes here.
 430 */
 431int __init devtmpfs_init(void)
 432{
 433        int err = register_filesystem(&dev_fs_type);
 434        if (err) {
 435                printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
 436                       "type %i\n", err);
 437                return err;
 438        }
 439
 440        thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
 441        if (!IS_ERR(thread)) {
 442                wait_for_completion(&setup_done);
 443        } else {
 444                err = PTR_ERR(thread);
 445                thread = NULL;
 446        }
 447
 448        if (err) {
 449                printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
 450                unregister_filesystem(&dev_fs_type);
 451                return err;
 452        }
 453
 454        printk(KERN_INFO "devtmpfs: initialized\n");
 455        return 0;
 456}
 457





   static struct file_system_type dev_fs_type = {
         .name = "devtmpfs",
         .mount = dev_mount,
         .kill_sb = kill_litter_super,
   };



 static struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
                      const char *dev_name, void *data)
 {
 #ifdef CONFIG_TMPFS
         return mount_single(fs_type, flags, data, shmem_fill_super);
  #else
          return mount_single(fs_type, flags, data, ramfs_fill_super);
  #endif
 }





shmem_fill_super  是一个函数,mount文件系统注册自定义文件操作的关键吧






2144int shmem_fill_super(struct super_block *sb, void *data, int silent)
2145{
2146        struct inode *inode;
2147        struct dentry *root;
2148        struct shmem_sb_info *sbinfo;
2149        int err = -ENOMEM;
2150
2151        /* Round up to L1_CACHE_BYTES to resist false sharing */
2152        sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info),
2153                                L1_CACHE_BYTES), GFP_KERNEL);
2154        if (!sbinfo)
2155                return -ENOMEM;
2156
2157        sbinfo->mode = S_IRWXUGO | S_ISVTX;
2158        sbinfo->uid = current_fsuid();
2159        sbinfo->gid = current_fsgid();
2160        sb->s_fs_info = sbinfo;
2161
2162#ifdef CONFIG_TMPFS
2163        /*
2164         * Per default we only allow half of the physical ram per
2165         * tmpfs instance, limiting inodes to one per page of lowmem;
2166         * but the internal instance is left unlimited.
2167         */
2168        if (!(sb->s_flags & MS_NOUSER)) {
2169                sbinfo->max_blocks = shmem_default_max_blocks();
2170                sbinfo->max_inodes = shmem_default_max_inodes();
2171                if (shmem_parse_options(data, sbinfo, false)) {
2172                        err = -EINVAL;
2173                        goto failed;
2174                }
2175        }
2176        sb->s_export_op = &shmem_export_ops;
2177#else
2178        sb->s_flags |= MS_NOUSER;
2179#endif
2180
2181        spin_lock_init(&sbinfo->stat_lock);
2182        if (percpu_counter_init(&sbinfo->used_blocks, 0))
2183                goto failed;
2184        sbinfo->free_inodes = sbinfo->max_inodes;
2185
2186        sb->s_maxbytes = MAX_LFS_FILESIZE;
2187        sb->s_blocksize = PAGE_CACHE_SIZE;
2188        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
2189        sb->s_magic = TMPFS_MAGIC;
2190        sb->s_op = &shmem_ops;
2191        sb->s_time_gran = 1;
2192#ifdef CONFIG_TMPFS_XATTR
2193        sb->s_xattr = shmem_xattr_handlers;
2194#endif
2195#ifdef CONFIG_TMPFS_POSIX_ACL
2196        sb->s_flags |= MS_POSIXACL;
2197#endif
2198        /////////////////那些什么自定义文件操作的回调都是放在inode里面返回的了
2199        inode = shmem_get_inode(sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);
2200        if (!inode)
2201                goto failed;
2202        inode->i_uid = sbinfo->uid;
2203        inode->i_gid = sbinfo->gid;
2204        root = d_alloc_root(inode);
2205        if (!root)
2206                goto failed_iput;
2207        sb->s_root = root;
2208        return 0;
2209
2210failed_iput:
2211        iput(inode);
2212failed:
2213        shmem_put_super(sb);
2214        return err;
2215}













1088static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
1089                                     int mode, dev_t dev, unsigned long flags)
1090{
1091        struct inode *inode;
1092        struct shmem_inode_info *info;
1093        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
1094
1095        if (shmem_reserve_inode(sb))
1096                return NULL;
1097
1098        inode = new_inode(sb);
1099        if (inode) {
1100                inode->i_ino = get_next_ino();
1101                inode_init_owner(inode, dir, mode);
1102                inode->i_blocks = 0;
1103                inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
1104                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
1105                inode->i_generation = get_seconds();
1106                info = SHMEM_I(inode);
1107                memset(info, 0, (char *)inode - (char *)info);
1108                spin_lock_init(&info->lock);
1109                info->flags = flags & VM_NORESERVE;
1110                INIT_LIST_HEAD(&info->swaplist);
1111                INIT_LIST_HEAD(&info->xattr_list);
1112                cache_no_acl(inode);
1113
1114                switch (mode & S_IFMT) {
1115                default:
1116                        inode->i_op = &shmem_special_inode_operations;
1117                        init_special_inode(inode, mode, dev);
1118                        break;
1119                case S_IFREG:
1120                        inode->i_mapping->a_ops = &shmem_aops;
1121                        inode->i_op = &shmem_inode_operations;
1122                        inode->i_fop = &shmem_file_operations;
1123                        mpol_shared_policy_init(&info->policy,
1124                                                 shmem_get_sbmpol(sbinfo));
1125                        break;
1126                case S_IFDIR:
1127                        inc_nlink(inode);
1128                        /* Some things misbehave if size == 0 on a directory */
1129                        inode->i_size = 2 * BOGO_DIRENT_SIZE;
1130                        inode->i_op = &shmem_dir_inode_operations;
1131                        inode->i_fop = &simple_dir_operations;
1132                        break;
1133                case S_IFLNK:
1134                        /*
1135                         * Must not load anything in the rbtree,
1136                         * mpol_free_shared_policy will not be called.
1137                         */
1138                        mpol_shared_policy_init(&info->policy, NULL);
1139                        break;
1140                }
1141        } else
1142                shmem_free_inode(sb);
1143        return inode;
1144}










2261static const struct address_space_operations shmem_aops = {
2262        .writepage      = shmem_writepage,
2263        .set_page_dirty = __set_page_dirty_no_writeback,
2264#ifdef CONFIG_TMPFS
2265        .write_begin    = shmem_write_begin,     ///写文件最终会调用到这个。
2266        .write_end      = shmem_write_end,
2267#endif
2268        .migratepage    = migrate_page,
2269        .error_remove_page = generic_error_remove_page,
2270};




2272static const struct file_operations shmem_file_operations = {
2273        .mmap           = shmem_mmap,
2274#ifdef CONFIG_TMPFS
2275        .llseek         = generic_file_llseek,
2276        .read           = do_sync_read,    ///////////这个其实调用的下面的shmem_file_aio_read
2277        .write          = do_sync_write,
2278        .aio_read       = shmem_file_aio_read,
2279        .aio_write      = generic_file_aio_write,
2280        .fsync          = noop_fsync,
2281        .splice_read    = shmem_file_splice_read,
2282        .splice_write   = generic_file_splice_write,
2283#endif
2284};
2285
2286static const struct inode_operations shmem_inode_operations = {
2287        .setattr        = shmem_setattr,
2288        .truncate_range = shmem_truncate_range,
2289#ifdef CONFIG_TMPFS_XATTR
2290        .setxattr       = shmem_setxattr,
2291        .getxattr       = shmem_getxattr,
2292        .listxattr      = shmem_listxattr,
2293        .removexattr    = shmem_removexattr,
2294#endif
2295};
2296
2297static const struct inode_operations shmem_dir_inode_operations = {
2298#ifdef CONFIG_TMPFS
2299        .create         = shmem_create,
2300        .lookup         = simple_lookup,
2301        .link           = shmem_link,
2302        .unlink         = shmem_unlink,
2303        .symlink        = shmem_symlink,
2304        .mkdir          = shmem_mkdir,
2305        .rmdir          = shmem_rmdir,
2306        .mknod          = shmem_mknod,
2307        .rename         = shmem_rename,
2308#endif
2309#ifdef CONFIG_TMPFS_XATTR
2310        .setxattr       = shmem_setxattr,
2311        .getxattr       = shmem_getxattr,
2312        .listxattr      = shmem_listxattr,
2313        .removexattr    = shmem_removexattr,
2314#endif
2315#ifdef CONFIG_TMPFS_POSIX_ACL
2316        .setattr        = shmem_setattr,
2317#endif
2318};
2319
2320static const struct inode_operations shmem_special_inode_operations = {
2321#ifdef CONFIG_TMPFS_XATTR
2322        .setxattr       = shmem_setxattr,
2323        .getxattr       = shmem_getxattr,
2324        .listxattr      = shmem_listxattr,
2325        .removexattr    = shmem_removexattr,
2326#endif
2327#ifdef CONFIG_TMPFS_POSIX_ACL
2328        .setattr        = shmem_setattr,
2329#endif
2330};
2331
2332static const struct super_operations shmem_ops = {
2333        .alloc_inode    = shmem_alloc_inode,
2334        .destroy_inode  = shmem_destroy_inode,
2335#ifdef CONFIG_TMPFS
2336        .statfs         = shmem_statfs,
2337        .remount_fs     = shmem_remount_fs,
2338        .show_options   = shmem_show_options,
2339#endif
2340        .evict_inode    = shmem_evict_inode,
2341        .drop_inode     = generic_delete_inode,
2342        .put_super      = shmem_put_super,
2343};
2344
2345static const struct vm_operations_struct shmem_vm_ops = {
2346        .fault          = shmem_fault,
2347#ifdef CONFIG_NUMA
2348        .set_policy     = shmem_set_policy,
2349        .get_policy     = shmem_get_policy,
2350#endif
2351};
2352
2353static struct dentry *shmem_mount(struct file_system_type *fs_type,
2354        int flags, const char *dev_name, void *data)
2355{
2356        return mount_nodev(fs_type, flags, data, shmem_fill_super);
2357}
2358
2359static struct file_system_type shmem_fs_type = {
2360        .owner          = THIS_MODULE,
2361        .name           = "tmpfs",
2362        .mount          = shmem_mount,
2363        .kill_sb        = kill_litter_super,
2364};
2365
2366int __init shmem_init(void)
2367{
2368        int error;
2369
2370        error = bdi_init(&shmem_backing_dev_info);
2371        if (error)
2372                goto out4;
2373
2374        error = shmem_init_inodecache();
2375        if (error)
2376                goto out3;
2377
2378        error = register_filesystem(&shmem_fs_type);
2379        if (error) {
2380                printk(KERN_ERR "Could not register tmpfs\n");
2381                goto out2;
2382        }
2383
2384        shm_mnt = vfs_kern_mount(&shmem_fs_type, MS_NOUSER,
2385                                 shmem_fs_type.name, NULL);
2386        if (IS_ERR(shm_mnt)) {
2387                error = PTR_ERR(shm_mnt);
2388                printk(KERN_ERR "Could not kern_mount tmpfs\n");
2389                goto out1;
2390        }
2391        return 0;
2392
2393out1:
2394        unregister_filesystem(&shmem_fs_type);
2395out2:
2396        shmem_destroy_inodecache();
2397out3:
2398        bdi_destroy(&shmem_backing_dev_info);
2399out4:
2400        shm_mnt = ERR_PTR(error);
2401        return error;
2402}








1177static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
1178{
1179        struct inode *inode = filp->f_path.dentry->d_inode;
1180        struct address_space *mapping = inode->i_mapping;
1181        pgoff_t index;
1182        unsigned long offset;
1183        enum sgp_type sgp = SGP_READ;
1184
1185        /*
1186         * Might this read be for a stacking filesystem?  Then when reading
1187         * holes of a sparse file, we actually need to allocate those pages,
1188         * and even mark them dirty, so it cannot exceed the max_blocks limit.
1189         */
1190        if (segment_eq(get_fs(), KERNEL_DS))
1191                sgp = SGP_DIRTY;
1192
1193        index = *ppos >> PAGE_CACHE_SHIFT;
1194        offset = *ppos & ~PAGE_CACHE_MASK;
1195
1196        for (;;) {
1197                struct page *page = NULL;
1198                pgoff_t end_index;
1199                unsigned long nr, ret;
1200                loff_t i_size = i_size_read(inode);
1201
1202                end_index = i_size >> PAGE_CACHE_SHIFT;
1203                if (index > end_index)
1204                        break;
1205                if (index == end_index) {
1206                        nr = i_size & ~PAGE_CACHE_MASK;
1207                        if (nr <= offset)
1208                                break;
1209                }
1210
1211                desc->error = shmem_getpage(inode, index, &page, sgp, NULL);
1212                if (desc->error) {
1213                        if (desc->error == -EINVAL)
1214                                desc->error = 0;
1215                        break;
1216                }
1217                if (page)
1218                        unlock_page(page);
1219
1220                /*
1221                 * We must evaluate after, since reads (unlike writes)
1222                 * are called without i_mutex protection against truncate
1223                 */
1224                nr = PAGE_CACHE_SIZE;
1225                i_size = i_size_read(inode);
1226                end_index = i_size >> PAGE_CACHE_SHIFT;
1227                if (index == end_index) {
1228                        nr = i_size & ~PAGE_CACHE_MASK;
1229                        if (nr <= offset) {
1230                                if (page)
1231                                        page_cache_release(page);
1232                                break;
1233                        }
1234                }
1235                nr -= offset;
1236
1237                if (page) {
1238                        /*
1239                         * If users can be writing to this page using arbitrary
1240                         * virtual addresses, take care about potential aliasing
1241                         * before reading the page on the kernel side.
1242                         */
1243                        if (mapping_writably_mapped(mapping))
1244                                flush_dcache_page(page);
1245                        /*
1246                         * Mark the page accessed if we read the beginning.
1247                         */
1248                        if (!offset)
1249                                mark_page_accessed(page);
1250                } else {
1251                        page = ZERO_PAGE(0);
1252                        page_cache_get(page);
1253                }
1254
1255                /*
1256                 * Ok, we have the page, and it's up-to-date, so
1257                 * now we can copy it to user space...
1258                 *
1259                 * The actor routine returns how many bytes were actually used..
1260                 * NOTE! This may not be the same as how much of a user buffer
1261                 * we filled up (we may be padding etc), so we can only update
1262                 * "pos" here (the actor routine has to update the user buffer
1263                 * pointers and the remaining count).
1264                 */
1265                ret = actor(desc, page, offset, nr);
1266                offset += ret;
1267                index += offset >> PAGE_CACHE_SHIFT;
1268                offset &= ~PAGE_CACHE_MASK;
1269
1270                page_cache_release(page);
1271                if (ret != nr || !desc->count)
1272                        break;
1273
1274                cond_resched();
1275        }
1276
1277        *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
1278        file_accessed(filp);
1279}
1280






另外可以看一下 nfs 文件系统的实现http://lxr.linux.no/linux+v3.1/fs/nfs/
  评论这张
 
阅读(1155)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017