Avoided double copy of dir when closing a file in an open dir

PERMISSION_HANDLING_BRANCH
jpandre 2009-12-10 10:04:53 +00:00
parent 91a3909048
commit 758a99ea87
4 changed files with 50 additions and 20 deletions

View File

@ -177,6 +177,7 @@ extern ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol);
extern ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref);
extern int ntfs_inode_close(ntfs_inode *ni);
extern int ntfs_inode_close_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni);
extern ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni,
const MFT_REF mref);

View File

@ -2068,8 +2068,10 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
longname, longlen,
FILE_NAME_WIN32_AND_DOS) >= 0))
res = 0;
ntfs_inode_close(ni);
ntfs_inode_close(dir_ni);
if (ntfs_inode_close_in_dir(ni,dir_ni) && !res)
res = -1;
if (ntfs_inode_close(dir_ni) && !res)
res = -1;
}
} else
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
@ -2088,13 +2090,17 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
longname, longlen,
FILE_NAME_WIN32))
res = 0;
ntfs_inode_close(ni);
if (ntfs_inode_close_in_dir(ni,
dir_ni)
&& !res)
res = -1;
}
ntfs_inode_close(dir_ni);
if (ntfs_inode_close(dir_ni) && !res)
res = -1;
}
}
} else {
ntfs_inode_close(ni);
ntfs_inode_close_in_dir(ni,dir_ni);
ntfs_inode_close(dir_ni);
}
return (res);

View File

@ -5,6 +5,7 @@
* Copyright (c) 2002-2008 Szabolcs Szakacsits
* Copyright (c) 2004-2007 Yura Pakhuchiy
* Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2009 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -595,7 +596,7 @@ static int ntfs_inode_sync_standard_information(ntfs_inode *ni)
*
* Return 0 on success or -1 on error with errno set to the error code.
*/
static int ntfs_inode_sync_file_name(ntfs_inode *ni)
static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
{
ntfs_attr_search_ctx *ctx = NULL;
ntfs_index_context *ictx;
@ -625,7 +626,10 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni)
*/
index_ni = ni;
} else
index_ni = ntfs_inode_open(ni->vol,
if (dir_ni)
index_ni = dir_ni;
else
index_ni = ntfs_inode_open(ni->vol,
le64_to_cpu(fn->parent_directory));
if (!index_ni) {
if (!err)
@ -640,7 +644,8 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni)
err = errno;
ntfs_log_perror("Failed to get index ctx, inode %lld",
(long long)index_ni->mft_no);
if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
if ((ni != index_ni) && !dir_ni
&& ntfs_inode_close(index_ni) && !err)
err = errno;
continue;
}
@ -678,7 +683,8 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni)
}
ntfs_index_entry_mark_dirty(ictx);
ntfs_index_ctx_put(ictx);
if ((ni != index_ni) && ntfs_inode_close(index_ni) && !err)
if ((ni != index_ni) && !dir_ni
&& ntfs_inode_close(index_ni) && !err)
err = errno;
}
/* Check for real error occurred. */
@ -720,11 +726,10 @@ err_out:
* EBUSY - Inode and/or one of its extents is busy, try again later.
* EIO - I/O error while writing the inode (or one of its extents).
*/
int ntfs_inode_sync(ntfs_inode *ni)
static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
{
int ret = 0;
int err = 0;
if (!ni) {
errno = EINVAL;
ntfs_log_error("Failed to sync NULL inode\n");
@ -746,7 +751,7 @@ int ntfs_inode_sync(ntfs_inode *ni)
/* Update FILE_NAME's in the index. */
if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
NInoFileNameTestAndClearDirty(ni) &&
ntfs_inode_sync_file_name(ni)) {
ntfs_inode_sync_file_name(ni, dir_ni)) {
if (!err || errno == EIO) {
err = errno;
if (err != EIO)
@ -849,6 +854,28 @@ sync_inode:
return ret;
}
int ntfs_inode_sync(ntfs_inode *ni)
{
return (ntfs_inode_sync_in_dir(ni, (ntfs_inode*)NULL));
}
/*
* Close an inode with an open parent inode
*/
int ntfs_inode_close_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
{
int res;
res = ntfs_inode_sync_in_dir(ni, dir_ni);
if (res) {
if (errno != EIO)
errno = EBUSY;
} else
res = ntfs_inode_close(ni);
return (res);
}
/**
* ntfs_inode_add_attrlist - add attribute list to inode and fill it
* @ni: opened ntfs inode to which add attribute list

View File

@ -1504,16 +1504,12 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev,
fi->fh |= CLOSE_ENCRYPTED;
NInoSetDirty(ni);
/*
* closing ni will necessitate to open dir_ni to
* synchronize the index.
* Better avoid a dangerous double opening.
* closing ni requires access to dir_ni to
* synchronize the index, avoid double opening.
*/
if (ntfs_inode_close_in_dir(ni, dir_ni))
set_fuse_error(&res);
ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
if (ntfs_inode_close(dir_ni))
set_fuse_error(&res);
dir_ni = (ntfs_inode*)NULL;
if (ntfs_inode_close(ni))
set_fuse_error(&res);
} else
res = -errno;
#if POSIXACLS