コード例 #1
0
int main()
{
	struct dnode *p = NULL;
	
	printf("No. of Elements in DLL is %d ", d_count(p));	
	printf("\nAppending node in the end .");
	d_append(&p, 1);
	d_append(&p, 2);
	d_append(&p, 3);
	d_append(&p, 13);
	d_append(&p, 14);
	d_append(&p, 19);
	d_append(&p, 41);
	d_append(&p, 51);
	d_append(&p, 5);
	d_append(&p, 77);
	d_display(p);
	printf("\n");
	d_reversedisplay(p);
	printf("\nNo. of Elements in DLL is %d ", d_count(p));	
	printf("\nAppending node in the beginning.");
	
	d_addatbeg(&p, 666);
	d_addatbeg(&p, 777);
	d_addatbeg(&p, 888);
	d_addatbeg(&p, 999);
	d_display(p);
	printf("\n");
	d_reversedisplay(p);
	printf("\nNo. of Elements in DLL is %d ", d_count(p));	
	printf("\nAppending node in the position.");
	
	d_addafter(p, 40, 4);
	d_addafter(p, 10, 1);
	d_addafter(p, 60, 6);
	d_addafter(p, 40, 4);
	d_display(p);
	printf("\n");
	d_reversedisplay(p);
	printf("\nNo. of Elements in DLL is %d ", d_count(p));	
	
	printf("\nDeleting Nodes\n");
	
	d_delete(&p , 1000);
	d_delete(&p, 77);
	d_delete(&p, 13);
	d_display(p);
	printf("\n");
	d_reversedisplay(p);
	printf("\nNo. of Elements in DLL is %d \n", d_count(p));	
	

	
return 0;
}
コード例 #2
0
ファイル: map.obj.c プロジェクト: nardinan/miranda
d_define_method(map, insert)(struct s_object *self, struct s_object *key, struct s_object *value) {
  d_using(map);
  struct s_hash_bucket previous_content;
  struct s_object *retained_key = d_retain(key), *retained_value = d_retain(value);
  if (f_hash_insert(map_attributes->hash, (void *)retained_key, (void *)retained_value, d_true, &previous_content)) {
    /* if the value already exists, hash table keeps the previous key */
    d_delete(retained_key);
    d_delete((struct s_object *)previous_content.value);
  }
  return self;
}
コード例 #3
0
ファイル: inode.c プロジェクト: FIT-CVUT/clondike
static int ccfs_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct dentry *lower_dentry;
	struct dentry *lower_dir_dentry;
	int rc;

	lower_dentry = ccfs_get_nested_dentry(dentry);
	
	mdbg(INFO3,"RMDIR w/ lower_dentry->d_name.name = [%s]", lower_dentry->d_name.name);
	
	dget(dentry);
	lower_dir_dentry = lock_parent(lower_dentry);
	dget(lower_dentry);
	rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
	dput(lower_dentry);
	if (!rc)
		d_delete(lower_dentry);
	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink); //Fix for kernel 3.7.1 use function set_nlink by Jiri Rakosnik
	unlock_dir(lower_dir_dentry);
	if (!rc)
		d_drop(dentry);
	dput(dentry);
	return rc;
}
コード例 #4
0
/* drop all shared dentries from other superblocks */
void sdcardfs_drop_sb_icache(struct super_block *sb, unsigned long ino)
{
	struct inode *inode = ilookup(sb, ino);
	struct dentry *dentry, *dir_dentry;

	if (!inode)
		return;

	dentry = d_find_any_alias(inode);

	if (!dentry) {
		iput(inode);
		return;
	}

	dir_dentry = lock_parent(dentry);

	mutex_lock(&inode->i_mutex);
	set_nlink(inode, sdcardfs_lower_inode(inode)->i_nlink);
	d_drop(dentry);
	dont_mount(dentry);
	mutex_unlock(&inode->i_mutex);

	/* We don't d_delete() NFS sillyrenamed files--they still exist. */
	if (!(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
		fsnotify_link_count(inode);
		d_delete(dentry);
	}

	unlock_dir(dir_dentry);
	dput(dentry);
	iput(inode);
}
コード例 #5
0
ファイル: namei.c プロジェクト: chinnyannieb/empeg-hijack
int sysv_unlink(struct inode * dir, struct dentry * dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct sysv_dir_entry * de;

	retval = -ENOENT;
	inode = dentry->d_inode;
	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
	if (!bh || de->inode != inode->i_ino)
		goto end_unlink;
	if (!inode->i_nlink) {
		printk("Deleting nonexistent file (%s:%lu), %d\n",
		        kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
		inode->i_nlink=1;
	}
	de->inode = 0;
	mark_buffer_dirty(bh, 1);
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(dir);
	inode->i_nlink--;
	inode->i_ctime = dir->i_ctime;
	mark_inode_dirty(inode);
	d_delete(dentry);
	retval = 0;
end_unlink:
	brelse(bh);
	return retval;
}
コード例 #6
0
ファイル: map.obj.c プロジェクト: nardinan/miranda
d_define_method(map, remove)(struct s_object *self, struct s_object *key) {
  d_using(map);
  struct s_hash_bucket previous_content;
  if (f_hash_delete(map_attributes->hash, (void *)key, &previous_content))
    d_delete((struct s_object *)previous_content.value);
  return self;
}
コード例 #7
0
d_define_method(illuminable_bitmap, set_lights)(struct s_object *self, struct s_object *lights) {
  d_using(illuminable_bitmap);
  if (illuminable_bitmap_attributes->lights)
    d_delete(illuminable_bitmap_attributes->lights);
  illuminable_bitmap_attributes->lights = d_retain(lights);
  return self;
}
コード例 #8
0
static void sel_remove_entries(struct dentry *de)
{
	struct list_head *node;

	spin_lock(&de->d_lock);
	node = de->d_subdirs.next;
	while (node != &de->d_subdirs) {
		struct dentry *d = list_entry(node, struct dentry, d_u.d_child);

		spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
		list_del_init(node);

		if (d->d_inode) {
			dget_dlock(d);
			spin_unlock(&de->d_lock);
			spin_unlock(&d->d_lock);
			d_delete(d);
			simple_unlink(de->d_inode, d);
			dput(d);
			spin_lock(&de->d_lock);
		} else
			spin_unlock(&d->d_lock);
		node = de->d_subdirs.next;
	}

	spin_unlock(&de->d_lock);
}
コード例 #9
0
ファイル: dir.c プロジェクト: Mr-Aloof/wl500g
int coda_rmdir(struct inode *dir, struct dentry *de)
{
	const char *name = de->d_name.name;
	int len = de->d_name.len;
        int error;

	lock_kernel();
	coda_vfs_stat.rmdir++;

	if (!d_unhashed(de)) {
		unlock_kernel();
		return -EBUSY;
	}
	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);

        if ( error ) {
		unlock_kernel();
                return error;
        }

	coda_dir_changed(dir, -1);
	drop_nlink(de->d_inode);
	d_delete(de);
	unlock_kernel();

        return 0;
}
コード例 #10
0
ファイル: inode.c プロジェクト: Tigrouzen/k1099
/**
 * debugfs_remove - removes a file or directory from the debugfs filesystem
 * @dentry: a pointer to a the dentry of the file or directory to be
 *          removed.
 *
 * This function removes a file or directory in debugfs that was previously
 * created with a call to another debugfs function (like
 * debugfs_create_file() or variants thereof.)
 *
 * This function is required to be called in order for the file to be
 * removed, no automatic cleanup of files will happen when a module is
 * removed, you are responsible here.
 */
void debugfs_remove(struct dentry *dentry)
{
	struct dentry *parent;
	int ret = 0;
	
	if (!dentry)
		return;

	parent = dentry->d_parent;
	if (!parent || !parent->d_inode)
		return;

	mutex_lock(&parent->d_inode->i_mutex);
	if (debugfs_positive(dentry)) {
		if (dentry->d_inode) {
			dget(dentry);
			switch (dentry->d_inode->i_mode & S_IFMT) {
			case S_IFDIR:
				ret = simple_rmdir(parent->d_inode, dentry);
				break;
			case S_IFLNK:
				kfree(dentry->d_inode->i_private);
				/* fall through */
			default:
				simple_unlink(parent->d_inode, dentry);
				break;
			}
			if (!ret)
				d_delete(dentry);
			dput(dentry);
		}
	}
	mutex_unlock(&parent->d_inode->i_mutex);
	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
コード例 #11
0
static int remove_device_files(struct super_block *sb,
			       struct ipath_devdata *dd)
{
	struct dentry *dir, *root;
	char unit[10];
	int ret;

	root = dget(sb->s_root);
	mutex_lock(&root->d_inode->i_mutex);
	snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
	dir = lookup_one_len(unit, root, strlen(unit));

	if (IS_ERR(dir)) {
		ret = PTR_ERR(dir);
		printk(KERN_ERR "Lookup of %s failed\n", unit);
		goto bail;
	}

	remove_file(dir, "flash");
	remove_file(dir, "atomic_counters");
	d_delete(dir);
	ret = simple_rmdir(root->d_inode, dir);

bail:
	mutex_unlock(&root->d_inode->i_mutex);
	dput(root);
	return ret;
}
コード例 #12
0
ファイル: namei.c プロジェクト: dzavalishin/oskit
int
affs_unlink(struct inode *dir, struct dentry *dentry)
{
	int			 retval;
	struct buffer_head	*bh;
	unsigned long		 ino;
	struct inode		*inode;

	pr_debug("AFFS: unlink(dir=%ld,\"%.*s\")\n",dir->i_ino,
		 (int)dentry->d_name.len,dentry->d_name.name);

	retval  = -ENOENT;
	if (!(bh = affs_find_entry(dir,dentry,&ino)))
		goto unlink_done;

	inode  = dentry->d_inode;

	if ((retval = affs_remove_header(bh,inode)) < 0)
		goto unlink_done;
	
	inode->i_nlink = retval;
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	dir->i_version = ++event;
	mark_inode_dirty(inode);
	d_delete(dentry);
	mark_inode_dirty(dir);
	retval = 0;

unlink_done:
	affs_brelse(bh);
	return retval;
}
コード例 #13
0
static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
{
	int ret = 0;

	if (debugfs_positive(dentry)) {
		if (dentry->d_inode) {
			dget(dentry);
			switch (dentry->d_inode->i_mode & S_IFMT) {
			case S_IFDIR:
				ret = simple_rmdir(parent->d_inode, dentry);
				break;
			case S_IFLNK:
				kfree(dentry->d_inode->i_private);
				/* fall through */
			default:
				simple_unlink(parent->d_inode, dentry);
				break;
			}
			if (!ret)
				d_delete(dentry);
			dput(dentry);
		}
	}
	return ret;
}
コード例 #14
0
ファイル: inode.c プロジェクト: vps2fast/openvz-kernel
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);
	if (IS_ERR(dentry))
		goto out;

	if (dentry) {
		inode->i_nlink--;
		d_delete(dentry);
		dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
	}

	dput(dentry);		/* d_find_alias above */
out:
	mutex_unlock(&root->d_inode->i_mutex);
}
コード例 #15
0
ファイル: inode.c プロジェクト: guribe94/linux
/**
 * 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 dentry *dentry)
{
	WARN_ON_ONCE(dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC);

	dentry->d_fsdata = NULL;
	drop_nlink(dentry->d_inode);
	d_delete(dentry);
	dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
}
コード例 #16
0
ファイル: file.c プロジェクト: AICP/kernel_moto_shamu
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;
}
コード例 #17
0
ファイル: inode.c プロジェクト: qwerty1023/wive-rtnl-firmware
static void hypfs_remove(struct dentry *dentry)
{
	struct dentry *parent;

	parent = dentry->d_parent;
	if (S_ISDIR(dentry->d_inode->i_mode))
		simple_rmdir(parent->d_inode, dentry);
	else
		simple_unlink(parent->d_inode, dentry);
	d_delete(dentry);
	dput(dentry);
}
コード例 #18
0
ファイル: uiable.obj.c プロジェクト: haifenghuang/miranda
d_define_method(uiable, set)(struct s_object *self, struct s_object *drawable, enum e_uiable_components component) {
	d_using(uiable);
	if (uiable_attributes->background[component])
		d_delete(uiable_attributes->background[component]);
	uiable_attributes->background[component] = d_retain(drawable);
	if (uiable_attributes->last_blend != e_drawable_blend_undefined)
		d_call(uiable_attributes->background[component], m_drawable_set_blend, uiable_attributes->last_blend);
	d_call(uiable_attributes->background[component], m_drawable_set_maskRGB, (unsigned int)uiable_attributes->last_mask_R,
				(unsigned int)uiable_attributes->last_mask_G, (unsigned int)uiable_attributes->last_mask_B);
	d_call(uiable_attributes->background[component], m_drawable_set_maskA, (unsigned int)uiable_attributes->last_mask_A);
	return self;
}
コード例 #19
0
ファイル: container.obj.c プロジェクト: nardinan/miranda
d_define_method(container, del_drawable)(struct s_object *self, struct s_object *drawable) {
  d_using(container);
  struct s_container_drawable *current_container;
  d_foreach(&(container_attributes->entries), current_container, struct s_container_drawable)
    if (current_container->drawable == drawable) {
      f_list_delete(&(container_attributes->entries), (struct s_list_node *)current_container);
      d_delete(current_container->drawable);
      d_free(current_container);
      break;
    }
  return self;
}
コード例 #20
0
d_define_method(illuminable_bitmap, set_light_mask)(struct s_object *self, struct s_object *drawable_mask, enum e_illuminable_bitmap_sides side) {
  d_using(illuminable_bitmap);
  double mask_width, mask_height, image_width, image_height;
  if (illuminable_bitmap_attributes->drawable_mask[side])
    d_delete(illuminable_bitmap_attributes->drawable_mask[side]);
  illuminable_bitmap_attributes->drawable_mask[side] = d_retain(drawable_mask);
  d_call(illuminable_bitmap_attributes->drawable_mask[side], m_drawable_set_blend, e_drawable_blend_add);
  d_call(illuminable_bitmap_attributes->drawable_mask[side], m_drawable_get_dimension, &mask_width, &mask_height);
  d_call(self, m_drawable_get_dimension, &image_width, &image_height);
  d_assert((image_width == mask_width));
  d_assert((image_height == mask_height));
  return self;
}
コード例 #21
0
ファイル: xattr.c プロジェクト: 7799/linux
/* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
 * mutation ops aren't called during rename or splace, which are the
 * only other users of I_MUTEX_CHILD. It violates the ordering, but that's
 * better than allocating another subclass just for this code. */
static int xattr_unlink(struct inode *dir, struct dentry *dentry)
{
	int error;
	BUG_ON(!mutex_is_locked(&dir->i_mutex));

	mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
	error = dir->i_op->unlink(dir, dentry);
	mutex_unlock(&dentry->d_inode->i_mutex);

	if (!error)
		d_delete(dentry);
	return error;
}
コード例 #22
0
ファイル: dir.c プロジェクト: xricson/knoppix
static void remove_dir(struct dentry * d)
{
	struct dentry * parent = dget(d->d_parent);
	down(&parent->d_inode->i_sem);
	d_delete(d);
	if (d->d_inode)
		simple_rmdir(parent->d_inode,d);

	pr_debug(" o %s removing done (%d)\n",d->d_name.name,
		 atomic_read(&d->d_count));

	up(&parent->d_inode->i_sem);
	dput(parent);
}
コード例 #23
0
ファイル: xattr.c プロジェクト: AshishNamdev/linux
/*
 * We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
 * mutation ops aren't called during rename or splace, which are the
 * only other users of I_MUTEX_CHILD. It violates the ordering, but that's
 * better than allocating another subclass just for this code.
 */
static int xattr_unlink(struct inode *dir, struct dentry *dentry)
{
	int error;

	BUG_ON(!inode_is_locked(dir));

	inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD);
	error = dir->i_op->unlink(dir, dentry);
	inode_unlock(d_inode(dentry));

	if (!error)
		d_delete(dentry);
	return error;
}
コード例 #24
0
ファイル: inode.c プロジェクト: emelski/code.melski.net
STATIC int
base0fs_unlink(inode_t *dir, struct dentry *dentry)
{
        int err = 0;
        inode_t *lower_dir;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;

        print_entry_location();

        lower_dir = INODE_TO_LOWER(dir); /* CPW: Moved below print_entry_location */
        lower_dentry = base0fs_lower_dentry(dentry);

        BUG_ON(!lower_dentry);
        fist_checkinode(dir, "base0fs_unlink-dir");

        dget(dentry);
        lower_dir_dentry = base0fs_lock_parent(lower_dentry);


        /* avoid destroying the lower inode if the file is in use */
        dget(lower_dentry);
        err = VFS_UNLINK(lower_dir, lower_dentry);
        dput(lower_dentry);

        if (!err)			  /* vfs_unlink does that */
                d_delete(lower_dentry);

out_lock:
        fist_copy_attr_times(dir, lower_dir);
        /* propagate number of hard-links */
        dentry->d_inode->i_nlink = INODE_TO_LOWER(dentry->d_inode)->i_nlink;
    	fist_copy_attr_ctime(dentry->d_inode, dir);

        unlock_dir(lower_dir_dentry);

        /*
         * call d_drop so the system "forgets" about us
         */
        if (!err) {
                d_drop(dentry);
        }

        dput(dentry);

        fist_checkinode(dir, "post base0fs_unlink-dir");
        print_exit_status(err);
        return err;
}
コード例 #25
0
ファイル: capifs.c プロジェクト: mrtos/Logitech-Revue
void capifs_free_ncci(unsigned int number)
{
	struct dentry *dentry = get_node(number);

	if (!IS_ERR(dentry)) {
		struct inode *inode = dentry->d_inode;
		if (inode) {
			inode->i_nlink--;
			d_delete(dentry);
			dput(dentry);
		}
		dput(dentry);
	}
	mutex_unlock(&capifs_root->d_inode->i_mutex);
}
コード例 #26
0
ファイル: inode.c プロジェクト: GodFox/magx_kernel_xpixl
void devpts_pty_kill(int number)
{
	struct dentry *dentry = get_node(number);

	if (!IS_ERR(dentry)) {
		struct inode *inode = dentry->d_inode;
		if (inode) {
			inode->i_nlink--;
			d_delete(dentry);
			dput(dentry);
		}
		dput(dentry);
	}
	up(&devpts_root->d_inode->i_sem);
}
コード例 #27
0
ファイル: xattr.c プロジェクト: mb3dot/community-b3-kernel
static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
{
	int error;
	BUG_ON(!mutex_is_locked(&dir->i_mutex));

	reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
					I_MUTEX_CHILD, dir->i_sb);
	error = dir->i_op->rmdir(dir, dentry);
	if (!error)
		dentry->d_inode->i_flags |= S_DEAD;
	mutex_unlock(&dentry->d_inode->i_mutex);
	if (!error)
		d_delete(dentry);

	return error;
}
コード例 #28
0
ファイル: inode.c プロジェクト: 1059232202/linux
static void hypfs_remove(struct dentry *dentry)
{
	struct dentry *parent;

	parent = dentry->d_parent;
	inode_lock(d_inode(parent));
	if (simple_positive(dentry)) {
		if (d_is_dir(dentry))
			simple_rmdir(d_inode(parent), dentry);
		else
			simple_unlink(d_inode(parent), dentry);
	}
	d_delete(dentry);
	dput(dentry);
	inode_unlock(d_inode(parent));
}
コード例 #29
0
ファイル: inode.c プロジェクト: 03199618/linux
static void hypfs_remove(struct dentry *dentry)
{
	struct dentry *parent;

	parent = dentry->d_parent;
	mutex_lock(&parent->d_inode->i_mutex);
	if (hypfs_positive(dentry)) {
		if (S_ISDIR(dentry->d_inode->i_mode))
			simple_rmdir(parent->d_inode, dentry);
		else
			simple_unlink(parent->d_inode, dentry);
	}
	d_delete(dentry);
	dput(dentry);
	mutex_unlock(&parent->d_inode->i_mutex);
}
コード例 #30
0
int minix_unlink(struct inode * dir, struct dentry *dentry)
{
	int retval;
	struct inode * inode;
	struct buffer_head * bh;
	struct minix_dir_entry * de;

repeat:
	retval = -ENOENT;
	inode = NULL;
	bh = minix_find_entry(dir, dentry->d_name.name,
			      dentry->d_name.len, &de);
	if (!bh)
		goto end_unlink;
	inode = dentry->d_inode;

	retval = -EPERM;
	if (de->inode != inode->i_ino) {
		brelse(bh);
		current->counter = 0;
		schedule();
		goto repeat;
	}
	if (de->inode != inode->i_ino) {
		retval = -ENOENT;
		goto end_unlink;
	}
	if (!inode->i_nlink) {
		printk("Deleting nonexistent file (%s:%lu), %d\n",
			kdevname(inode->i_dev),
		       inode->i_ino, inode->i_nlink);
		inode->i_nlink=1;
	}
	de->inode = 0;
	dir->i_version = ++event;
	mark_buffer_dirty(bh, 1);
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	mark_inode_dirty(dir);
	inode->i_nlink--;
	inode->i_ctime = dir->i_ctime;
	mark_inode_dirty(inode);
	d_delete(dentry);	/* This also frees the inode */
	retval = 0;
end_unlink:
	brelse(bh);
	return retval;
}