/*
- * Copyright (C) 2005-2012 Junjiro R. Okajima
+ * Copyright (C) 2005-2013 Junjiro R. Okajima
*
* This program, aufs is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
{
int err;
aufs_bindex_t bwh, bindex, bstart;
- struct au_dtime dt;
- struct au_pin pin;
- struct path h_path;
struct inode *inode, *h_dir;
struct dentry *parent, *wh_dentry;
+ /* to reuduce stack size */
+ struct {
+ struct au_dtime dt;
+ struct au_pin pin;
+ struct path h_path;
+ } *a;
IMustLock(dir);
+ err = -ENOMEM;
+ a = kmalloc(sizeof(*a), GFP_NOFS);
+ if (unlikely(!a))
+ goto out;
+
err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
if (unlikely(err))
- goto out;
+ goto out_free;
err = au_d_hashed_positive(dentry);
if (unlikely(err))
goto out_unlock;
bindex = -1;
parent = dentry->d_parent; /* dir inode is locked */
di_write_lock_parent(parent);
- wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
+ &a->pin);
err = PTR_ERR(wh_dentry);
if (IS_ERR(wh_dentry))
goto out_parent;
- h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
- h_path.dentry = au_h_dptr(dentry, bstart);
- dget(h_path.dentry);
+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
+ a->h_path.dentry = au_h_dptr(dentry, bstart);
+ dget(a->h_path.dentry);
if (bindex == bstart) {
- h_dir = au_pinned_h_dir(&pin);
- err = vfsub_unlink(h_dir, &h_path, /*force*/0);
+ h_dir = au_pinned_h_dir(&a->pin);
+ err = vfsub_unlink(h_dir, &a->h_path, /*force*/0);
} else {
/* dir inode is locked */
h_dir = wh_dentry->d_parent->d_inode;
/* update target timestamps */
if (bindex == bstart) {
- vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
- inode->i_ctime = h_path.dentry->d_inode->i_ctime;
+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
+ /*ignore*/
+ inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
} else
/* todo: this timestamp may be reverted later */
inode->i_ctime = h_dir->i_ctime;
if (wh_dentry) {
int rerr;
- rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
+ &a->dt);
if (rerr)
err = rerr;
}
out_unpin:
- au_unpin(&pin);
+ au_unpin(&a->pin);
dput(wh_dentry);
- dput(h_path.dentry);
+ dput(a->h_path.dentry);
out_parent:
di_write_unlock(parent);
out_unlock:
aufs_read_unlock(dentry, AuLock_DW);
+out_free:
+ kfree(a);
out:
return err;
}
{
int err, rmdir_later;
aufs_bindex_t bwh, bindex, bstart;
- struct au_dtime dt;
- struct au_pin pin;
struct inode *inode;
struct dentry *parent, *wh_dentry, *h_dentry;
struct au_whtmp_rmdir *args;
+ /* to reuduce stack size */
+ struct {
+ struct au_dtime dt;
+ struct au_pin pin;
+ } *a;
IMustLock(dir);
+ err = -ENOMEM;
+ a = kmalloc(sizeof(*a), GFP_NOFS);
+ if (unlikely(!a))
+ goto out;
+
err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
if (unlikely(err))
- goto out;
+ goto out_free;
err = au_alive_dir(dentry);
if (unlikely(err))
goto out_unlock;
bstart = au_dbstart(dentry);
bwh = au_dbwh(dentry);
bindex = -1;
- wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
+ &a->pin);
err = PTR_ERR(wh_dentry);
if (IS_ERR(wh_dentry))
goto out_parent;
if (wh_dentry) {
int rerr;
- rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
+ &a->dt);
if (rerr)
err = rerr;
}
out_unpin:
- au_unpin(&pin);
+ au_unpin(&a->pin);
dput(wh_dentry);
dput(h_dentry);
out_parent:
au_whtmp_rmdir_free(args);
out_unlock:
aufs_read_unlock(dentry, AuLock_DW);
+out_free:
+ kfree(a);
out:
AuTraceErr(err);
return err;