📄 vfs.c
字号:
error = may_create(dir->d_inode, dentry); if (error) { EXIT; goto exit_pre_lock; } error = -EPERM; iops = filter_c2cdiops(fset->fset_cache->cache_filter); if (!iops->create) { EXIT; goto exit_pre_lock; } presto_getversion(&tgt_dir_ver, dir->d_inode); handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_CREATE); if ( IS_ERR(handle) ) { EXIT; presto_release_space(fset->fset_cache, PRESTO_REQHIGH); printk("presto_do_create: no space for transaction\n"); error=-ENOSPC; goto exit_pre_lock; } DQUOT_INIT(dir->d_inode); lock_kernel(); error = iops->create(dir->d_inode, dentry, mode); if (error) { EXIT; goto exit_lock; } if (dentry->d_inode && dentry->d_inode->i_gid != presto_excluded_gid) { struct presto_cache *cache = fset->fset_cache; /* was this already done? */ if ( !filter_c2cfiops(cache->cache_filter) ) filter_setup_file_ops(cache->cache_filter, dentry->d_inode, &presto_file_iops, &presto_file_fops); /* make the new inode ours */ dentry->d_inode->i_op = filter_c2ufiops(cache->cache_filter); dentry->d_inode->i_fop = filter_c2uffops(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 creates this file, 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_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit_lock; } error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit_lock; } presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x10); presto_getversion(&new_file_ver, dentry->d_inode); if ( presto_do_kml(info, dentry->d_inode) ) error = presto_journal_create(&rec, fset, dentry, &tgt_dir_ver, &new_file_ver, dentry->d_inode->i_mode); presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x20); if ( presto_do_expect(info, dentry->d_inode) ) error = presto_write_last_rcvd(&rec, fset, info); presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x30); EXIT; exit_lock: unlock_kernel(); presto_trans_commit(fset, handle); exit_pre_lock: presto_release_space(fset->fset_cache, PRESTO_REQHIGH); up(&dir->d_inode->i_zombie); return error;}/* from namei.c */static struct dentry *lookup_create(struct nameidata *nd, int is_dir){ struct dentry *dentry; down(&nd->dentry->d_inode->i_sem); dentry = ERR_PTR(-EEXIST); if (nd->last_type != LAST_NORM) goto fail; dentry = lookup_hash(&nd->last, nd->dentry); if (IS_ERR(dentry)) goto fail; if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) goto enoent; return dentry;enoent: dput(dentry); dentry = ERR_PTR(-ENOENT);fail: return dentry;}int lento_create(const char *name, int mode, struct lento_vfs_context *info){ int error; struct nameidata nd; char * pathname; struct dentry *dentry; struct presto_file_set *fset; ENTRY; pathname = getname(name); error = PTR_ERR(pathname); if (IS_ERR(pathname)) { EXIT; goto exit; } /* this looks up the parent */// if (path_init(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &nd)) if (path_init(pathname, LOOKUP_PARENT, &nd)) error = path_walk(pathname, &nd); if (error) { EXIT; goto exit; } dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); if (IS_ERR(dentry)) { EXIT; goto exit_lock; } fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto exit_lock; } error = presto_do_create(fset, dentry->d_parent, dentry, (mode&S_IALLUGO)|S_IFREG, info); EXIT; exit_lock: path_release (&nd); dput(dentry); up(&dentry->d_parent->d_inode->i_sem); putname(pathname);exit: return error;}int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry, struct dentry *dir, struct dentry *new_dentry, struct lento_vfs_context *info){ struct rec_info rec; struct inode *inode; int error; struct inode_operations *iops; struct presto_version tgt_dir_ver; struct presto_version new_link_ver; void *handle; down(&dir->d_inode->i_zombie); error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); if (error) { EXIT; up(&dir->d_inode->i_zombie); return error; } error = -ENOENT; inode = old_dentry->d_inode; if (!inode) goto exit_lock; error = may_create(dir->d_inode, new_dentry); if (error) goto exit_lock; error = -EXDEV; if (dir->d_inode->i_dev != inode->i_dev) goto exit_lock; /* * A link to an append-only or immutable file cannot be created. */ error = -EPERM; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { EXIT; goto exit_lock; } iops = filter_c2cdiops(fset->fset_cache->cache_filter); if (!iops->link) { EXIT; goto exit_lock; } presto_getversion(&tgt_dir_ver, dir->d_inode); handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_LINK); if ( IS_ERR(handle) ) { presto_release_space(fset->fset_cache, PRESTO_REQHIGH); printk("presto_do_link: no space for transaction\n"); return -ENOSPC; } DQUOT_INIT(dir->d_inode); lock_kernel(); error = iops->link(old_dentry, dir->d_inode, new_dentry); unlock_kernel(); if (error) { EXIT; goto exit_lock; } error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit_lock; } error = presto_settime(fset, new_dentry, info, ATTR_CTIME); if (error) { EXIT; goto exit_lock; } presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x10); presto_getversion(&new_link_ver, new_dentry->d_inode); if ( presto_do_kml(info, old_dentry->d_inode) ) error = presto_journal_link(&rec, fset, old_dentry, new_dentry, &tgt_dir_ver, &new_link_ver); presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x20); if ( presto_do_expect(info, old_dentry->d_inode) ) error = presto_write_last_rcvd(&rec, fset, info); presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x30); EXIT; presto_trans_commit(fset, handle);exit_lock: presto_release_space(fset->fset_cache, PRESTO_REQHIGH); up(&dir->d_inode->i_zombie); return error;}int lento_link(const char * oldname, const char * newname, struct lento_vfs_context *info){ int error; char * from; char * to; struct presto_file_set *fset; from = getname(oldname); if(IS_ERR(from)) return PTR_ERR(from); to = getname(newname); error = PTR_ERR(to); if (!IS_ERR(to)) { struct dentry *new_dentry; struct nameidata nd, old_nd; error = 0; if (path_init(from, LOOKUP_POSITIVE, &old_nd)) error = path_walk(from, &old_nd); if (error) goto exit; if (path_init(to, LOOKUP_PARENT, &nd)) error = path_walk(to, &nd); if (error) goto out; error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out; new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { fset = presto_fset(new_dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto out2; } error = presto_do_link(fset, old_nd.dentry, nd.dentry, new_dentry, info); dput(new_dentry); } out2: up(&nd.dentry->d_inode->i_sem); path_release(&nd); out: path_release(&old_nd); exit: putname(to); } putname(from); return error;}int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir, struct dentry *dentry, struct lento_vfs_context *info){ struct rec_info rec; int error; struct inode_operations *iops; struct presto_version tgt_dir_ver, old_file_ver; void *handle; int do_kml = 0, do_expect =0; int linkno = 0; ENTRY; down(&dir->d_inode->i_zombie); error = may_delete(dir->d_inode, dentry, 0); if (error) { EXIT; up(&dir->d_inode->i_zombie); return error; } error = -EPERM; iops = filter_c2cdiops(fset->fset_cache->cache_filter); if (!iops->unlink) { EXIT; up(&dir->d_inode->i_zombie); return error; } error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW); if (error) { EXIT; up(&dir->d_inode->i_zombie); return error; } presto_getversion(&tgt_dir_ver, dir->d_inode); presto_getversion(&old_file_ver, dentry->d_inode); handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_UNLINK); if ( IS_ERR(handle) ) { presto_release_space(fset->fset_cache, PRESTO_REQLOW); printk("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n"); up(&dir->d_inode->i_zombie); return -ENOSPC; } DQUOT_INIT(dir->d_inode); if (d_mountpoint(dentry)) error = -EBUSY; else { lock_kernel(); linkno = dentry->d_inode->i_nlink; if (linkno > 1) { dget(dentry); } do_kml = presto_do_kml(info, dir->d_inode); do_expect = presto_do_expect(info, dir->d_inode); error = iops->unlink(dir->d_inode, dentry); unlock_kernel(); if (!error) d_delete(dentry); } if (linkno > 1) { error = presto_settime(fset, dentry, info, ATTR_CTIME); dput(dentry); if (error) { EXIT; goto exit; } } error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit; } up(&dir->d_inode->i_zombie); if (error) { EXIT; goto exit; } presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x10); if ( do_kml ) { error = presto_journal_unlink(&rec, fset, dir, &tgt_dir_ver, &old_file_ver, dentry->d_name.len, dentry->d_name.name); } presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x20); if ( do_expect ) { error = presto_write_last_rcvd(&rec, fset, info); } presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x30); EXIT;exit:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -