void zfsctl_dir_destroy(void *ptr) { zfsvfs_t *zfsvfs = NULL; ASSERT(ptr); zfsvfs = (zfsvfs_t *) ptr; drop_nlink(LZFS_VTOI(zfsvfs->z_ctldir)); mutex_destroy(&(zfsvfs->z_ctldir->v_lock)); }
static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) { const unsigned char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; struct quad_buffer_head qbh; struct hpfs_dirent *de; struct inode *inode = dentry->d_inode; dnode_secno dno; int n_items = 0; int err; int r; hpfs_adjust_length(name, &len); hpfs_lock(dir->i_sb); err = -ENOENT; de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); if (!de) goto out; err = -EPERM; if (de->first) goto out1; err = -ENOTDIR; if (!de->directory) goto out1; hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items); err = -ENOTEMPTY; if (n_items) goto out1; r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); switch (r) { case 1: hpfs_error(dir->i_sb, "there was error when removing dirent"); err = -EFSERROR; break; case 2: err = -ENOSPC; break; default: drop_nlink(dir); clear_nlink(inode); err = 0; } goto out; out1: hpfs_brelse4(&qbh); out: if (!err) hpfs_update_directory_times(dir); hpfs_unlock(dir->i_sb); return err; }
static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) { struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); struct inode *inode = dentry->d_inode; struct qstr str; char name[32]; u32 cnid; int res; if (HFSPLUS_IS_RSRC(inode)) return -EPERM; mutex_lock(&sbi->vh_mutex); cnid = (u32)(unsigned long)dentry->d_fsdata; if (inode->i_ino == cnid && atomic_read(&HFSPLUS_I(inode)->opencnt)) { str.name = name; str.len = sprintf(name, "temp%lu", inode->i_ino); res = hfsplus_rename_cat(inode->i_ino, dir, &dentry->d_name, sbi->hidden_dir, &str); if (!res) inode->i_flags |= S_DEAD; goto out; } res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); if (res) goto out; if (inode->i_nlink > 0) drop_nlink(inode); if (inode->i_ino == cnid) clear_nlink(inode); if (!inode->i_nlink) { if (inode->i_ino != cnid) { sbi->file_count--; if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { res = hfsplus_delete_cat(inode->i_ino, sbi->hidden_dir, NULL); if (!res) hfsplus_delete_inode(inode); } else inode->i_flags |= S_DEAD; } else hfsplus_delete_inode(inode); } else sbi->file_count--; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); out: mutex_unlock(&sbi->vh_mutex); return res; }
static ssize_t efivarfs_file_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct efivar_entry *var = file->private_data; void *data; u32 attributes; struct inode *inode = file->f_mapping->host; unsigned long datasize = count - sizeof(attributes); ssize_t bytes = 0; bool set = false; if (count < sizeof(attributes)) return -EINVAL; if (copy_from_user(&attributes, userbuf, sizeof(attributes))) return -EFAULT; if (attributes & ~(EFI_VARIABLE_MASK)) return -EINVAL; data = kmalloc(datasize, GFP_KERNEL); if (!data) return -ENOMEM; if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) { bytes = -EFAULT; goto out; } bytes = efivar_entry_set_get_size(var, attributes, &datasize, data, &set); if (!set && bytes) { if (bytes == -ENOENT) bytes = -EIO; goto out; } if (bytes == -ENOENT) { drop_nlink(inode); d_delete(file->f_dentry); dput(file->f_dentry); } else { mutex_lock(&inode->i_mutex); i_size_write(inode, datasize + sizeof(attributes)); mutex_unlock(&inode->i_mutex); } bytes = count; out: kfree(data); return bytes; }
static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) { struct efivar_entry *var = dentry->d_inode->i_private; if (efivar_entry_delete(var)) return -EINVAL; drop_nlink(dentry->d_inode); dput(dentry); return 0; };
/** * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent * @sd: target sysfs_dirent * * Drop dentry for @sd. @sd must have been unlinked from its * parent on entry to this function such that it can't be looked * up anymore. * * @sd->s_dentry which is protected with sysfs_assoc_lock points * to the currently associated dentry but we're not holding a * reference to it and racing with dput(). Grab dcache_lock and * verify dentry before dropping it. If @sd->s_dentry is NULL or * dput() beats us, no need to bother. */ static void sysfs_drop_dentry(struct sysfs_dirent *sd) { struct dentry *dentry = NULL; struct inode *inode; /* We're not holding a reference to ->s_dentry dentry but the * field will stay valid as long as sysfs_assoc_lock is held. */ spin_lock(&sysfs_assoc_lock); spin_lock(&dcache_lock); /* drop dentry if it's there and dput() didn't kill it yet */ if (sd->s_dentry && sd->s_dentry->d_inode) { dentry = dget_locked(sd->s_dentry); spin_lock(&dentry->d_lock); __d_drop(dentry); spin_unlock(&dentry->d_lock); } spin_unlock(&dcache_lock); spin_unlock(&sysfs_assoc_lock); /* dentries for shadowed inodes are pinned, unpin */ if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) dput(dentry); dput(dentry); /* adjust nlink and update timestamp */ inode = ilookup(sysfs_sb, sd->s_ino); if (inode) { mutex_lock(&inode->i_mutex); inode->i_ctime = CURRENT_TIME; drop_nlink(inode); if (sysfs_type(sd) == SYSFS_DIR) drop_nlink(inode); mutex_unlock(&inode->i_mutex); iput(inode); } }
static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) { struct super_block *sb = dir->i_sb; struct inode *inode = dentry->d_inode; struct qstr str; char name[32]; u32 cnid; int res; if (HFSPLUS_IS_RSRC(inode)) return -EPERM; cnid = (u32)(unsigned long)dentry->d_fsdata; if (inode->i_ino == cnid && atomic_read(&HFSPLUS_I(inode).opencnt)) { str.name = name; str.len = sprintf(name, "temp%lu", inode->i_ino); res = hfsplus_rename_cat(inode->i_ino, dir, &dentry->d_name, HFSPLUS_SB(sb).hidden_dir, &str); if (!res) inode->i_flags |= S_DEAD; return res; } res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); if (res) return res; if (inode->i_nlink > 0) drop_nlink(inode); if (inode->i_ino == cnid) clear_nlink(inode); if (!inode->i_nlink) { if (inode->i_ino != cnid) { HFSPLUS_SB(sb).file_count--; if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { res = hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); if (!res) hfsplus_delete_inode(inode); } else inode->i_flags |= S_DEAD; } else hfsplus_delete_inode(inode); } else HFSPLUS_SB(sb).file_count--; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); return res; }
/** * sysfs_remove_one - remove sysfs_dirent from parent * @acxt: addrm context to use * @sd: sysfs_dirent to be added * * Mark @sd removed and drop nlink of parent inode if @sd is a * directory. @sd is NOT unlinked from the children list of the * parent. The caller is repsonsible for removing @sd from the * children list before calling this function. * * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be * passed the same @acxt as passed to sysfs_addrm_start(). * * LOCKING: * Determined by sysfs_addrm_start(). */ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED)); sd->s_flags |= SYSFS_FLAG_REMOVED; sd->s_sibling = acxt->removed; acxt->removed = sd; if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) drop_nlink(acxt->parent_inode); acxt->cnt++; }
/* destruction routines: unlink, rmdir */ static int coda_unlink(struct inode *dir, struct dentry *de) { int error; const char *name = de->d_name.name; int len = de->d_name.len; error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); if (error) return error; coda_dir_update_mtime(dir); drop_nlink(de->d_inode); return 0; }
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); struct jffs2_full_dirent *fd; int ret; for (fd = f->dents ; fd; fd = fd->next) { if (fd->ino) return -ENOTEMPTY; } ret = jffs2_unlink(dir_i, dentry); if (!ret) drop_nlink(dir_i); return ret; }
static int nilfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct nilfs_transaction_info ti; struct super_block *sb = dir->i_sb; unsigned int l = strlen(symname) + 1; struct inode *inode; int err; if (l > sb->s_blocksize) return -ENAMETOOLONG; err = nilfs_transaction_begin(dir->i_sb, &ti, 1); if (err) return err; inode = nilfs_new_inode(dir, S_IFLNK | S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; /* slow symlink */ inode->i_op = &nilfs_symlink_inode_operations; inode_nohighmem(inode); inode->i_mapping->a_ops = &nilfs_aops; err = page_symlink(inode, symname, l); if (err) goto out_fail; /* mark_inode_dirty(inode); */ /* page_symlink() do this */ err = nilfs_add_nondir(dentry, inode); out: if (!err) err = nilfs_transaction_commit(dir->i_sb); else nilfs_transaction_abort(dir->i_sb); return err; out_fail: drop_nlink(inode); nilfs_mark_inode_dirty(inode); unlock_new_inode(inode); iput(inode); goto out; }
int yramfs_dir_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; int err; DBG_PRINT("unlink for %s", dentry->d_name.name); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; err = yramfs_dir_remove_path(dir, dentry); if (err) { DBG_PRINT("remove path failed:%d", err); } drop_nlink(inode); dput(dentry); return 0; }
/* * hfs_unlink() * * This is the unlink() entry in the inode_operations structure for * regular HFS directories. The purpose is to delete an existing * file, given the inode for the parent directory and the name * (and its length) of the existing file. */ static int hfs_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode; int res; inode = dentry->d_inode; res = hfs_cat_delete(inode->i_ino, dir, &dentry->d_name); if (res) return res; drop_nlink(inode); hfs_delete_inode(inode); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); return res; }
static int pmfs_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct super_block *sb = dir->i_sb; int retval = -ENOMEM; struct pmfs_inode *pi = pmfs_get_inode(sb, inode); struct pmfs_inode *pidir; u64 pidir_tail = 0, pi_tail = 0; int invalidate = 0; timing_t unlink_time; PMFS_START_TIMING(unlink_t, unlink_time); pidir = pmfs_get_inode(sb, dir); if (!pidir) goto out; pmfs_dbgv("%s: %s, ino %lu, dir %lu\n", __func__, dentry->d_name.name, inode->i_ino, dir->i_ino); retval = pmfs_remove_entry(dentry, 0, 0, &pidir_tail); if (retval) goto out; inode->i_ctime = dir->i_ctime; if (inode->i_nlink == 1) invalidate = 1; if (inode->i_nlink) { drop_nlink(inode); } retval = pmfs_append_link_change_entry(sb, pi, inode, 0, &pi_tail); if (retval) goto out; pmfs_lite_transaction_for_time_and_link(sb, pi, pidir, pi_tail, pidir_tail, invalidate); PMFS_END_TIMING(unlink_t, unlink_time); return 0; out: pmfs_err(sb, "%s return %d\n", __func__, retval); PMFS_END_TIMING(unlink_t, unlink_time); return retval; }
static void au_do_hide(struct dentry *dentry) { struct inode *inode; inode = dentry->d_inode; if (inode) { if (!S_ISDIR(inode->i_mode)) { if (inode->i_nlink && !d_unhashed(dentry)) drop_nlink(inode); } else { clear_nlink(inode); /* stop next lookup */ inode->i_flags |= S_DEAD; } smp_mb(); /* necessary? */ } d_drop(dentry); }
static void au_do_hide(struct dentry *dentry) { struct inode *inode; if (d_really_is_positive(dentry)) { inode = d_inode(dentry); if (!d_is_dir(dentry)) { if (inode->i_nlink && !d_unhashed(dentry)) drop_nlink(inode); } else { clear_nlink(inode); /* stop next lookup */ inode->i_flags |= S_DEAD; } smp_mb(); /* necessary? */ } d_drop(dentry); }
/** * devpts_pty_kill -- remove inode form /dev/pts/ * @inode: inode of the slave to be removed * * This is an inverse operation of devpts_pty_new. */ void devpts_pty_kill(struct inode *inode) { struct super_block *sb = pts_sb_from_inode(inode); struct dentry *root = sb->s_root; struct dentry *dentry; BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); mutex_lock(&root->d_inode->i_mutex); dentry = d_find_alias(inode); drop_nlink(inode); d_delete(dentry); dput(dentry); /* d_alloc_name() in devpts_pty_new() */ dput(dentry); /* d_find_alias above */ mutex_unlock(&root->d_inode->i_mutex); }
int cifs_rmdir(struct inode *inode, struct dentry *direntry) { int rc = 0; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; struct cifsInodeInfo *cifsInode; cFYI(1, ("cifs_rmdir, inode = 0x%p", inode)); xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { drop_nlink(inode); spin_lock(&direntry->d_inode->i_lock); i_size_write(direntry->d_inode, 0); clear_nlink(direntry->d_inode); spin_unlock(&direntry->d_inode->i_lock); } cifsInode = CIFS_I(direntry->d_inode); cifsInode->time = 0; /* force revalidate to go get info when needed */ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); kfree(full_path); FreeXid(xid); return rc; }
/* return 0 on success; non-zero otherwise */ static int orangefs_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; int ret; gossip_debug(GOSSIP_NAME_DEBUG, "%s: called on %s\n" " (inode %pU): Parent is %pU | fs_id %d\n", __func__, dentry->d_name.name, get_khandle_from_ino(inode), &parent->refn.khandle, parent->refn.fs_id); new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE); if (!new_op) return -ENOMEM; new_op->upcall.req.remove.parent_refn = parent->refn; strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name, ORANGEFS_NAME_MAX); ret = service_operation(new_op, "orangefs_unlink", get_interruptible_flag(inode)); gossip_debug(GOSSIP_NAME_DEBUG, "%s: service_operation returned:%d:\n", __func__, ret); op_release(new_op); if (!ret) { drop_nlink(inode); SetMtimeFlag(parent); dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); mark_inode_dirty_sync(dir); } return ret; }
void devpts_pty_kill(struct tty_struct *tty) { struct inode *inode = tty->driver_data; struct super_block *sb = pts_sb_from_inode(inode); struct dentry *root = sb->s_root; struct dentry *dentry; BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); mutex_lock(&root->d_inode->i_mutex); dentry = d_find_alias(inode); drop_nlink(inode); d_delete(dentry); dput(dentry); dput(dentry); mutex_unlock(&root->d_inode->i_mutex); }
/* destruction routines: unlink, rmdir */ int coda_unlink(struct inode *dir, struct dentry *de) { int error; const char *name = de->d_name.name; int len = de->d_name.len; lock_kernel(); coda_vfs_stat.unlink++; error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); if ( error ) { unlock_kernel(); return error; } coda_dir_changed(dir, 0); drop_nlink(de->d_inode); unlock_kernel(); return 0; }
void capifs_free_ncci(struct dentry *dentry) { struct dentry *root = capifs_mnt->mnt_sb->s_root; struct inode *inode; if (!dentry) return; mutex_lock(&root->d_inode->i_mutex); inode = dentry->d_inode; if (inode) { drop_nlink(inode); d_delete(dentry); dput(dentry); } dput(dentry); mutex_unlock(&root->d_inode->i_mutex); simple_release_fs(&capifs_mnt, &capifs_mnt_count); }
static int gfs2_unlink_inode(struct gfs2_inode *dip, const struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct gfs2_inode *ip = GFS2_I(inode); int error; error = gfs2_dir_del(dip, dentry); if (error) return error; ip->i_entries = 0; inode->i_ctime = CURRENT_TIME; if (S_ISDIR(inode->i_mode)) clear_nlink(inode); else drop_nlink(inode); mark_inode_dirty(inode); if (inode->i_nlink == 0) gfs2_unlink_di(inode); return 0; }
static int fuse_unlink(struct inode *dir, struct dentry *entry) { int err; struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_req *req = fuse_get_req_nopages(fc); if (IS_ERR(req)) return PTR_ERR(req); req->in.h.opcode = FUSE_UNLINK; req->in.h.nodeid = get_node_id(dir); req->in.numargs = 1; req->in.args[0].size = entry->d_name.len + 1; req->in.args[0].value = entry->d_name.name; fuse_request_send(fc, req); err = req->out.h.error; fuse_put_request(fc, req); if (!err) { struct inode *inode = entry->d_inode; struct fuse_inode *fi = get_fuse_inode(inode); spin_lock(&fc->lock); fi->attr_version = ++fc->attr_version; /* * If i_nlink == 0 then unlink doesn't make sense, yet this can * happen if userspace filesystem is careless. It would be * difficult to enforce correct nlink usage so just ignore this * condition here */ if (inode->i_nlink > 0) drop_nlink(inode); spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); fuse_invalidate_entry_cache(entry); } else if (err == -EINTR) fuse_invalidate_entry(entry); return err; }
/** * gfs2_change_nlink - Change nlink count on inode * @ip: The GFS2 inode * @diff: The change in the nlink count required * * Returns: errno */ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) { struct buffer_head *dibh; u32 nlink; int error; BUG_ON(diff != 1 && diff != -1); nlink = ip->i_inode.i_nlink + diff; /* If we are reducing the nlink count, but the new value ends up being bigger than the old one, we must have underflowed. */ if (diff < 0 && nlink > ip->i_inode.i_nlink) { if (gfs2_consist_inode(ip)) gfs2_dinode_print(ip); return -EIO; } error = gfs2_meta_inode_buffer(ip, &dibh); if (error) return error; if (diff > 0) inc_nlink(&ip->i_inode); else drop_nlink(&ip->i_inode); ip->i_inode.i_ctime = CURRENT_TIME; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); mark_inode_dirty(&ip->i_inode); if (ip->i_inode.i_nlink == 0) gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ return error; }
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) { struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); struct jffs2_full_dirent *fd; int ret; uint32_t now = get_seconds(); for (fd = f->dents ; fd; fd = fd->next) { if (fd->ino) return -ENOTEMPTY; } ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, f, now); if (!ret) { dir_i->i_mtime = dir_i->i_ctime = ITIME(now); clear_nlink(dentry->d_inode); drop_nlink(dir_i); } return ret; }
static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { const unsigned char *old_name = old_dentry->d_name.name; unsigned old_len = old_dentry->d_name.len; const unsigned char *new_name = new_dentry->d_name.name; unsigned new_len = new_dentry->d_name.len; struct inode *i = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct quad_buffer_head qbh, qbh1; struct hpfs_dirent *dep, *nde; struct hpfs_dirent de; dnode_secno dno; int r; struct buffer_head *bh; struct fnode *fnode; int err; if ((err = hpfs_chk_name(new_name, &new_len))) return err; err = 0; hpfs_adjust_length(old_name, &old_len); hpfs_lock(i->i_sb); /* order doesn't matter, due to VFS exclusion */ /* Erm? Moving over the empty non-busy directory is perfectly legal */ if (new_inode && S_ISDIR(new_inode->i_mode)) { err = -EINVAL; goto end1; } if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) { hpfs_error(i->i_sb, "lookup succeeded but map dirent failed"); err = -ENOENT; goto end1; } copy_de(&de, dep); de.hidden = new_name[0] == '.'; if (new_inode) { int r; if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) { if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) { clear_nlink(new_inode); copy_de(nde, &de); memcpy(nde->name, new_name, new_len); hpfs_mark_4buffers_dirty(&qbh1); hpfs_brelse4(&qbh1); goto end; } hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent"); err = -EFSERROR; goto end1; } err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0; goto end1; } if (new_dir == old_dir) hpfs_brelse4(&qbh); if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) { if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!"); err = r == 1 ? -ENOSPC : -EFSERROR; if (new_dir != old_dir) hpfs_brelse4(&qbh); goto end1; } if (new_dir == old_dir) if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) { hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2"); err = -ENOENT; goto end1; } if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) { hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent"); err = r == 2 ? -ENOSPC : -EFSERROR; goto end1; } end: hpfs_i(i)->i_parent_dir = new_dir->i_ino; if (S_ISDIR(i->i_mode)) { inc_nlink(new_dir); drop_nlink(old_dir); } if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) { fnode->up = cpu_to_le32(new_dir->i_ino); fnode->len = new_len; memcpy(fnode->name, new_name, new_len>15?15:new_len); if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len); mark_buffer_dirty(bh); brelse(bh); } end1: if (!err) { hpfs_update_directory_times(old_dir); hpfs_update_directory_times(new_dir); } hpfs_unlock(i->i_sb); return err; }
static int hpfs_unlink(struct inode *dir, struct dentry *dentry) { const unsigned char *name = dentry->d_name.name; unsigned len = dentry->d_name.len; struct quad_buffer_head qbh; struct hpfs_dirent *de; struct inode *inode = dentry->d_inode; dnode_secno dno; int r; int rep = 0; int err; hpfs_lock(dir->i_sb); hpfs_adjust_length(name, &len); again: err = -ENOENT; de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); if (!de) goto out; err = -EPERM; if (de->first) goto out1; err = -EISDIR; if (de->directory) goto out1; r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); switch (r) { case 1: hpfs_error(dir->i_sb, "there was error when removing dirent"); err = -EFSERROR; break; case 2: /* no space for deleting, try to truncate file */ err = -ENOSPC; if (rep++) break; dentry_unhash(dentry); if (!d_unhashed(dentry)) { hpfs_unlock(dir->i_sb); return -ENOSPC; } if (generic_permission(inode, MAY_WRITE) || !S_ISREG(inode->i_mode) || get_write_access(inode)) { d_rehash(dentry); } else { struct iattr newattrs; /*printk("HPFS: truncating file before delete.\n");*/ newattrs.ia_size = 0; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; err = notify_change(dentry, &newattrs); put_write_access(inode); if (!err) goto again; } hpfs_unlock(dir->i_sb); return -ENOSPC; default: drop_nlink(inode); err = 0; } goto out; out1: hpfs_brelse4(&qbh); out: if (!err) hpfs_update_directory_times(dir); hpfs_unlock(dir->i_sb); return err; }
static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct page *dir_page = NULL; struct ufs_dir_entry * dir_de = NULL; struct page *old_page; struct ufs_dir_entry *old_de; int err = -ENOENT; old_de = ufs_find_entry(old_dir, old_dentry, &old_page); if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; dir_de = ufs_dotdot(old_inode, &dir_page); if (!dir_de) goto out_old; } if (new_inode) { struct page *new_page; struct ufs_dir_entry *new_de; err = -ENOTEMPTY; if (dir_de && !ufs_empty_dir(new_inode)) goto out_dir; err = -ENOENT; new_de = ufs_find_entry(new_dir, new_dentry, &new_page); if (!new_de) goto out_dir; inode_inc_link_count(old_inode); ufs_set_link(new_dir, new_de, new_page, old_inode); new_inode->i_ctime = CURRENT_TIME_SEC; if (dir_de) drop_nlink(new_inode); inode_dec_link_count(new_inode); } else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= UFS_LINK_MAX) goto out_dir; } inode_inc_link_count(old_inode); err = ufs_add_link(new_dentry, old_inode); if (err) { inode_dec_link_count(old_inode); goto out_dir; } if (dir_de) inode_inc_link_count(new_dir); } /* * Like most other Unix systems, set the ctime for inodes on a * rename. * inode_dec_link_count() will mark the inode dirty. */ old_inode->i_ctime = CURRENT_TIME_SEC; ufs_delete_entry(old_dir, old_de, old_page); inode_dec_link_count(old_inode); if (dir_de) { ufs_set_link(old_inode, dir_de, dir_page, new_dir); inode_dec_link_count(old_dir); } return 0; out_dir: if (dir_de) { kunmap(dir_page); page_cache_release(dir_page); } out_old: kunmap(old_page); page_cache_release(old_page); out: return err; }
static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct page *dir_page = NULL; struct nilfs_dir_entry *dir_de = NULL; struct page *old_page; struct nilfs_dir_entry *old_de; struct nilfs_transaction_info ti; int err; err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1); if (unlikely(err)) return err; err = -ENOENT; old_de = nilfs_find_entry(old_dir, old_dentry, &old_page); if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; dir_de = nilfs_dotdot(old_inode, &dir_page); if (!dir_de) goto out_old; } if (new_inode) { struct page *new_page; struct nilfs_dir_entry *new_de; err = -ENOTEMPTY; if (dir_de && !nilfs_empty_dir(new_inode)) goto out_dir; err = -ENOENT; new_de = nilfs_find_entry(new_dir, new_dentry, &new_page); if (!new_de) goto out_dir; inode_inc_link_count(old_inode); nilfs_set_link(new_dir, new_de, new_page, old_inode); new_inode->i_ctime = CURRENT_TIME; if (dir_de) drop_nlink(new_inode); inode_dec_link_count(new_inode); } else { if (dir_de) { err = -EMLINK; if (new_dir->i_nlink >= NILFS_LINK_MAX) goto out_dir; } inode_inc_link_count(old_inode); err = nilfs_add_link(new_dentry, old_inode); if (err) { inode_dec_link_count(old_inode); goto out_dir; } if (dir_de) inode_inc_link_count(new_dir); } /* * Like most other Unix systems, set the ctime for inodes on a * rename. * inode_dec_link_count() will mark the inode dirty. */ old_inode->i_ctime = CURRENT_TIME; nilfs_delete_entry(old_de, old_page); inode_dec_link_count(old_inode); if (dir_de) { nilfs_set_link(old_inode, dir_de, dir_page, new_dir); inode_dec_link_count(old_dir); } err = nilfs_transaction_commit(old_dir->i_sb); return err; out_dir: if (dir_de) { kunmap(dir_page); page_cache_release(dir_page); } out_old: kunmap(old_page); page_cache_release(old_page); out: nilfs_transaction_abort(old_dir->i_sb); return err; }