/********************************************************************************************************* ** Function name: socket_attach ** Descriptions: 联结 socket ** input parameters: sock_fd socket 的私有文件描述符 ** output parameters: NONE ** Returned value: IO 系统文件描述符 *********************************************************************************************************/ int socket_attach(int sock_fd) { char path[PATH_MAX]; int fd; privinfo_t *priv; reg_t reg; file_t *file; int err; priv = kmalloc(sizeof(privinfo_t), GFP_KERNEL); if (priv != NULL) { priv->sock_fd = sock_fd; device_init(priv); sprintf(path, "/dev/socket%d", sock_fd); reg = interrupt_disable(); if (device_create(path, "socket", priv) < 0) { interrupt_resume(reg); kfree(priv); return -1; } fd = vfs_open(path, O_RDWR, 0666); if (fd < 0) { geterrno(err); vfs_unlink(path); seterrno(err); interrupt_resume(reg); kfree(priv); return -1; } file = vfs_get_file(fd); if (file == NULL) { geterrno(err); vfs_close(fd); vfs_unlink(path); seterrno(err); interrupt_resume(reg); kfree(priv); return -1; } file->type = VFS_FILE_TYPE_SOCK; vfs_put_file(file); lwip_socket_set_ctx(sock_fd, priv); interrupt_resume(reg); seterrno(0); return fd; } else { seterrno(ENOMEM); return -1; } }
/** * ecryptfs_do_create * @directory_inode: inode of the new file's dentry's parent in ecryptfs * @ecryptfs_dentry: New file's dentry in ecryptfs * @mode: The mode of the new file * * Creates the underlying file and the eCryptfs inode which will link to * it. It will also update the eCryptfs directory inode to mimic the * stat of the lower directory inode. * * Returns the new eCryptfs inode on success; an ERR_PTR on error condition */ static struct inode * ecryptfs_do_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, umode_t mode) { int rc; struct dentry *lower_dentry; struct dentry *lower_dir_dentry; struct inode *inode; lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); lower_dir_dentry = lock_parent(lower_dentry); rc = vfs_create(d_inode(lower_dir_dentry), lower_dentry, mode, true); if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc = [%d]\n", __func__, rc); inode = ERR_PTR(rc); goto out_lock; } inode = __ecryptfs_get_inode(d_inode(lower_dentry), directory_inode->i_sb); if (IS_ERR(inode)) { vfs_unlink(d_inode(lower_dir_dentry), lower_dentry, NULL); goto out_lock; } fsstack_copy_attr_times(directory_inode, d_inode(lower_dir_dentry)); fsstack_copy_inode_size(directory_inode, d_inode(lower_dir_dentry)); out_lock: unlock_dir(lower_dir_dentry); return inode; }
int main() { struct dentry *dentry = NULL; struct inode *inode = NULL; return vfs_unlink(inode, dentry, &inode); }
int do_unlink (struct inode *inode, const char *name, int len) { #if POST_20_KERNEL_F struct dentry *tmp_dent; #endif int ret_code; DOWN(&(inode->i_sem)); #if POST_20_KERNEL_F /* Grab a dentry for the file being unlinked. */ ret_code = ovlfs_inode_get_child_dentry(inode, name, len, &tmp_dent, OVLFS_DENT_GET_POSITIVE); if ( ret_code == 0 ) { /* Use the vfs_unlink function to do the dirty work. */ ret_code = vfs_unlink(inode, tmp_dent); dput(tmp_dent); } #else IMARK(inode); ret = inode->i_op->unlink(inode, fname, len); #endif UP(&(inode->i_sem)); return ret_code; }
static int mlog_vfs_destroy(struct mlog_handle *handle) { struct dentry *dentry = NULL; struct mlog_ctxt *ctxt = NULL; int ret = 0; struct vfsmount *mnt = NULL; MENTRY(); dentry = handle->mgh_file->f_dentry; mnt = handle->mgh_file->f_vfsmnt; ctxt = handle->mgh_ctxt; MASSERT(dentry->d_parent == ctxt->moc_dlog); mntget(mnt); dget(dentry); ret = mlog_vfs_close(handle); if (ret == 0) { mutex_lock(&dentry->d_parent->d_inode->i_mutex); ret = vfs_unlink(dentry->d_parent->d_inode, dentry); mutex_unlock(&dentry->d_parent->d_inode->i_mutex); } dput(dentry); mntput(mnt); MRETURN(ret); }
static int delete_partial_file(struct file *fp) { int rc; struct dentry *d = fp->f_path.dentry; struct inode *pi = fp->f_path.dentry->d_parent->d_inode; struct dentry *pd = NULL; dget(d); pd= dget_parent(d); mutex_lock_nested(&pd->d_inode->i_mutex,I_MUTEX_PARENT); rc= vfs_unlink(pi,d,NULL); if(rc){ printk("Error in vfs_unlink() \n"); rc= -ECANCELED; goto out; } out: mutex_unlock(&pd->d_inode->i_mutex); dput(pd); dput(d); printk("rc = %d\n",rc); return rc; }
static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) { int err; struct dentry *lower_dentry; struct inode *lower_dir_inode = sdcardfs_lower_inode(dir); struct dentry *lower_dir_dentry; struct path lower_path; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); const struct cred *saved_cred = NULL; int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive); if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) { printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n" " dentry: %s, task:%s\n", __func__, dentry->d_name.name, current->comm); err = -EACCES; goto out_eacces; } /* save current_cred and override it */ OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); sdcardfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_unlink(lower_dir_inode, lower_dentry); /* * Note: unlinking on top of NFS can cause silly-renamed files. * Trying to delete such files results in EBUSY from NFS * below. Silly-renamed files will get deleted by NFS later on, so * we just need to detect them here and treat such EBUSY errors as * if the upper file was successfully deleted. */ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) err = 0; if (err) goto out; fsstack_copy_attr_times(dir, lower_dir_inode); fsstack_copy_inode_size(dir, lower_dir_inode); set_nlink(dentry->d_inode, sdcardfs_lower_inode(dentry->d_inode)->i_nlink); dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); dput(lower_dentry); sdcardfs_put_lower_path(dentry, &lower_path); REVERT_CRED(saved_cred); out_eacces: return err; }
int main() { struct dentry *dentry = NULL; struct inode *inode = NULL; struct vfsmount *mnt = NULL; return vfs_unlink(inode, dentry, mnt); }
void __u2fs_unlink(struct work_struct *work) { struct sioq_args *args = container_of(work, struct sioq_args, work); struct unlink_args *u = &args->unlink; args->err = vfs_unlink(u->parent, u->dentry); complete(&args->comp); }
static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) { int err; struct dentry *newdentry; const struct cred *old_cred; struct cred *override_cred; /* FIXME: recheck lower dentry to see if whiteout is really needed */ err = -ENOMEM; override_cred = ovl_prepare_creds(dentry->d_sb); if (!override_cred) goto out; override_cred->fsuid = make_kuid(override_cred->user_ns, 0); if (!uid_valid(override_cred->fsuid)) override_cred->fsuid = GLOBAL_ROOT_UID; override_cred->fsgid = make_kgid(override_cred->user_ns, 0); if (!gid_valid(override_cred->fsgid)) override_cred->fsgid = GLOBAL_ROOT_GID; old_cred = override_creds(override_cred); newdentry = lookup_one_len(dentry->d_name.name, upperdir, dentry->d_name.len); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_put_cred; /* Just been removed within the same locked region */ WARN_ON(newdentry->d_inode); err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink); if (err) goto out_dput; ovl_dentry_version_inc(dentry->d_parent); err = ovl_do_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0); if (err) vfs_unlink(upperdir->d_inode, newdentry, NULL); out_dput: dput(newdentry); out_put_cred: revert_creds(old_cred); put_cred(override_cred); out: if (err) { /* * There's no way to recover from failure to whiteout. * What should we do? Log a big fat error and... ? */ pr_err("overlayfs: ERROR - failed to whiteout '%s'\n", dentry->d_name.name); } return err; }
static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry) { struct dentry *hidden_dentry; struct dentry *hidden_dir_dentry; int bindex; int err = 0; print_entry_location(); if ((err = unionfs_partial_lookup(dentry))) goto out; bindex = dbstart(dentry); hidden_dentry = dtohd_index(dentry, bindex); if (!hidden_dentry) goto out; hidden_dir_dentry = lock_parent(hidden_dentry); /* avoid destroying the hidden inode if the file is in use */ DGET(hidden_dentry); if (!(err = is_robranch_super(dentry->d_sb, bindex))) err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry); DPUT(hidden_dentry); fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); unlock_dir(hidden_dir_dentry); if (err) { if (!IS_COPYUP_ERR(err)) goto out; } if (err) { if (dbstart(dentry) == 0) { goto out; } err = create_whiteout(dentry, dbstart(dentry) - 1); } else if (dbopaque(dentry) != -1) { /* There is a hidden lower-priority file with the same name. */ err = create_whiteout(dentry, dbopaque(dentry)); } else { err = create_whiteout(dentry, dbstart(dentry)); } out: if (!err) dentry->d_inode->i_nlink--; /* We don't want to leave negative leftover dentries for revalidate. */ if (!err && (dbopaque(dentry) != -1)) update_bstart(dentry); print_exit_status(err); return err; }
/** * ecryptfs_do_create2 * @directory_inode: inode of the new file's dentry's parent in ecryptfs * @ecryptfs_dentry: New file's dentry in ecryptfs * @mode: The mode of the new file * @nd: nameidata of ecryptfs' parent's dentry & vfsmount * * Creates the underlying file and the eCryptfs inode which will link to * it. It will also update the eCryptfs directory inode to mimic the * stat of the lower directory inode. * * Returns the new eCryptfs inode on success; an ERR_PTR on error condition */ static struct inode * ecryptfs_do_create2(struct inode *directory_inode, struct dentry *ecryptfs_dentry, umode_t mode, struct nameidata *nd) { int rc; struct dentry *lower_dentry; struct dentry *lower_dir_dentry; struct vfsmount *lower_mnt = NULL; struct inode *inode = NULL; struct dentry *dentry_save = NULL; struct vfsmount *vfsmount_save = NULL; lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) goto out; lower_dir_dentry = lock_parent(lower_dentry); if (IS_ERR(lower_dir_dentry)) { ecryptfs_printk(KERN_ERR, "Error locking directory of " "dentry\n"); inode = ERR_CAST(lower_dir_dentry); goto out; } if (nd) { dentry_save = nd->path.dentry; vfsmount_save = nd->path.mnt; nd->path.dentry = lower_dentry; nd->path.mnt = lower_mnt; } rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, nd); if (nd) { nd->path.dentry = dentry_save; nd->path.mnt = vfsmount_save; } if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc = [%d]\n", __func__, rc); inode = ERR_PTR(rc); goto out_lock; } inode = __ecryptfs_get_inode(lower_dentry->d_inode, directory_inode->i_sb); if (IS_ERR(inode)) { vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); goto out_lock; } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: unlock_dir(lower_dir_dentry); out: return inode; }
void hwgfs_unregister( hwgfs_handle_t de) { struct inode *parent_inode = de->d_parent->d_inode; if (S_ISDIR(de->d_inode->i_mode)) vfs_rmdir(parent_inode, de); else vfs_unlink(parent_inode, de); }
/* sysfile_unlink - unlink file */ int sysfile_unlink(const char *__path) { int ret; char *path; if ((ret = copy_path(&path, __path)) != 0) { return ret; } ret = vfs_unlink(path); kfree(path); return ret; }
int remove_file(struct file *fp){ mm_segment_t oldfs=get_fs(); int ret; struct dentry *fp_dentry=NULL; set_fs(get_ds()); fp_dentry=fp->f_dentry; filp_close(fp,NULL); ret= vfs_unlink(fp_dentry->d_parent->d_inode,fp_dentry); set_fs(oldfs); return ret; }
void unlink_file_ghost(ghost_t *ghost) { struct file_ghost_data *ghost_data = ghost->data; struct dentry *dentry = ghost_data->file->f_dentry; struct inode *dir = dentry->d_parent->d_inode; BUG_ON(ghost_data->from_fd); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); vfs_unlink(dir, dentry); mutex_unlock(&dir->i_mutex); }
int sys_unlink (char *pathname) { error_t err = 0; if((err = vfs_unlink(current_task->vfs_cwd, pathname))) { current_thread->info.errno = (err < 0) ? -err : err; return -1; } return 0; }
int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; if (!dev_mnt) return 0; nodename = device_get_devnode(dev, NULL, &tmp); if (!nodename) return -ENOMEM; curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err) goto out; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); out: kfree(tmp); revert_creds(curr_cred); return err; }
/* * Unlink all destinations (if they exist) to the left of the left-most * source */ static int __rename_all_unlink(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, struct rename_info *info) { int bindex; struct dentry *unlink_dentry; struct dentry *unlink_dir_dentry; int err = 0; print_entry_location(); for (bindex = info->old_bstart - 1; bindex > info->new_bstart; bindex--) { unlink_dentry = dtohd_index(new_dentry, bindex); if (!unlink_dentry) continue; /* lock, unlink if possible, copyup times, unlock */ unlink_dir_dentry = lock_parent(unlink_dentry); if (!(err = is_robranch_super(old_dir->i_sb, bindex))) err = vfs_unlink(unlink_dir_dentry->d_inode, unlink_dentry); fist_copy_attr_times(new_dentry->d_parent->d_inode, unlink_dir_dentry->d_inode); new_dentry->d_parent->d_inode->i_nlink = get_nlinks(new_dentry->d_parent->d_inode); unlock_dir(unlink_dir_dentry); if (!err) { if (bindex != info->new_bstart) { DPUT(unlink_dentry); set_dtohd_index(new_dentry, bindex, NULL); } } else if (IS_COPYUP_ERR(err)) { if (info->isdir) { err = -EXDEV; break; } info->do_copyup = bindex - 1; err = 0; /* reset error */ } else break; /* err is set by is_ro_branch_super or vfs_unlink */ } print_exit_status(err); return err; }
static int wrapfs_unlink(struct inode *dir, struct dentry *dentry) { int err; struct dentry *lower_dentry; struct inode *lower_dir_inode = wrapfs_lower_inode(dir); struct dentry *lower_dir_dentry; struct path lower_path; if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE) DEBUG_MESG("Enter"); wrapfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_unlink(lower_dir_inode, lower_dentry); /* * Note: unlinking on top of NFS can cause silly-renamed files. * Trying to delete such files results in EBUSY from NFS * below. Silly-renamed files will get deleted by NFS later on, so * we just need to detect them here and treat such EBUSY errors as * if the upper file was successfully deleted. */ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) err = 0; if (err) goto out; fsstack_copy_attr_times(dir, lower_dir_inode); fsstack_copy_inode_size(dir, lower_dir_inode); set_nlink(dentry->d_inode, wrapfs_lower_inode(dentry->d_inode)->i_nlink); dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); dput(lower_dentry); wrapfs_put_lower_path(dentry, &lower_path); if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE) DEBUG_RETURN("Exit", err); return err; }
static int nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry) { int status; if (!S_ISREG(dir->d_inode->i_mode)) { printk("nfsd4: non-file found in client recovery directory\n"); return -EINVAL; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); status = vfs_unlink(dir->d_inode, dentry); mutex_unlock(&dir->d_inode->i_mutex); return status; }
static int handle_remove(const char *nodename, struct device *dev) { struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; err = kern_path_parent(nodename, &nd); if (err) return err; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = 0; newattrs.ia_gid = 0; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); return err; }
int sys_unlink (char *pathname) { error_t err = 0; struct ku_obj ku_path; KU_BUFF(ku_path, pathname); if((err = vfs_unlink(¤t_task->vfs_cwd, &ku_path))) { current_thread->info.errno = (err < 0) ? -err : err; return -1; } return 0; }
static int esdfs_unlink(struct inode *dir, struct dentry *dentry) { int err; struct dentry *lower_dentry; struct inode *lower_dir_inode = esdfs_lower_inode(dir); struct dentry *lower_dir_dentry; struct path lower_path; const struct cred *creds; creds = esdfs_override_creds(ESDFS_SB(dir->i_sb), NULL); if (!creds) return -ENOMEM; esdfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); err = mnt_want_write(lower_path.mnt); if (err) goto out_unlock; err = vfs_unlink(lower_dir_inode, lower_dentry); /* * Note: unlinking on top of NFS can cause silly-renamed files. * Trying to delete such files results in EBUSY from NFS * below. Silly-renamed files will get deleted by NFS later on, so * we just need to detect them here and treat such EBUSY errors as * if the upper file was successfully deleted. */ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) err = 0; if (err) goto out; fsstack_copy_attr_times(dir, lower_dir_inode); fsstack_copy_inode_size(dir, lower_dir_inode); set_nlink(dentry->d_inode, esdfs_lower_inode(dentry->d_inode)->i_nlink); dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ out: mnt_drop_write(lower_path.mnt); out_unlock: unlock_dir(lower_dir_dentry); dput(lower_dentry); esdfs_put_lower_path(dentry, &lower_path); esdfs_revert_creds(creds, NULL); return err; }
int remove_physical_file (struct file *file) { struct dentry *dentry; struct inode *dir; int res = 0; dentry = file->f_dentry; dir = dentry->d_parent->d_inode; res = vfs_unlink (dir, dentry); dput (dentry); put_filp (file); return res; }
int do_vfsub_unlink(struct inode *dir, struct dentry *dentry) { int err; LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry)); IMustLock(dir); /* vfs_unlink() locks inode */ lockdep_off(); err = vfs_unlink(dir, dentry); lockdep_on(); /* dir inode is locked */ if (!err) au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/ return err; }
static struct inode * scfs_do_create(struct inode *parent_inode, struct dentry *scfs_dentry, umode_t mode) { struct dentry *lower_file_dentry; struct dentry *lower_parent_dentry; struct inode *inode; int ret; SCFS_DEBUG_START; lower_file_dentry = scfs_lower_dentry(scfs_dentry); lower_parent_dentry = lock_parent(lower_file_dentry); if (IS_ERR(lower_parent_dentry)) { SCFS_PRINT_ERROR("lower_parent_dentry is invalid\n"); inode = ERR_CAST(lower_parent_dentry); goto out; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ret = vfs_create(lower_parent_dentry->d_inode, lower_file_dentry, mode, true); #else ret = vfs_create(lower_parent_dentry->d_inode, lower_file_dentry, mode, NULL); #endif if (ret) { SCFS_PRINT_ERROR("error in vfs_create, lower create, ret : %d\n", ret); inode = ERR_PTR(ret); goto unlock; } inode = _scfs_get_inode(lower_file_dentry->d_inode, parent_inode->i_sb); if (IS_ERR(inode)) { SCFS_PRINT_ERROR("error in get_inode, so lower thing will be unlinked\n"); vfs_unlink(lower_parent_dentry->d_inode, lower_file_dentry); goto unlock; } fsstack_copy_attr_times(parent_inode, lower_parent_dentry->d_inode); fsstack_copy_inode_size(parent_inode, lower_parent_dentry->d_inode); unlock: unlock_dir(lower_parent_dentry); out: SCFS_DEBUG_END; return inode; }
static int amfs_unlink(struct inode *dir, struct dentry *dentry) { int err; struct dentry *lower_dentry; struct inode *lower_dir_inode = amfs_lower_inode(dir); struct dentry *lower_dir_dentry; struct path lower_path; /*************Check if trying to delete pattern file**************/ if (dentry->d_inode->i_ino == AMFS_SB(dentry->d_sb)->inode_no) { err = -EPERM; goto out_err; } /* here I am not allowing user to delete pattern db file. This will only * work if pattern db lies inside the directory which is being mounted */ /**********************XATTR ENDS HERE**************/ amfs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); err = vfs_unlink(lower_dir_inode, lower_dentry, NULL); /* * Note: unlinking on top of NFS can cause silly-renamed files. * Trying to delete such files results in EBUSY from NFS * below. Silly-renamed files will get deleted by NFS later on, so * we just need to detect them here and treat such EBUSY errors as * if the upper file was successfully deleted. */ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) err = 0; if (err) goto out; fsstack_copy_attr_times(dir, lower_dir_inode); fsstack_copy_inode_size(dir, lower_dir_inode); set_nlink(dentry->d_inode, amfs_lower_inode(dentry->d_inode)->i_nlink); dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ out: unlock_dir(lower_dir_dentry); dput(lower_dentry); amfs_put_lower_path(dentry, &lower_path); out_err: return err; }
static int _rm_handler(int argc, char **argv) { if (argc < 2) { _vfs_usage(argv); return 1; } char *rm_name = argv[1]; printf("%s: unlink: %s\n", argv[0], rm_name); int res = vfs_unlink(rm_name); if (res < 0) { char errbuf[16]; _errno_string(res, (char *)errbuf, sizeof(errbuf)); printf("rm ERR: %s\n", errbuf); return 2; } return 0; }
static int cmd_vfs_rm(struct vmm_chardev *cdev, const char *path) { int rc; struct stat st; rc = vfs_stat(path, &st); if (rc) { vmm_cprintf(cdev, "Path %s does not exist.\n", path); return rc; } if (!(st.st_mode & S_IFREG)) { vmm_cprintf(cdev, "Path %s should be regular file.\n", path); return VMM_EINVALID; } return vfs_unlink(path); }