⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfs.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
	size = PRESTO_REQHIGH - dentry->d_inode->i_size; 	error = presto_reserve_space(fset->fset_cache, size); 	if (error) { 		EXIT;		return error;	}        presto_getversion(&tgt_dir_ver, dir->d_inode);        presto_getversion(&old_dir_ver, dentry->d_inode);        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_RMDIR);        if ( IS_ERR(handle) ) {		presto_release_space(fset->fset_cache, size);                 printk("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");                return -ENOSPC;        }        DQUOT_INIT(dir->d_inode);        do_kml = presto_do_kml(info, dir->d_inode);        do_expect = presto_do_expect(info, dir->d_inode);        double_down(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);        d_unhash(dentry);        if (IS_DEADDIR(dir->d_inode))                error = -ENOENT;        else if (d_mountpoint(dentry))                error = -EBUSY;        else {                lock_kernel();                error = iops->rmdir(dir->d_inode, dentry);                unlock_kernel();                if (!error) {                        dentry->d_inode->i_flags |= S_DEAD;			error = presto_settime(fset, dir, info, 					       ATTR_CTIME | ATTR_MTIME);		}        }        double_up(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);        if (!error)                d_delete(dentry);        dput(dentry);        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x10);        if ( !error && do_kml )                error = presto_journal_rmdir(&rec, fset, dir, &tgt_dir_ver,                                             &old_dir_ver,                                             dentry->d_name.len,                                             dentry->d_name.name);        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x20);        if ( !error && do_expect )                 error = presto_write_last_rcvd(&rec, fset, info);        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x30);        EXIT;        presto_trans_commit(fset, handle);	presto_release_space(fset->fset_cache, size);         return error;}int lento_rmdir(const char *pathname, struct lento_vfs_context *info){        int error = 0;        char * name;        struct dentry *dentry;        struct presto_file_set *fset;        struct nameidata nd;        ENTRY;        name = getname(pathname);        if(IS_ERR(name))                return PTR_ERR(name);        if (path_init(name, LOOKUP_PARENT, &nd))                error = path_walk(name, &nd);        if (error)                goto exit;        switch(nd.last_type) {                case LAST_DOTDOT:                        error = -ENOTEMPTY;                        goto exit1;                case LAST_ROOT: case LAST_DOT:                        error = -EBUSY;                        goto exit1;        }        down(&nd.dentry->d_inode->i_sem);        dentry = lookup_hash(&nd.last, nd.dentry);        error = PTR_ERR(dentry);        if (!IS_ERR(dentry)) {                fset = presto_fset(dentry);                error = -EINVAL;                if ( !fset ) {                        printk("No fileset!\n");                        EXIT;                        goto exit_put;                }                error = presto_do_rmdir(fset, nd.dentry, dentry, info);        exit_put:                dput(dentry);        }        up(&nd.dentry->d_inode->i_sem);exit1:        EXIT;        path_release(&nd);exit:        EXIT;        putname(name);        return error;}int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,                    struct dentry *dentry, int mode, dev_t dev,                    struct lento_vfs_context *info){        struct rec_info rec;        int error = -EPERM;        struct presto_version tgt_dir_ver, new_node_ver;        struct inode_operations *iops;        void *handle;        ENTRY;        down(&dir->d_inode->i_zombie);	/* one KML entry */ 	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 	if (error) {		EXIT;        	up(&dir->d_inode->i_zombie);		return error;	}        if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) {                EXIT;                goto exit_lock;        }        error = may_create(dir->d_inode, dentry);        if (error) {                EXIT;                goto exit_lock;        }        error = -EPERM;        iops = filter_c2cdiops(fset->fset_cache->cache_filter);        if (!iops->mknod) {                EXIT;                goto exit_lock;        }        DQUOT_INIT(dir->d_inode);        lock_kernel();                error = -ENOSPC;        presto_getversion(&tgt_dir_ver, dir->d_inode);        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKNOD);        if ( IS_ERR(handle) ) {		presto_release_space(fset->fset_cache, PRESTO_REQHIGH);                 printk("presto_do_mknod: no space for transaction\n");                goto exit_lock2;        }        error = iops->mknod(dir->d_inode, dentry, mode, dev);        if (error) {                EXIT;                goto exit_commit;        }        if ( dentry->d_inode &&             dentry->d_inode->i_gid != presto_excluded_gid) {                struct presto_cache *cache = fset->fset_cache;                /* make it ours */                dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);                filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,                                         &presto_dentry_ops);                dentry->d_op = filter_c2udops(cache->cache_filter);                /* if Lento does this, we won't have data */                if ( ISLENTO(presto_c2m(cache)) ) {                        presto_set(dentry, PRESTO_ATTR);                } else {                        presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);                }        }        error = presto_settime(fset, dir, info, ATTR_MTIME);        if (error) {                 EXIT;        }        error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);        if (error) {                 EXIT;        }        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x10);        presto_getversion(&new_node_ver, dentry->d_inode);        if ( presto_do_kml(info, dentry->d_inode) )                error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,                                             &new_node_ver,                                             dentry->d_inode->i_mode,                                             MAJOR(dev), MINOR(dev) );        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x20);        if ( presto_do_expect(info, dentry->d_inode) )                 error = presto_write_last_rcvd(&rec, fset, info);        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x30);        EXIT; exit_commit:        presto_trans_commit(fset, handle); exit_lock2:        unlock_kernel(); exit_lock:	presto_release_space(fset->fset_cache, PRESTO_REQHIGH);         up(&dir->d_inode->i_zombie);        return error;}int lento_mknod(const char *filename, int mode, dev_t dev,                struct lento_vfs_context *info){        int error = 0;        char * tmp;        struct dentry * dentry;        struct nameidata nd;        struct presto_file_set *fset;        ENTRY;        if (S_ISDIR(mode))                return -EPERM;        tmp = getname(filename);        if (IS_ERR(tmp))                return PTR_ERR(tmp);        if (path_init(tmp, LOOKUP_PARENT, &nd))                error = path_walk(tmp, &nd);        if (error)                goto out;        dentry = lookup_create(&nd, 0);        error = PTR_ERR(dentry);        if (!IS_ERR(dentry)) {                fset = presto_fset(dentry);                error = -EINVAL;                if ( !fset ) {                        printk("No fileset!\n");                        EXIT;                        goto exit_put;                }                switch (mode & S_IFMT) {                case 0: case S_IFREG:                        error = -EOPNOTSUPP;                        break;                case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:                        error = presto_do_mknod(fset, nd.dentry, dentry,                                                 mode, dev, info);                        break;                case S_IFDIR:                        error = -EPERM;                        break;                default:                        error = -EINVAL;                }        exit_put:                dput(dentry);        }        up(&nd.dentry->d_inode->i_sem);        path_release(&nd);out:        putname(tmp);        return error;}static int do_rename(struct presto_file_set *fset,                     struct dentry *old_parent, struct dentry *old_dentry,                     struct dentry *new_parent, struct dentry *new_dentry,                     struct lento_vfs_context *info){        struct rec_info rec;        int error;        struct inode_operations *iops;        struct presto_version src_dir_ver, tgt_dir_ver;        void *handle;	int new_inode_unlink = 0;        struct inode *old_dir = old_parent->d_inode;        struct inode *new_dir = new_parent->d_inode;        ENTRY;        presto_getversion(&src_dir_ver, old_dir);        presto_getversion(&tgt_dir_ver, new_dir);        error = -EPERM;        iops = filter_c2cdiops(fset->fset_cache->cache_filter);        if (!iops || !iops->rename) {                EXIT;                return error;        }	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 	if (error) {		EXIT;		return error;	}        handle = presto_trans_start(fset, old_dir, PRESTO_OP_RENAME);        if ( IS_ERR(handle) ) {		presto_release_space(fset->fset_cache, PRESTO_REQHIGH);                 printk("presto_do_rename: no space for transaction\n");                return -ENOSPC;        }        if (new_dentry->d_inode && new_dentry->d_inode->i_nlink > 1) {                 dget(new_dentry);                 new_inode_unlink = 1;        }        error = iops->rename(old_dir, old_dentry, new_dir, new_dentry);        if (error) {                EXIT;                goto exit;        }        if (new_inode_unlink) {                 error = presto_settime(fset, old_dentry, info, ATTR_CTIME);                dput(old_dentry);                 if (error) {                         EXIT;                        goto exit;                }        }        error = presto_settime(fset, old_parent, info, ATTR_CTIME | ATTR_MTIME);        if (error) {                 EXIT;                goto exit;        }        error = presto_settime(fset, new_parent, info, ATTR_CTIME | ATTR_MTIME);        if (error) {                 EXIT;                goto exit;        }        /* XXX make a distinction between cross file set         * and intra file set renames here         */        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x10);        if ( presto_do_kml(info, old_dir) )                error = presto_journal_rename(&rec, fset, old_dentry, new_dentry,                                              &src_dir_ver, &tgt_dir_ver);        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x20);        if ( presto_do_expect(info, new_dir) )                 error = presto_write_last_rcvd(&rec, fset, info);        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x30);        EXIT;exit:        presto_trans_commit(fset, handle);	presto_release_space(fset->fset_cache, PRESTO_REQHIGH);         return error;}staticint presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,                      struct dentry *old_dentry, struct dentry *new_parent,                      struct dentry *new_dentry, struct lento_vfs_context *info){        int error;        struct inode *target;        struct inode *old_dir = old_parent->d_inode;        struct inode *new_dir = new_parent->d_inode;        if (old_dentry->d_inode == new_dentry->d_inode)                return 0;        error = may_delete(old_dir, old_dentry, 1);        if (error)                return error;        if (new_dir->i_dev != old_dir->i_dev)                return -EXDEV;        if (!new_dentry->d_inode)                error = may_create(new_dir, new_dentry);        else                error = may_delete(new_dir, new_dentry, 1);        if (error)                return error;        if (!old_dir->i_op || !old_dir->i_op->rename)                return -EPERM;        /*         * If we are going to change the parent - check write permissions,         * we'll need to flip '..'.         */        if (new_dir != old_dir) {                error = permission(old_dentry->d_inode, MAY_WRITE);        }        if (error)                return error;        DQUOT_INIT(old_dir);        DQUOT_INIT(new_dir);        down(&old_dir->i_sb->s_vfs_rename_sem);        error = -EINVAL;        if (is_subdir(new_dentry, old_dentry))                goto out_unlock;        target = new_dentry->d_inode;        if (target) { /* Hastur! Hastur! Hastur! */                triple_down(&old_dir->i_zombie,                            &new_dir->i_zombie,                            &target->i_zombie);                d_unhash(new_dentry);        } else                double_down(&old_dir->i_zombie,                            &new_dir->i_zombie);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -