]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ext3 ->tmpfile() support
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 11 Jun 2013 08:52:02 +0000 (12:52 +0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:57:12 +0000 (12:57 +0400)
In this case we do need a bit more than usual, due to orphan
list handling.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/ext3/namei.c

index 692de13e35963a86dbbbab1cb246a3f2b74ba202..7523c61f796cae7757562054f9387263c8a7599b 100644 (file)
@@ -1762,6 +1762,45 @@ retry:
        return err;
 }
 
+static int ext3_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+       handle_t *handle;
+       struct inode *inode;
+       int err, retries = 0;
+
+       dquot_initialize(dir);
+
+retry:
+       handle = ext3_journal_start(dir, EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
+                         4 + EXT3_XATTR_TRANS_BLOCKS);
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+
+       inode = ext3_new_inode (handle, dir, NULL, mode);
+       err = PTR_ERR(inode);
+       if (!IS_ERR(inode)) {
+               inode->i_op = &ext3_file_inode_operations;
+               inode->i_fop = &ext3_file_operations;
+               ext3_set_aops(inode);
+               err = ext3_orphan_add(handle, inode);
+               if (err)
+                       goto err_drop_inode;
+               mark_inode_dirty(inode);
+               d_tmpfile(dentry, inode);
+               unlock_new_inode(inode);
+       }
+       ext3_journal_stop(handle);
+       if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
+               goto retry;
+       return err;
+err_drop_inode:
+       ext3_journal_stop(handle);
+       unlock_new_inode(inode);
+       iput(inode);
+       return err;
+}
+
 static int ext3_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
 {
        handle_t *handle;
@@ -2303,7 +2342,7 @@ static int ext3_link (struct dentry * old_dentry,
 
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS);
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 1);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2317,6 +2356,11 @@ retry:
        err = ext3_add_entry(handle, dentry, inode);
        if (!err) {
                ext3_mark_inode_dirty(handle, inode);
+               /* this can happen only for tmpfile being
+                * linked the first time
+                */
+               if (inode->i_nlink == 1)
+                       ext3_orphan_del(handle, inode);
                d_instantiate(dentry, inode);
        } else {
                drop_nlink(inode);
@@ -2519,6 +2563,7 @@ const struct inode_operations ext3_dir_inode_operations = {
        .mkdir          = ext3_mkdir,
        .rmdir          = ext3_rmdir,
        .mknod          = ext3_mknod,
+       .tmpfile        = ext3_tmpfile,
        .rename         = ext3_rename,
        .setattr        = ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR