📄 vfs.c
字号:
if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir)) error = -ENOENT; else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; else error = do_rename(fset, old_parent, old_dentry, new_parent, new_dentry, info); if (target) { if (!error) target->i_flags |= S_DEAD; triple_up(&old_dir->i_zombie, &new_dir->i_zombie, &target->i_zombie); if (d_unhashed(new_dentry)) d_rehash(new_dentry); dput(new_dentry); } else double_up(&old_dir->i_zombie, &new_dir->i_zombie); if (!error) d_move(old_dentry,new_dentry);out_unlock: up(&old_dir->i_sb->s_vfs_rename_sem); return error;}staticint presto_rename_other(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 inode *old_dir = old_parent->d_inode; struct inode *new_dir = new_parent->d_inode; int error; if (old_dentry->d_inode == new_dentry->d_inode) return 0; error = may_delete(old_dir, old_dentry, 0); 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, 0); if (error) return error; if (!old_dir->i_op || !old_dir->i_op->rename) return -EPERM; DQUOT_INIT(old_dir); DQUOT_INIT(new_dir); double_down(&old_dir->i_zombie, &new_dir->i_zombie); if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; else error = do_rename(fset, old_parent, old_dentry, new_parent, new_dentry, info); double_up(&old_dir->i_zombie, &new_dir->i_zombie); if (error) return error; /* The following d_move() should become unconditional */ if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) { d_move(old_dentry, new_dentry); } return 0;}int presto_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){ if (S_ISDIR(old_dentry->d_inode->i_mode)) return presto_rename_dir(fset, old_parent,old_dentry,new_parent, new_dentry, info); else return presto_rename_other(fset, old_parent, old_dentry, new_parent,new_dentry, info);}int lento_do_rename(const char *oldname, const char *newname, struct lento_vfs_context *info){ int error = 0; struct dentry * old_dir, * new_dir; struct dentry * old_dentry, *new_dentry; struct nameidata oldnd, newnd; struct presto_file_set *fset; ENTRY; if (path_init(oldname, LOOKUP_PARENT, &oldnd)) error = path_walk(oldname, &oldnd); if (error) goto exit; if (path_init(newname, LOOKUP_PARENT, &newnd)) error = path_walk(newname, &newnd); if (error) goto exit1; error = -EXDEV; if (oldnd.mnt != newnd.mnt) goto exit2; old_dir = oldnd.dentry; error = -EBUSY; if (oldnd.last_type != LAST_NORM) goto exit2; new_dir = newnd.dentry; if (newnd.last_type != LAST_NORM) goto exit2; double_lock(new_dir, old_dir); old_dentry = lookup_hash(&oldnd.last, old_dir); error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; /* source must exist */ error = -ENOENT; if (!old_dentry->d_inode) goto exit4; fset = presto_fset(old_dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto exit4; } /* unless the source is a directory trailing slashes give -ENOTDIR */ if (!S_ISDIR(old_dentry->d_inode->i_mode)) { error = -ENOTDIR; if (oldnd.last.name[oldnd.last.len]) goto exit4; if (newnd.last.name[newnd.last.len]) goto exit4; } new_dentry = lookup_hash(&newnd.last, new_dir); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto exit4; lock_kernel(); error = presto_do_rename(fset, old_dir, old_dentry, new_dir, new_dentry, info); unlock_kernel(); dput(new_dentry);exit4: dput(old_dentry);exit3: double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);exit2: path_release(&newnd);exit1: path_release(&oldnd);exit: return error;}int lento_rename(const char * oldname, const char * newname, struct lento_vfs_context *info){ int error; char * from; char * to; from = getname(oldname); if(IS_ERR(from)) return PTR_ERR(from); to = getname(newname); error = PTR_ERR(to); if (!IS_ERR(to)) { error = lento_do_rename(from,to, info); putname(to); } putname(from); return error;}struct dentry *presto_iopen(struct dentry *dentry, ino_t ino, unsigned int generation){ struct presto_file_set *fset; char name[48]; int error; ENTRY; /* see if we already have the dentry we want */ if (dentry->d_inode && dentry->d_inode->i_ino == ino && dentry->d_inode->i_generation == generation) { EXIT; return dentry; } /* Make sure we have a cache beneath us. We should always find at * least one dentry inside the cache (if it exists), otherwise not * even the cache root exists, or we passed in a bad name. */ fset = presto_fset(dentry); error = -EINVAL; if (!fset) { printk("No fileset for %*s!\n", dentry->d_name.len, dentry->d_name.name); EXIT; dput(dentry); return ERR_PTR(error); } dput(dentry); sprintf(name, "%s%#lx%c%#x", PRESTO_ILOOKUP_MAGIC, ino, PRESTO_ILOOKUP_SEP, generation); CDEBUG(D_PIOCTL, "opening %ld by number (as %s)\n", ino, name); return lookup_one_len(name, fset->fset_mtpt, strlen(name));}static struct file *presto_filp_dopen(struct dentry *dentry, int flags){ struct file *f; struct inode *inode; int flag, error; ENTRY; error = -ENFILE; f = get_empty_filp(); if (!f) { CDEBUG(D_PIOCTL, "error getting file pointer\n"); EXIT; goto out; } f->f_flags = flag = flags; f->f_mode = (flag+1) & O_ACCMODE; inode = dentry->d_inode; if (f->f_mode & FMODE_WRITE) { error = get_write_access(inode); if (error) { CDEBUG(D_PIOCTL, "error getting write access\n"); EXIT; goto cleanup_file; } } f->f_dentry = dentry; f->f_pos = 0; f->f_reada = 0; f->f_op = NULL; if (inode->i_op) /* XXX should we set to presto ops, or leave at cache ops? */ f->f_op = inode->i_fop; if (f->f_op && f->f_op->open) { error = f->f_op->open(inode, f); if (error) { CDEBUG(D_PIOCTL, "error calling cache 'open'\n"); EXIT; goto cleanup_all; } } f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); return f;cleanup_all: if (f->f_mode & FMODE_WRITE) put_write_access(inode);cleanup_file: put_filp(f);out: return ERR_PTR(error);}/* Open an inode by number. We pass in the cache root name (or a subdirectory * from the cache that is guaranteed to exist) to be able to access the cache. */int lento_iopen(const char *name, ino_t ino, unsigned int generation, int flags){ char * tmp; struct dentry *dentry; struct nameidata nd; int fd; int error; ENTRY; CDEBUG(D_PIOCTL, "open %s:inode %#lx (%ld), generation %x (%d), flags %d \n", name, ino, ino, generation, generation, flags); /* We don't allow creation of files by number only, as it would * lead to a dangling files not in any directory. We could also * just turn off the flag and ignore it. */ if (flags & O_CREAT) { printk(KERN_WARNING __FUNCTION__ ": create file by inode number (%ld) not allowed\n",ino); EXIT; return -EACCES; } tmp = getname(name); if (IS_ERR(tmp)) { EXIT; return PTR_ERR(tmp); } lock_kernel();again: /* look the named file or a parent directory so we can get the cache */ error = presto_walk(tmp, &nd); if ( error && error != -ENOENT ) { EXIT; return error; } if (error == -ENOENT) dentry = NULL; else dentry = nd.dentry; /* we didn't find the named file, so see if a parent exists */ if (!dentry) { char *slash; slash = strrchr(tmp, '/'); if (slash && slash != tmp) { *slash = '\0'; path_release(&nd); goto again; } /* we should never get here... */ CDEBUG(D_PIOCTL, "no more path components to try!\n"); fd = -ENOENT; goto exit; } CDEBUG(D_PIOCTL, "returned dentry %p\n", dentry); dentry = presto_iopen(dentry, ino, generation); fd = PTR_ERR(dentry); if (IS_ERR(dentry)) { EXIT; goto exit; } /* XXX start of code that might be replaced by something like: * if (flags & (O_WRONLY | O_RDWR)) { * error = get_write_access(dentry->d_inode); * if (error) { * EXIT; * goto cleanup_dput; * } * } * fd = open_dentry(dentry, flags); * * including the presto_filp_dopen() function (check dget counts!) */ fd = get_unused_fd(); if (fd < 0) { EXIT; goto cleanup_dput; } { int error; struct file * f = presto_filp_dopen(dentry, flags); error = PTR_ERR(f); if (IS_ERR(f)) { put_unused_fd(fd); fd = error; EXIT; goto cleanup_dput; } fd_install(fd, f); } /* end of code that might be replaced by open_dentry */ EXIT;exit: unlock_kernel(); path_release(&nd); putname(tmp); return fd;cleanup_dput: putname(&nd); goto exit;}int lento_close(unsigned int fd, struct lento_vfs_context *info){ struct rec_info rec; int error; struct file * filp; struct dentry *dentry; int do_kml, do_expect; ENTRY; lock_kernel(); error = -EBADF; filp = fcheck(fd); if (filp) { struct files_struct * files = current->files; dentry = filp->f_dentry; dget(dentry); do_kml = presto_do_kml(info, dentry->d_inode); do_expect = presto_do_expect
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -