|
@@ -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
|