ext4: ->tmpfile() support
very similar to ext3 counterpart... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
46a1c2c7ae
commit
af51a2ac36
@ -2299,6 +2299,45 @@ retry:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ext4_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
|
{
|
||||||
|
handle_t *handle;
|
||||||
|
struct inode *inode;
|
||||||
|
int err, retries = 0;
|
||||||
|
|
||||||
|
dquot_initialize(dir);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
inode = ext4_new_inode_start_handle(dir, mode,
|
||||||
|
NULL, 0, NULL,
|
||||||
|
EXT4_HT_DIR,
|
||||||
|
EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
|
||||||
|
4 + EXT4_XATTR_TRANS_BLOCKS);
|
||||||
|
handle = ext4_journal_current_handle();
|
||||||
|
err = PTR_ERR(inode);
|
||||||
|
if (!IS_ERR(inode)) {
|
||||||
|
inode->i_op = &ext4_file_inode_operations;
|
||||||
|
inode->i_fop = &ext4_file_operations;
|
||||||
|
ext4_set_aops(inode);
|
||||||
|
err = ext4_orphan_add(handle, inode);
|
||||||
|
if (err)
|
||||||
|
goto err_drop_inode;
|
||||||
|
mark_inode_dirty(inode);
|
||||||
|
d_tmpfile(dentry, inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
|
}
|
||||||
|
if (handle)
|
||||||
|
ext4_journal_stop(handle);
|
||||||
|
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
|
||||||
|
goto retry;
|
||||||
|
return err;
|
||||||
|
err_drop_inode:
|
||||||
|
ext4_journal_stop(handle);
|
||||||
|
unlock_new_inode(inode);
|
||||||
|
iput(inode);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
|
struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
|
||||||
struct ext4_dir_entry_2 *de,
|
struct ext4_dir_entry_2 *de,
|
||||||
int blocksize, int csum_size,
|
int blocksize, int csum_size,
|
||||||
@ -2906,7 +2945,7 @@ static int ext4_link(struct dentry *old_dentry,
|
|||||||
retry:
|
retry:
|
||||||
handle = ext4_journal_start(dir, EXT4_HT_DIR,
|
handle = ext4_journal_start(dir, EXT4_HT_DIR,
|
||||||
(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
|
(EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
|
||||||
EXT4_INDEX_EXTRA_TRANS_BLOCKS));
|
EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1);
|
||||||
if (IS_ERR(handle))
|
if (IS_ERR(handle))
|
||||||
return PTR_ERR(handle);
|
return PTR_ERR(handle);
|
||||||
|
|
||||||
@ -2920,6 +2959,11 @@ retry:
|
|||||||
err = ext4_add_entry(handle, dentry, inode);
|
err = ext4_add_entry(handle, dentry, inode);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ext4_mark_inode_dirty(handle, inode);
|
ext4_mark_inode_dirty(handle, inode);
|
||||||
|
/* this can happen only for tmpfile being
|
||||||
|
* linked the first time
|
||||||
|
*/
|
||||||
|
if (inode->i_nlink == 1)
|
||||||
|
ext4_orphan_del(handle, inode);
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
} else {
|
} else {
|
||||||
drop_nlink(inode);
|
drop_nlink(inode);
|
||||||
@ -3172,6 +3216,7 @@ const struct inode_operations ext4_dir_inode_operations = {
|
|||||||
.mkdir = ext4_mkdir,
|
.mkdir = ext4_mkdir,
|
||||||
.rmdir = ext4_rmdir,
|
.rmdir = ext4_rmdir,
|
||||||
.mknod = ext4_mknod,
|
.mknod = ext4_mknod,
|
||||||
|
.tmpfile = ext4_tmpfile,
|
||||||
.rename = ext4_rename,
|
.rename = ext4_rename,
|
||||||
.setattr = ext4_setattr,
|
.setattr = ext4_setattr,
|
||||||
.setxattr = generic_setxattr,
|
.setxattr = generic_setxattr,
|
||||||
|
Loading…
Reference in New Issue
Block a user