Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2: (31 commits) ocfs2: implement i_op->permission configfs: make configfs_dirent_exists() static ocfs2: update file system paths to set atime ocfs2: core atime update functions ocfs2: Add splice support ocfs2: Remove ocfs2_write_should_remove_suid() [PATCH] Export should_remove_suid() configfs: mutex_lock_nested() fix ocfs2: Remove struct ocfs2_journal_handle in favor of handle_t ocfs2: remove handle argument to ocfs2_start_trans() ocfs2: remove ocfs2_journal_handle journal field ocfs2: pass ocfs2_super * into ocfs2_commit_trans() ocfs2: remove unused handle argument from ocfs2_meta_lock_full() ocfs2: make ocfs2_alloc_handle() static ocfs2: remove unused ocfs2_handle_add_lock() ocfs2: remove unused ocfs2_handle_add_inode() ocfs2: Don't allocate handle early in ocfs2_rename() ocfs2: don't use handle for locking in allocation functions ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_rename() ocfs2: don't pass handle to ocfs2_meta_lock in ocfs2_symlink() ...
This commit is contained in:
commit
651857a1ec
@ -93,8 +93,8 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare
|
||||
*
|
||||
* called with parent inode's i_mutex held
|
||||
*/
|
||||
int configfs_dirent_exists(struct configfs_dirent *parent_sd,
|
||||
const unsigned char *new)
|
||||
static int configfs_dirent_exists(struct configfs_dirent *parent_sd,
|
||||
const unsigned char *new)
|
||||
{
|
||||
struct configfs_dirent * sd;
|
||||
|
||||
@ -1176,8 +1176,9 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex,
|
||||
I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
|
||||
if (configfs_detach_prep(dentry)) {
|
||||
printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n");
|
||||
}
|
||||
|
@ -52,14 +52,14 @@ static int ocfs2_extent_contig(struct inode *inode,
|
||||
u64 blkno);
|
||||
|
||||
static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
int wanted,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct buffer_head *bhs[]);
|
||||
|
||||
static int ocfs2_add_branch(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct buffer_head *eb_bh,
|
||||
@ -67,14 +67,14 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
|
||||
struct ocfs2_alloc_context *meta_ac);
|
||||
|
||||
static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct buffer_head **ret_new_eb_bh);
|
||||
|
||||
static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 blkno,
|
||||
@ -152,7 +152,7 @@ bail:
|
||||
* l_count for you
|
||||
*/
|
||||
static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
int wanted,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
@ -253,7 +253,7 @@ bail:
|
||||
* contain a single record with e_clusters == 0.
|
||||
*/
|
||||
static int ocfs2_add_branch(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct buffer_head *eb_bh,
|
||||
@ -418,7 +418,7 @@ bail:
|
||||
* after this call.
|
||||
*/
|
||||
static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
@ -520,7 +520,7 @@ bail:
|
||||
* down.
|
||||
*/
|
||||
static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 start_blk,
|
||||
@ -809,7 +809,7 @@ bail:
|
||||
|
||||
/* the caller needs to update fe->i_clusters */
|
||||
int ocfs2_insert_extent(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 start_blk,
|
||||
@ -951,7 +951,7 @@ static int ocfs2_truncate_log_can_coalesce(struct ocfs2_truncate_log *tl,
|
||||
}
|
||||
|
||||
static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
u64 start_blk,
|
||||
unsigned int num_clusters)
|
||||
{
|
||||
@ -1034,7 +1034,7 @@ bail:
|
||||
}
|
||||
|
||||
static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *data_alloc_inode,
|
||||
struct buffer_head *data_alloc_bh)
|
||||
{
|
||||
@ -1113,7 +1113,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
||||
{
|
||||
int status;
|
||||
unsigned int num_to_flush;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle;
|
||||
struct inode *tl_inode = osb->osb_tl_inode;
|
||||
struct inode *data_alloc_inode = NULL;
|
||||
struct buffer_head *tl_bh = osb->osb_tl_bh;
|
||||
@ -1130,7 +1130,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
||||
if (!OCFS2_IS_VALID_DINODE(di)) {
|
||||
OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
|
||||
status = -EIO;
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_to_flush = le16_to_cpu(tl->tl_used);
|
||||
@ -1138,14 +1138,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
||||
num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno);
|
||||
if (!num_to_flush) {
|
||||
status = 0;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data_alloc_inode = ocfs2_get_system_file_inode(osb,
|
||||
@ -1154,41 +1147,40 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
||||
if (!data_alloc_inode) {
|
||||
status = -EINVAL;
|
||||
mlog(ML_ERROR, "Could not get bitmap inode!\n");
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ocfs2_handle_add_inode(handle, data_alloc_inode);
|
||||
status = ocfs2_meta_lock(data_alloc_inode, handle, &data_alloc_bh, 1);
|
||||
mutex_lock(&data_alloc_inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(data_alloc_inode, &data_alloc_bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_mutex;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_TRUNCATE_LOG_UPDATE);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
status = ocfs2_replay_truncate_records(osb, handle, data_alloc_inode,
|
||||
data_alloc_bh);
|
||||
if (status < 0) {
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (data_alloc_inode)
|
||||
iput(data_alloc_inode);
|
||||
out_unlock:
|
||||
brelse(data_alloc_bh);
|
||||
ocfs2_meta_unlock(data_alloc_inode, 1);
|
||||
|
||||
if (data_alloc_bh)
|
||||
brelse(data_alloc_bh);
|
||||
out_mutex:
|
||||
mutex_unlock(&data_alloc_inode->i_mutex);
|
||||
iput(data_alloc_inode);
|
||||
|
||||
out:
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
@ -1347,7 +1339,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
|
||||
int i;
|
||||
unsigned int clusters, num_recs, start_cluster;
|
||||
u64 start_blk;
|
||||
struct ocfs2_journal_handle *handle;
|
||||
handle_t *handle;
|
||||
struct inode *tl_inode = osb->osb_tl_inode;
|
||||
struct ocfs2_truncate_log *tl;
|
||||
|
||||
@ -1373,8 +1365,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL,
|
||||
OCFS2_TRUNCATE_LOG_UPDATE);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
@ -1387,7 +1378,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
|
||||
|
||||
status = ocfs2_truncate_log_append(osb, handle,
|
||||
start_blk, clusters);
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail_up;
|
||||
@ -1543,7 +1534,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct buffer_head *old_last_eb_bh,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_truncate_context *tc)
|
||||
{
|
||||
int status, i, depth;
|
||||
@ -1782,7 +1773,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
|
||||
struct ocfs2_extent_block *eb;
|
||||
struct ocfs2_extent_list *el;
|
||||
struct buffer_head *last_eb_bh;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct inode *tl_inode = osb->osb_tl_inode;
|
||||
|
||||
mlog_entry_void();
|
||||
@ -1868,7 +1859,7 @@ start:
|
||||
|
||||
credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
|
||||
fe, el);
|
||||
handle = ocfs2_start_trans(osb, NULL, credits);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -1891,7 +1882,7 @@ start:
|
||||
mutex_unlock(&tl_inode->i_mutex);
|
||||
tl_sem = 0;
|
||||
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
handle = NULL;
|
||||
|
||||
BUG_ON(le32_to_cpu(fe->i_clusters) < target_i_clusters);
|
||||
@ -1906,7 +1897,7 @@ bail:
|
||||
mutex_unlock(&tl_inode->i_mutex);
|
||||
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (last_eb_bh)
|
||||
brelse(last_eb_bh);
|
||||
@ -2011,10 +2002,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
|
||||
mutex_lock(&ext_alloc_inode->i_mutex);
|
||||
(*tc)->tc_ext_alloc_inode = ext_alloc_inode;
|
||||
|
||||
status = ocfs2_meta_lock(ext_alloc_inode,
|
||||
NULL,
|
||||
&ext_alloc_bh,
|
||||
1);
|
||||
status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
struct ocfs2_alloc_context;
|
||||
int ocfs2_insert_extent(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 blkno,
|
||||
|
@ -200,7 +200,7 @@ static int ocfs2_readpage(struct file *file, struct page *page)
|
||||
|
||||
mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0));
|
||||
|
||||
ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page);
|
||||
ret = ocfs2_meta_lock_with_page(inode, NULL, 0, page);
|
||||
if (ret != 0) {
|
||||
if (ret == AOP_TRUNCATED_PAGE)
|
||||
unlock = 0;
|
||||
@ -305,7 +305,7 @@ static int ocfs2_prepare_write(struct file *file, struct page *page,
|
||||
|
||||
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
|
||||
|
||||
ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page);
|
||||
ret = ocfs2_meta_lock_with_page(inode, NULL, 0, page);
|
||||
if (ret != 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@ -355,16 +355,16 @@ static int walk_page_buffers( handle_t *handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned from,
|
||||
unsigned to)
|
||||
{
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
int ret = 0;
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (!handle) {
|
||||
ret = -ENOMEM;
|
||||
mlog_errno(ret);
|
||||
@ -372,7 +372,7 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
}
|
||||
|
||||
if (ocfs2_should_order_data(inode)) {
|
||||
ret = walk_page_buffers(handle->k_handle,
|
||||
ret = walk_page_buffers(handle,
|
||||
page_buffers(page),
|
||||
from, to, NULL,
|
||||
ocfs2_journal_dirty_data);
|
||||
@ -382,7 +382,7 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
out:
|
||||
if (ret) {
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
handle = ERR_PTR(ret);
|
||||
}
|
||||
return handle;
|
||||
@ -394,7 +394,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
|
||||
int ret;
|
||||
struct buffer_head *di_bh = NULL;
|
||||
struct inode *inode = page->mapping->host;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_dinode *di;
|
||||
|
||||
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
|
||||
@ -412,7 +412,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
|
||||
* stale inode allocation image (i_size, i_clusters, etc).
|
||||
*/
|
||||
|
||||
ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page);
|
||||
ret = ocfs2_meta_lock_with_page(inode, &di_bh, 1, page);
|
||||
if (ret != 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@ -464,7 +464,7 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
|
||||
}
|
||||
|
||||
out_commit:
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
|
||||
out_unlock_data:
|
||||
ocfs2_data_unlock(inode, 1);
|
||||
out_unlock_meta:
|
||||
@ -490,7 +490,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
|
||||
* accessed concurrently from multiple nodes.
|
||||
*/
|
||||
if (!INODE_JOURNAL(inode)) {
|
||||
err = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
err = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (err) {
|
||||
if (err != -ENOENT)
|
||||
mlog_errno(err);
|
||||
|
@ -25,7 +25,7 @@
|
||||
int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
|
||||
unsigned from, unsigned to);
|
||||
|
||||
struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned from,
|
||||
unsigned to);
|
||||
|
@ -82,6 +82,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
struct super_block * sb = inode->i_sb;
|
||||
unsigned int ra_sectors = 16;
|
||||
int lock_level = 0;
|
||||
|
||||
mlog_entry("dirino=%llu\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
@ -89,7 +90,15 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
||||
stored = 0;
|
||||
bh = NULL;
|
||||
|
||||
error = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
|
||||
if (lock_level && error >= 0) {
|
||||
/* We release EX lock which used to update atime
|
||||
* and get PR lock again to reduce contention
|
||||
* on commonly accessed directories. */
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
lock_level = 0;
|
||||
error = ocfs2_meta_lock(inode, NULL, 0);
|
||||
}
|
||||
if (error < 0) {
|
||||
if (error != -ENOENT)
|
||||
mlog_errno(error);
|
||||
@ -198,7 +207,7 @@ revalidate:
|
||||
|
||||
stored = 0;
|
||||
bail:
|
||||
ocfs2_meta_unlock(inode, 0);
|
||||
ocfs2_meta_unlock(inode, lock_level);
|
||||
|
||||
bail_nolock:
|
||||
mlog_exit(stored);
|
||||
@ -340,7 +349,7 @@ int ocfs2_empty_dir(struct inode *inode)
|
||||
|
||||
/* returns a bh of the 1st new block in the allocation. */
|
||||
int ocfs2_do_extend_dir(struct super_block *sb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *dir,
|
||||
struct buffer_head *parent_fe_bh,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
@ -398,7 +407,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
|
||||
struct ocfs2_alloc_context *data_ac = NULL;
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct buffer_head *new_bh = NULL;
|
||||
struct ocfs2_dir_entry * de;
|
||||
struct super_block *sb = osb->sb;
|
||||
@ -409,13 +418,6 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
mlog(0, "extending dir %llu (i_size = %lld)\n",
|
||||
(unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size);
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* dir->i_size is always block aligned. */
|
||||
spin_lock(&OCFS2_I(dir)->ip_lock);
|
||||
if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
|
||||
@ -428,8 +430,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
if (!num_free_extents) {
|
||||
status = ocfs2_reserve_new_metadata(osb, handle,
|
||||
fe, &meta_ac);
|
||||
status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -437,7 +438,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
}
|
||||
}
|
||||
|
||||
status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
|
||||
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -450,7 +451,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, credits);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -496,7 +497,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
get_bh(*new_de_bh);
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (data_ac)
|
||||
ocfs2_free_alloc_context(data_ac);
|
||||
|
@ -45,7 +45,7 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
|
||||
struct buffer_head **ret_de_bh);
|
||||
struct ocfs2_alloc_context;
|
||||
int ocfs2_do_extend_dir(struct super_block *sb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *dir,
|
||||
struct buffer_head *parent_fe_bh,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
|
@ -68,7 +68,8 @@ static void **dlm_alloc_pagevec(int pages)
|
||||
goto out_free;
|
||||
|
||||
mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n",
|
||||
pages, DLM_HASH_PAGES, (unsigned long)DLM_BUCKETS_PER_PAGE);
|
||||
pages, (unsigned long)DLM_HASH_PAGES,
|
||||
(unsigned long)DLM_BUCKETS_PER_PAGE);
|
||||
return vec;
|
||||
out_free:
|
||||
dlm_free_pagevec(vec, i);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "dcache.h"
|
||||
#include "dlmglue.h"
|
||||
#include "extent_map.h"
|
||||
#include "file.h"
|
||||
#include "heartbeat.h"
|
||||
#include "inode.h"
|
||||
#include "journal.h"
|
||||
@ -1063,10 +1064,10 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
||||
mlog_exit_void();
|
||||
}
|
||||
|
||||
int ocfs2_create_new_lock(struct ocfs2_super *osb,
|
||||
struct ocfs2_lock_res *lockres,
|
||||
int ex,
|
||||
int local)
|
||||
static int ocfs2_create_new_lock(struct ocfs2_super *osb,
|
||||
struct ocfs2_lock_res *lockres,
|
||||
int ex,
|
||||
int local)
|
||||
{
|
||||
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
||||
unsigned long flags;
|
||||
@ -1579,7 +1580,6 @@ static int ocfs2_assign_bh(struct inode *inode,
|
||||
* the result of the lock will be communicated via the callback.
|
||||
*/
|
||||
int ocfs2_meta_lock_full(struct inode *inode,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **ret_bh,
|
||||
int ex,
|
||||
int arg_flags)
|
||||
@ -1668,12 +1668,6 @@ int ocfs2_meta_lock_full(struct inode *inode,
|
||||
}
|
||||
}
|
||||
|
||||
if (handle) {
|
||||
status = ocfs2_handle_add_lock(handle, inode);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
}
|
||||
|
||||
bail:
|
||||
if (status < 0) {
|
||||
if (ret_bh && (*ret_bh)) {
|
||||
@ -1713,18 +1707,16 @@ bail:
|
||||
* the lock inversion simply.
|
||||
*/
|
||||
int ocfs2_meta_lock_with_page(struct inode *inode,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **ret_bh,
|
||||
int ex,
|
||||
struct page *page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ocfs2_meta_lock_full(inode, handle, ret_bh, ex,
|
||||
OCFS2_LOCK_NONBLOCK);
|
||||
ret = ocfs2_meta_lock_full(inode, ret_bh, ex, OCFS2_LOCK_NONBLOCK);
|
||||
if (ret == -EAGAIN) {
|
||||
unlock_page(page);
|
||||
if (ocfs2_meta_lock(inode, handle, ret_bh, ex) == 0)
|
||||
if (ocfs2_meta_lock(inode, ret_bh, ex) == 0)
|
||||
ocfs2_meta_unlock(inode, ex);
|
||||
ret = AOP_TRUNCATED_PAGE;
|
||||
}
|
||||
@ -1732,6 +1724,44 @@ int ocfs2_meta_lock_with_page(struct inode *inode,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ocfs2_meta_lock_atime(struct inode *inode,
|
||||
struct vfsmount *vfsmnt,
|
||||
int *level)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mlog_entry_void();
|
||||
ret = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we should update atime, we will get EX lock,
|
||||
* otherwise we just get PR lock.
|
||||
*/
|
||||
if (ocfs2_should_update_atime(inode, vfsmnt)) {
|
||||
struct buffer_head *bh = NULL;
|
||||
|
||||
ocfs2_meta_unlock(inode, 0);
|
||||
ret = ocfs2_meta_lock(inode, &bh, 1);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
return ret;
|
||||
}
|
||||
*level = 1;
|
||||
if (ocfs2_should_update_atime(inode, vfsmnt))
|
||||
ocfs2_update_inode_atime(inode, bh);
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
} else
|
||||
*level = 0;
|
||||
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ocfs2_meta_unlock(struct inode *inode,
|
||||
int ex)
|
||||
{
|
||||
|
@ -68,8 +68,6 @@ void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
|
||||
u64 parent, struct inode *inode);
|
||||
void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
|
||||
int ocfs2_create_new_inode_locks(struct inode *inode);
|
||||
int ocfs2_create_new_lock(struct ocfs2_super *osb,
|
||||
struct ocfs2_lock_res *lockres, int ex, int local);
|
||||
int ocfs2_drop_inode_locks(struct inode *inode);
|
||||
int ocfs2_data_lock_full(struct inode *inode,
|
||||
int write,
|
||||
@ -82,19 +80,20 @@ void ocfs2_data_unlock(struct inode *inode,
|
||||
int write);
|
||||
int ocfs2_rw_lock(struct inode *inode, int write);
|
||||
void ocfs2_rw_unlock(struct inode *inode, int write);
|
||||
int ocfs2_meta_lock_atime(struct inode *inode,
|
||||
struct vfsmount *vfsmnt,
|
||||
int *level);
|
||||
int ocfs2_meta_lock_full(struct inode *inode,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **ret_bh,
|
||||
int ex,
|
||||
int arg_flags);
|
||||
int ocfs2_meta_lock_with_page(struct inode *inode,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **ret_bh,
|
||||
int ex,
|
||||
struct page *page);
|
||||
/* 99% of the time we don't want to supply any additional flags --
|
||||
* those are for very specific cases only. */
|
||||
#define ocfs2_meta_lock(i, h, b, e) ocfs2_meta_lock_full(i, h, b, e, 0)
|
||||
#define ocfs2_meta_lock(i, b, e) ocfs2_meta_lock_full(i, b, e, 0)
|
||||
void ocfs2_meta_unlock(struct inode *inode,
|
||||
int ex);
|
||||
int ocfs2_super_lock(struct ocfs2_super *osb,
|
||||
|
@ -100,7 +100,7 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
|
||||
mlog(0, "find parent of directory %llu\n",
|
||||
(unsigned long long)OCFS2_I(dir)->ip_blkno);
|
||||
|
||||
status = ocfs2_meta_lock(dir, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(dir, NULL, 0);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
|
343
fs/ocfs2/file.c
343
fs/ocfs2/file.c
@ -31,6 +31,8 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pipe_fs_i.h>
|
||||
#include <linux/mount.h>
|
||||
|
||||
#define MLOG_MASK_PREFIX ML_INODE
|
||||
#include <cluster/masklog.h>
|
||||
@ -134,7 +136,58 @@ bail:
|
||||
return (err < 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_should_update_atime(struct inode *inode,
|
||||
struct vfsmount *vfsmnt)
|
||||
{
|
||||
struct timespec now;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
|
||||
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
|
||||
return 0;
|
||||
|
||||
if ((inode->i_flags & S_NOATIME) ||
|
||||
((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
|
||||
return 0;
|
||||
|
||||
if ((vfsmnt->mnt_flags & MNT_NOATIME) ||
|
||||
((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
|
||||
return 0;
|
||||
|
||||
now = CURRENT_TIME;
|
||||
if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ocfs2_update_inode_atime(struct inode *inode,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
int ret;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
handle_t *handle;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
ret = ocfs2_mark_inode_dirty(handle, inode, bh);
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
|
||||
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
|
||||
out:
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ocfs2_set_inode_size(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 new_i_size)
|
||||
@ -163,10 +216,9 @@ static int ocfs2_simple_size_update(struct inode *inode,
|
||||
{
|
||||
int ret;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL,
|
||||
OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
mlog_errno(ret);
|
||||
@ -178,7 +230,7 @@ static int ocfs2_simple_size_update(struct inode *inode,
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -189,14 +241,14 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
|
||||
u64 new_i_size)
|
||||
{
|
||||
int status;
|
||||
struct ocfs2_journal_handle *handle;
|
||||
handle_t *handle;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
/* TODO: This needs to actually orphan the inode in this
|
||||
* transaction. */
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
@ -207,7 +259,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out:
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@ -328,7 +380,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 clusters_to_add,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret)
|
||||
@ -433,7 +485,7 @@ static int ocfs2_extend_allocation(struct inode *inode,
|
||||
u32 prev_clusters;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct ocfs2_dinode *fe = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_alloc_context *data_ac = NULL;
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
enum ocfs2_alloc_restarted why;
|
||||
@ -463,13 +515,6 @@ restart_all:
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
|
||||
fe->i_clusters, clusters_to_add);
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
num_free_extents = ocfs2_num_free_extents(osb,
|
||||
inode,
|
||||
fe);
|
||||
@ -480,10 +525,7 @@ restart_all:
|
||||
}
|
||||
|
||||
if (!num_free_extents) {
|
||||
status = ocfs2_reserve_new_metadata(osb,
|
||||
handle,
|
||||
fe,
|
||||
&meta_ac);
|
||||
status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -491,10 +533,7 @@ restart_all:
|
||||
}
|
||||
}
|
||||
|
||||
status = ocfs2_reserve_clusters(osb,
|
||||
handle,
|
||||
clusters_to_add,
|
||||
&data_ac);
|
||||
status = ocfs2_reserve_clusters(osb, clusters_to_add, &data_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -509,7 +548,7 @@ restart_all:
|
||||
drop_alloc_sem = 1;
|
||||
|
||||
credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add);
|
||||
handle = ocfs2_start_trans(osb, handle, credits);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -589,7 +628,7 @@ leave:
|
||||
drop_alloc_sem = 0;
|
||||
}
|
||||
if (handle) {
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
handle = NULL;
|
||||
}
|
||||
if (data_ac) {
|
||||
@ -624,7 +663,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
|
||||
struct page *page;
|
||||
unsigned long index;
|
||||
unsigned int offset;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
int ret;
|
||||
|
||||
offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
|
||||
@ -668,7 +707,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
|
||||
ret = 0;
|
||||
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
|
||||
out_unlock:
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
@ -789,7 +828,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct ocfs2_super *osb = OCFS2_SB(sb);
|
||||
struct buffer_head *bh = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
|
||||
mlog_entry("(0x%p, '%.*s')\n", dentry,
|
||||
dentry->d_name.len, dentry->d_name.name);
|
||||
@ -825,7 +864,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
}
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(inode, NULL, &bh, 1);
|
||||
status = ocfs2_meta_lock(inode, &bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
@ -845,7 +884,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
@ -863,7 +902,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
mlog_errno(status);
|
||||
|
||||
bail_commit:
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
bail_unlock:
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
bail_unlock_rw:
|
||||
@ -906,19 +945,41 @@ bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
ret = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = generic_permission(inode, mask, NULL);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
|
||||
ocfs2_meta_unlock(inode, 0);
|
||||
out:
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ocfs2_write_remove_suid(struct inode *inode)
|
||||
{
|
||||
int ret;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct ocfs2_inode_info *oi = OCFS2_I(inode);
|
||||
struct ocfs2_journal_handle *handle;
|
||||
handle_t *handle;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_dinode *di;
|
||||
|
||||
mlog_entry("(Inode %llu, mode 0%o)\n",
|
||||
(unsigned long long)oi->ip_blkno, inode->i_mode);
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
mlog_errno(ret);
|
||||
@ -951,75 +1012,29 @@ static int ocfs2_write_remove_suid(struct inode *inode)
|
||||
out_bh:
|
||||
brelse(bh);
|
||||
out_trans:
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out:
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int ocfs2_write_should_remove_suid(struct inode *inode)
|
||||
static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
|
||||
loff_t *ppos,
|
||||
size_t count,
|
||||
int appending)
|
||||
{
|
||||
mode_t mode = inode->i_mode;
|
||||
|
||||
if (!capable(CAP_FSETID)) {
|
||||
if (unlikely(mode & S_ISUID))
|
||||
return 1;
|
||||
|
||||
if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
const struct iovec *iov,
|
||||
unsigned long nr_segs,
|
||||
loff_t pos)
|
||||
{
|
||||
int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0;
|
||||
int ret = 0, meta_level = appending;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
u32 clusters;
|
||||
struct file *filp = iocb->ki_filp;
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
loff_t newsize, saved_pos;
|
||||
|
||||
mlog_entry("(0x%p, %u, '%.*s')\n", filp,
|
||||
(unsigned int)nr_segs,
|
||||
filp->f_dentry->d_name.len,
|
||||
filp->f_dentry->d_name.name);
|
||||
|
||||
/* happy write of zero bytes */
|
||||
if (iocb->ki_left == 0)
|
||||
return 0;
|
||||
|
||||
if (!inode) {
|
||||
mlog(0, "bad inode\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
/* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
|
||||
if (filp->f_flags & O_DIRECT) {
|
||||
have_alloc_sem = 1;
|
||||
down_read(&inode->i_alloc_sem);
|
||||
}
|
||||
|
||||
/* concurrent O_DIRECT writes are allowed */
|
||||
rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1;
|
||||
ret = ocfs2_rw_lock(inode, rw_level);
|
||||
if (ret < 0) {
|
||||
rw_level = -1;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We sample i_size under a read level meta lock to see if our write
|
||||
* is extending the file, if it is we back off and get a write level
|
||||
* meta lock.
|
||||
*/
|
||||
meta_level = (filp->f_flags & O_APPEND) ? 1 : 0;
|
||||
for(;;) {
|
||||
ret = ocfs2_meta_lock(inode, NULL, NULL, meta_level);
|
||||
ret = ocfs2_meta_lock(inode, NULL, meta_level);
|
||||
if (ret < 0) {
|
||||
meta_level = -1;
|
||||
mlog_errno(ret);
|
||||
@ -1035,7 +1050,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
* inode. There's also the dinode i_size state which
|
||||
* can be lost via setattr during extending writes (we
|
||||
* set inode->i_size at the end of a write. */
|
||||
if (ocfs2_write_should_remove_suid(inode)) {
|
||||
if (should_remove_suid(dentry)) {
|
||||
if (meta_level == 0) {
|
||||
ocfs2_meta_unlock(inode, meta_level);
|
||||
meta_level = 1;
|
||||
@ -1045,19 +1060,19 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
ret = ocfs2_write_remove_suid(inode);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* work on a copy of ppos until we're sure that we won't have
|
||||
* to recalculate it due to relocking. */
|
||||
if (filp->f_flags & O_APPEND) {
|
||||
if (appending) {
|
||||
saved_pos = i_size_read(inode);
|
||||
mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos);
|
||||
} else {
|
||||
saved_pos = iocb->ki_pos;
|
||||
saved_pos = *ppos;
|
||||
}
|
||||
newsize = iocb->ki_left + saved_pos;
|
||||
newsize = count + saved_pos;
|
||||
|
||||
mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
|
||||
(long long) saved_pos, (long long) newsize,
|
||||
@ -1090,19 +1105,66 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
if (!clusters)
|
||||
break;
|
||||
|
||||
ret = ocfs2_extend_file(inode, NULL, newsize, iocb->ki_left);
|
||||
ret = ocfs2_extend_file(inode, NULL, newsize, count);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENOSPC)
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
goto out_unlock;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* ok, we're done with i_size and alloc work */
|
||||
iocb->ki_pos = saved_pos;
|
||||
if (appending)
|
||||
*ppos = saved_pos;
|
||||
|
||||
out_unlock:
|
||||
ocfs2_meta_unlock(inode, meta_level);
|
||||
meta_level = -1;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
const struct iovec *iov,
|
||||
unsigned long nr_segs,
|
||||
loff_t pos)
|
||||
{
|
||||
int ret, rw_level, have_alloc_sem = 0;
|
||||
struct file *filp = iocb->ki_filp;
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
int appending = filp->f_flags & O_APPEND ? 1 : 0;
|
||||
|
||||
mlog_entry("(0x%p, %u, '%.*s')\n", filp,
|
||||
(unsigned int)nr_segs,
|
||||
filp->f_dentry->d_name.len,
|
||||
filp->f_dentry->d_name.name);
|
||||
|
||||
/* happy write of zero bytes */
|
||||
if (iocb->ki_left == 0)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
/* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
|
||||
if (filp->f_flags & O_DIRECT) {
|
||||
have_alloc_sem = 1;
|
||||
down_read(&inode->i_alloc_sem);
|
||||
}
|
||||
|
||||
/* concurrent O_DIRECT writes are allowed */
|
||||
rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1;
|
||||
ret = ocfs2_rw_lock(inode, rw_level);
|
||||
if (ret < 0) {
|
||||
rw_level = -1;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos,
|
||||
iocb->ki_left, appending);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* communicate with ocfs2_dio_end_io */
|
||||
ocfs2_iocb_set_rw_locked(iocb);
|
||||
@ -1128,8 +1190,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
||||
}
|
||||
|
||||
out:
|
||||
if (meta_level != -1)
|
||||
ocfs2_meta_unlock(inode, meta_level);
|
||||
if (have_alloc_sem)
|
||||
up_read(&inode->i_alloc_sem);
|
||||
if (rw_level != -1)
|
||||
@ -1140,12 +1200,83 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
|
||||
struct file *out,
|
||||
loff_t *ppos,
|
||||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
struct inode *inode = out->f_dentry->d_inode;
|
||||
|
||||
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
|
||||
(unsigned int)len,
|
||||
out->f_dentry->d_name.len,
|
||||
out->f_dentry->d_name.name);
|
||||
|
||||
inode_double_lock(inode, pipe->inode);
|
||||
|
||||
ret = ocfs2_rw_lock(inode, 1);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* ok, we're done with i_size and alloc work */
|
||||
ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
|
||||
|
||||
out_unlock:
|
||||
ocfs2_rw_unlock(inode, 1);
|
||||
out:
|
||||
inode_double_unlock(inode, pipe->inode);
|
||||
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_splice_read(struct file *in,
|
||||
loff_t *ppos,
|
||||
struct pipe_inode_info *pipe,
|
||||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
struct inode *inode = in->f_dentry->d_inode;
|
||||
|
||||
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe,
|
||||
(unsigned int)len,
|
||||
in->f_dentry->d_name.len,
|
||||
in->f_dentry->d_name.name);
|
||||
|
||||
/*
|
||||
* See the comment in ocfs2_file_aio_read()
|
||||
*/
|
||||
ret = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto bail;
|
||||
}
|
||||
ocfs2_meta_unlock(inode, 0);
|
||||
|
||||
ret = generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
|
||||
bail:
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
|
||||
const struct iovec *iov,
|
||||
unsigned long nr_segs,
|
||||
loff_t pos)
|
||||
{
|
||||
int ret = 0, rw_level = -1, have_alloc_sem = 0;
|
||||
int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
|
||||
struct file *filp = iocb->ki_filp;
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
|
||||
@ -1187,12 +1318,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
|
||||
* like i_size. This allows the checks down below
|
||||
* generic_file_aio_read() a chance of actually working.
|
||||
*/
|
||||
ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
ret = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto bail;
|
||||
}
|
||||
ocfs2_meta_unlock(inode, 0);
|
||||
ocfs2_meta_unlock(inode, lock_level);
|
||||
|
||||
ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
|
||||
if (ret == -EINVAL)
|
||||
@ -1220,11 +1351,13 @@ bail:
|
||||
struct inode_operations ocfs2_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
};
|
||||
|
||||
struct inode_operations ocfs2_special_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
};
|
||||
|
||||
const struct file_operations ocfs2_fops = {
|
||||
@ -1238,6 +1371,8 @@ const struct file_operations ocfs2_fops = {
|
||||
.aio_read = ocfs2_file_aio_read,
|
||||
.aio_write = ocfs2_file_aio_write,
|
||||
.ioctl = ocfs2_ioctl,
|
||||
.splice_read = ocfs2_file_splice_read,
|
||||
.splice_write = ocfs2_file_splice_write,
|
||||
};
|
||||
|
||||
const struct file_operations ocfs2_dops = {
|
||||
|
@ -41,17 +41,24 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 clusters_to_add,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason);
|
||||
int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
int ocfs2_permission(struct inode *inode, int mask,
|
||||
struct nameidata *nd);
|
||||
|
||||
int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_set_inode_size(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
u64 new_i_size);
|
||||
|
||||
int ocfs2_should_update_atime(struct inode *inode,
|
||||
struct vfsmount *vfsmnt);
|
||||
int ocfs2_update_inode_atime(struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
|
||||
#endif /* OCFS2_FILE_H */
|
||||
|
@ -360,7 +360,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
|
||||
inode);
|
||||
|
||||
ocfs2_set_inode_flags(inode);
|
||||
inode->i_flags |= S_NOATIME;
|
||||
|
||||
status = 0;
|
||||
bail:
|
||||
@ -441,7 +440,7 @@ static int ocfs2_read_locked_inode(struct inode *inode,
|
||||
generation, inode);
|
||||
|
||||
if (can_lock) {
|
||||
status = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (status) {
|
||||
make_bad_inode(inode);
|
||||
mlog_errno(status);
|
||||
@ -512,7 +511,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
struct buffer_head *fe_bh)
|
||||
{
|
||||
int status = 0;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_truncate_context *tc = NULL;
|
||||
struct ocfs2_dinode *fe;
|
||||
|
||||
@ -524,7 +523,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
if (!fe->i_clusters)
|
||||
goto bail;
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -538,7 +537,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
handle = NULL;
|
||||
|
||||
status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);
|
||||
@ -554,7 +553,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
}
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@ -568,7 +567,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
int status;
|
||||
struct inode *inode_alloc_inode = NULL;
|
||||
struct buffer_head *inode_alloc_bh = NULL;
|
||||
struct ocfs2_journal_handle *handle;
|
||||
handle_t *handle;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
|
||||
|
||||
@ -582,7 +581,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
}
|
||||
|
||||
mutex_lock(&inode_alloc_inode->i_mutex);
|
||||
status = ocfs2_meta_lock(inode_alloc_inode, NULL, &inode_alloc_bh, 1);
|
||||
status = ocfs2_meta_lock(inode_alloc_inode, &inode_alloc_bh, 1);
|
||||
if (status < 0) {
|
||||
mutex_unlock(&inode_alloc_inode->i_mutex);
|
||||
|
||||
@ -590,7 +589,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_DELETE_INODE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
@ -629,7 +628,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
mlog_errno(status);
|
||||
|
||||
bail_commit:
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
bail_unlock:
|
||||
ocfs2_meta_unlock(inode_alloc_inode, 1);
|
||||
mutex_unlock(&inode_alloc_inode->i_mutex);
|
||||
@ -705,7 +704,7 @@ static int ocfs2_wipe_inode(struct inode *inode,
|
||||
* delete_inode operation. We do this now to avoid races with
|
||||
* recovery completion on other nodes. */
|
||||
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1);
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1);
|
||||
if (status < 0) {
|
||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||
|
||||
@ -933,7 +932,7 @@ void ocfs2_delete_inode(struct inode *inode)
|
||||
* allocation lock here as it won't be needed - nobody will
|
||||
* have the file open.
|
||||
*/
|
||||
status = ocfs2_meta_lock(inode, NULL, &di_bh, 1);
|
||||
status = ocfs2_meta_lock(inode, &di_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
@ -1067,12 +1066,6 @@ void ocfs2_clear_inode(struct inode *inode)
|
||||
mlog_bug_on_msg(oi->ip_open_count,
|
||||
"Clear inode of %llu has open count %d\n",
|
||||
(unsigned long long)oi->ip_blkno, oi->ip_open_count);
|
||||
mlog_bug_on_msg(!list_empty(&oi->ip_handle_list),
|
||||
"Clear inode of %llu has non empty handle list\n",
|
||||
(unsigned long long)oi->ip_blkno);
|
||||
mlog_bug_on_msg(oi->ip_handle,
|
||||
"Clear inode of %llu has non empty handle pointer\n",
|
||||
(unsigned long long)oi->ip_blkno);
|
||||
|
||||
/* Clear all other flags. */
|
||||
oi->ip_flags = OCFS2_INODE_CACHE_INLINE;
|
||||
@ -1186,7 +1179,7 @@ int ocfs2_inode_revalidate(struct dentry *dentry)
|
||||
|
||||
/* Let ocfs2_meta_lock do the work of updating our struct
|
||||
* inode for us. */
|
||||
status = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
@ -1204,7 +1197,7 @@ bail:
|
||||
* struct inode.
|
||||
* Only takes ip_lock.
|
||||
*/
|
||||
int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_mark_inode_dirty(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
|
@ -48,13 +48,6 @@ struct ocfs2_inode_info
|
||||
|
||||
struct mutex ip_io_mutex;
|
||||
|
||||
/* Used by the journalling code to attach an inode to a
|
||||
* handle. These are protected by ip_io_mutex in order to lock
|
||||
* out other I/O to the inode until we either commit or
|
||||
* abort. */
|
||||
struct list_head ip_handle_list;
|
||||
struct ocfs2_journal_handle *ip_handle;
|
||||
|
||||
u32 ip_flags; /* see below */
|
||||
u32 ip_attr; /* inode attributes */
|
||||
|
||||
@ -143,7 +136,7 @@ ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf,
|
||||
void ocfs2_sync_blockdev(struct super_block *sb);
|
||||
void ocfs2_refresh_inode(struct inode *inode,
|
||||
struct ocfs2_dinode *fe);
|
||||
int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_mark_inode_dirty(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
|
||||
|
@ -26,7 +26,7 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = ocfs2_meta_lock(inode, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(inode, NULL, 0);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
return status;
|
||||
@ -43,14 +43,14 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
|
||||
{
|
||||
struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
unsigned oldflags;
|
||||
int status;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(inode, NULL, &bh, 1);
|
||||
status = ocfs2_meta_lock(inode, &bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@ -67,7 +67,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
flags &= ~OCFS2_DIRSYNC_FL;
|
||||
|
||||
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
@ -96,7 +96,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
bail_unlock:
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
bail:
|
||||
|
@ -57,9 +57,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
|
||||
static int __ocfs2_recovery_thread(void *arg);
|
||||
static int ocfs2_commit_cache(struct ocfs2_super *osb);
|
||||
static int ocfs2_wait_on_mount(struct ocfs2_super *osb);
|
||||
static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal,
|
||||
struct ocfs2_journal_handle *handle);
|
||||
static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle);
|
||||
static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
|
||||
int dirty);
|
||||
static int ocfs2_trylock_journal(struct ocfs2_super *osb,
|
||||
@ -113,46 +110,18 @@ finally:
|
||||
return status;
|
||||
}
|
||||
|
||||
struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb)
|
||||
{
|
||||
struct ocfs2_journal_handle *retval = NULL;
|
||||
|
||||
retval = kcalloc(1, sizeof(*retval), GFP_NOFS);
|
||||
if (!retval) {
|
||||
mlog(ML_ERROR, "Failed to allocate memory for journal "
|
||||
"handle!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval->max_buffs = 0;
|
||||
retval->num_locks = 0;
|
||||
retval->k_handle = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&retval->locks);
|
||||
INIT_LIST_HEAD(&retval->inode_list);
|
||||
retval->journal = osb->journal;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* pass it NULL and it will allocate a new handle object for you. If
|
||||
* you pass it a handle however, it may still return error, in which
|
||||
* case it has free'd the passed handle for you. */
|
||||
struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
int max_buffs)
|
||||
handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
|
||||
{
|
||||
int ret;
|
||||
journal_t *journal = osb->journal->j_journal;
|
||||
|
||||
mlog_entry("(max_buffs = %d)\n", max_buffs);
|
||||
handle_t *handle;
|
||||
|
||||
BUG_ON(!osb || !osb->journal->j_journal);
|
||||
|
||||
if (ocfs2_is_hard_readonly(osb)) {
|
||||
ret = -EROFS;
|
||||
goto done_free;
|
||||
}
|
||||
if (ocfs2_is_hard_readonly(osb))
|
||||
return ERR_PTR(-EROFS);
|
||||
|
||||
BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE);
|
||||
BUG_ON(max_buffs <= 0);
|
||||
@ -163,154 +132,39 @@ struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (!handle)
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
ret = -ENOMEM;
|
||||
mlog(ML_ERROR, "Failed to allocate memory for journal "
|
||||
"handle!\n");
|
||||
goto done_free;
|
||||
}
|
||||
|
||||
handle->max_buffs = max_buffs;
|
||||
|
||||
down_read(&osb->journal->j_trans_barrier);
|
||||
|
||||
/* actually start the transaction now */
|
||||
handle->k_handle = journal_start(journal, max_buffs);
|
||||
if (IS_ERR(handle->k_handle)) {
|
||||
handle = journal_start(journal, max_buffs);
|
||||
if (IS_ERR(handle)) {
|
||||
up_read(&osb->journal->j_trans_barrier);
|
||||
|
||||
ret = PTR_ERR(handle->k_handle);
|
||||
handle->k_handle = NULL;
|
||||
mlog_errno(ret);
|
||||
mlog_errno(PTR_ERR(handle));
|
||||
|
||||
if (is_journal_aborted(journal)) {
|
||||
ocfs2_abort(osb->sb, "Detected aborted journal");
|
||||
ret = -EROFS;
|
||||
handle = ERR_PTR(-EROFS);
|
||||
}
|
||||
goto done_free;
|
||||
}
|
||||
} else
|
||||
atomic_inc(&(osb->journal->j_num_trans));
|
||||
|
||||
atomic_inc(&(osb->journal->j_num_trans));
|
||||
handle->flags |= OCFS2_HANDLE_STARTED;
|
||||
|
||||
mlog_exit_ptr(handle);
|
||||
return handle;
|
||||
|
||||
done_free:
|
||||
if (handle)
|
||||
ocfs2_commit_unstarted_handle(handle); /* will kfree handle */
|
||||
|
||||
mlog_exit(ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle,
|
||||
struct inode *inode)
|
||||
int ocfs2_commit_trans(struct ocfs2_super *osb,
|
||||
handle_t *handle)
|
||||
{
|
||||
BUG_ON(!handle);
|
||||
BUG_ON(!inode);
|
||||
|
||||
atomic_inc(&inode->i_count);
|
||||
|
||||
/* we're obviously changing it... */
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
/* sanity check */
|
||||
BUG_ON(OCFS2_I(inode)->ip_handle);
|
||||
BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list));
|
||||
|
||||
OCFS2_I(inode)->ip_handle = handle;
|
||||
list_move_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list));
|
||||
}
|
||||
|
||||
static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
struct inode *inode;
|
||||
struct ocfs2_inode_info *oi;
|
||||
|
||||
list_for_each_safe(p, n, &handle->inode_list) {
|
||||
oi = list_entry(p, struct ocfs2_inode_info,
|
||||
ip_handle_list);
|
||||
inode = &oi->vfs_inode;
|
||||
|
||||
OCFS2_I(inode)->ip_handle = NULL;
|
||||
list_del_init(&OCFS2_I(inode)->ip_handle_list);
|
||||
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
iput(inode);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is trivial so we do it out of the main commit
|
||||
* paths. Beware, it can be called from start_trans too! */
|
||||
static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle)
|
||||
{
|
||||
mlog_entry_void();
|
||||
|
||||
BUG_ON(handle->flags & OCFS2_HANDLE_STARTED);
|
||||
|
||||
ocfs2_handle_unlock_inodes(handle);
|
||||
/* You are allowed to add journal locks before the transaction
|
||||
* has started. */
|
||||
ocfs2_handle_cleanup_locks(handle->journal, handle);
|
||||
|
||||
kfree(handle);
|
||||
|
||||
mlog_exit_void();
|
||||
}
|
||||
|
||||
void ocfs2_commit_trans(struct ocfs2_journal_handle *handle)
|
||||
{
|
||||
handle_t *jbd_handle;
|
||||
int retval;
|
||||
struct ocfs2_journal *journal = handle->journal;
|
||||
|
||||
mlog_entry_void();
|
||||
int ret;
|
||||
struct ocfs2_journal *journal = osb->journal;
|
||||
|
||||
BUG_ON(!handle);
|
||||
|
||||
if (!(handle->flags & OCFS2_HANDLE_STARTED)) {
|
||||
ocfs2_commit_unstarted_handle(handle);
|
||||
mlog_exit_void();
|
||||
return;
|
||||
}
|
||||
|
||||
/* release inode semaphores we took during this transaction */
|
||||
ocfs2_handle_unlock_inodes(handle);
|
||||
|
||||
/* ocfs2_extend_trans may have had to call journal_restart
|
||||
* which will always commit the transaction, but may return
|
||||
* error for any number of reasons. If this is the case, we
|
||||
* clear k_handle as it's not valid any more. */
|
||||
if (handle->k_handle) {
|
||||
jbd_handle = handle->k_handle;
|
||||
|
||||
if (handle->flags & OCFS2_HANDLE_SYNC)
|
||||
jbd_handle->h_sync = 1;
|
||||
else
|
||||
jbd_handle->h_sync = 0;
|
||||
|
||||
/* actually stop the transaction. if we've set h_sync,
|
||||
* it'll have been committed when we return */
|
||||
retval = journal_stop(jbd_handle);
|
||||
if (retval < 0) {
|
||||
mlog_errno(retval);
|
||||
mlog(ML_ERROR, "Could not commit transaction\n");
|
||||
BUG();
|
||||
}
|
||||
|
||||
handle->k_handle = NULL; /* it's been free'd in journal_stop */
|
||||
}
|
||||
|
||||
ocfs2_handle_cleanup_locks(journal, handle);
|
||||
ret = journal_stop(handle);
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
|
||||
up_read(&journal->j_trans_barrier);
|
||||
|
||||
kfree(handle);
|
||||
mlog_exit_void();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -326,20 +180,18 @@ void ocfs2_commit_trans(struct ocfs2_journal_handle *handle)
|
||||
* good because transaction ids haven't yet been recorded on the
|
||||
* cluster locks associated with this handle.
|
||||
*/
|
||||
int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
|
||||
int nblocks)
|
||||
int ocfs2_extend_trans(handle_t *handle, int nblocks)
|
||||
{
|
||||
int status;
|
||||
|
||||
BUG_ON(!handle);
|
||||
BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
|
||||
BUG_ON(!nblocks);
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
mlog(0, "Trying to extend transaction by %d blocks\n", nblocks);
|
||||
|
||||
status = journal_extend(handle->k_handle, nblocks);
|
||||
status = journal_extend(handle, nblocks);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@ -347,15 +199,12 @@ int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
|
||||
|
||||
if (status > 0) {
|
||||
mlog(0, "journal_extend failed, trying journal_restart\n");
|
||||
status = journal_restart(handle->k_handle, nblocks);
|
||||
status = journal_restart(handle, nblocks);
|
||||
if (status < 0) {
|
||||
handle->k_handle = NULL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
handle->max_buffs = nblocks;
|
||||
} else
|
||||
handle->max_buffs += nblocks;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
bail:
|
||||
@ -364,7 +213,7 @@ bail:
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_journal_access(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh,
|
||||
int type)
|
||||
@ -374,7 +223,6 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
BUG_ON(!inode);
|
||||
BUG_ON(!handle);
|
||||
BUG_ON(!bh);
|
||||
BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
|
||||
|
||||
mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n",
|
||||
(unsigned long long)bh->b_blocknr, type,
|
||||
@ -403,11 +251,11 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
switch (type) {
|
||||
case OCFS2_JOURNAL_ACCESS_CREATE:
|
||||
case OCFS2_JOURNAL_ACCESS_WRITE:
|
||||
status = journal_get_write_access(handle->k_handle, bh);
|
||||
status = journal_get_write_access(handle, bh);
|
||||
break;
|
||||
|
||||
case OCFS2_JOURNAL_ACCESS_UNDO:
|
||||
status = journal_get_undo_access(handle->k_handle, bh);
|
||||
status = journal_get_undo_access(handle, bh);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -424,17 +272,15 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_journal_dirty(handle_t *handle,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
int status;
|
||||
|
||||
BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
|
||||
|
||||
mlog_entry("(bh->b_blocknr=%llu)\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
|
||||
status = journal_dirty_metadata(handle->k_handle, bh);
|
||||
status = journal_dirty_metadata(handle, bh);
|
||||
if (status < 0)
|
||||
mlog(ML_ERROR, "Could not dirty metadata buffer. "
|
||||
"(bh->b_blocknr=%llu)\n",
|
||||
@ -456,59 +302,6 @@ int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* We always assume you're adding a metadata lock at level 'ex' */
|
||||
int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle,
|
||||
struct inode *inode)
|
||||
{
|
||||
int status;
|
||||
struct ocfs2_journal_lock *lock;
|
||||
|
||||
BUG_ON(!inode);
|
||||
|
||||
lock = kmem_cache_alloc(ocfs2_lock_cache, GFP_NOFS);
|
||||
if (!lock) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(-ENOMEM);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!igrab(inode))
|
||||
BUG();
|
||||
lock->jl_inode = inode;
|
||||
|
||||
list_add_tail(&(lock->jl_lock_list), &(handle->locks));
|
||||
handle->num_locks++;
|
||||
|
||||
status = 0;
|
||||
bail:
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal,
|
||||
struct ocfs2_journal_handle *handle)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
struct ocfs2_journal_lock *lock;
|
||||
struct inode *inode;
|
||||
|
||||
list_for_each_safe(p, n, &(handle->locks)) {
|
||||
lock = list_entry(p, struct ocfs2_journal_lock,
|
||||
jl_lock_list);
|
||||
list_del(&lock->jl_lock_list);
|
||||
handle->num_locks--;
|
||||
|
||||
inode = lock->jl_inode;
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
if (atomic_read(&inode->i_count) == 1)
|
||||
mlog(ML_ERROR,
|
||||
"Inode %llu, I'm doing a last iput for!",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
iput(inode);
|
||||
kmem_cache_free(ocfs2_lock_cache, lock);
|
||||
}
|
||||
}
|
||||
|
||||
#define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * 5)
|
||||
|
||||
void ocfs2_set_journal_params(struct ocfs2_super *osb)
|
||||
@ -562,8 +355,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
|
||||
/* Skip recovery waits here - journal inode metadata never
|
||||
* changes in a live cluster so it can be considered an
|
||||
* exception to the rule. */
|
||||
status = ocfs2_meta_lock_full(inode, NULL, &bh, 1,
|
||||
OCFS2_META_LOCK_RECOVERY);
|
||||
status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY);
|
||||
if (status < 0) {
|
||||
if (status != -ERESTARTSYS)
|
||||
mlog(ML_ERROR, "Could not get lock on journal!\n");
|
||||
@ -1160,8 +952,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
|
||||
}
|
||||
SET_INODE_JOURNAL(inode);
|
||||
|
||||
status = ocfs2_meta_lock_full(inode, NULL, &bh, 1,
|
||||
OCFS2_META_LOCK_RECOVERY);
|
||||
status = ocfs2_meta_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY);
|
||||
if (status < 0) {
|
||||
mlog(0, "status returned from ocfs2_meta_lock=%d\n", status);
|
||||
if (status != -ERESTARTSYS)
|
||||
@ -1350,7 +1141,7 @@ static int ocfs2_trylock_journal(struct ocfs2_super *osb,
|
||||
SET_INODE_JOURNAL(inode);
|
||||
|
||||
flags = OCFS2_META_LOCK_RECOVERY | OCFS2_META_LOCK_NOQUEUE;
|
||||
status = ocfs2_meta_lock_full(inode, NULL, NULL, 1, flags);
|
||||
status = ocfs2_meta_lock_full(inode, NULL, 1, flags);
|
||||
if (status < 0) {
|
||||
if (status != -EAGAIN)
|
||||
mlog_errno(status);
|
||||
@ -1433,7 +1224,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, NULL, 0);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto out;
|
||||
|
@ -37,7 +37,6 @@ enum ocfs2_journal_state {
|
||||
|
||||
struct ocfs2_super;
|
||||
struct ocfs2_dinode;
|
||||
struct ocfs2_journal_handle;
|
||||
|
||||
struct ocfs2_journal {
|
||||
enum ocfs2_journal_state j_state; /* Journals current state */
|
||||
@ -133,44 +132,6 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
|
||||
spin_unlock(&trans_inc_lock);
|
||||
}
|
||||
|
||||
extern kmem_cache_t *ocfs2_lock_cache;
|
||||
|
||||
struct ocfs2_journal_lock {
|
||||
struct inode *jl_inode;
|
||||
struct list_head jl_lock_list;
|
||||
};
|
||||
|
||||
struct ocfs2_journal_handle {
|
||||
handle_t *k_handle; /* kernel handle. */
|
||||
struct ocfs2_journal *journal;
|
||||
u32 flags; /* see flags below. */
|
||||
int max_buffs; /* Buffs reserved by this handle */
|
||||
|
||||
/* The following two fields are for ocfs2_handle_add_lock */
|
||||
int num_locks;
|
||||
struct list_head locks; /* A bunch of locks to
|
||||
* release on commit. This
|
||||
* should be a list_head */
|
||||
|
||||
struct list_head inode_list;
|
||||
};
|
||||
|
||||
#define OCFS2_HANDLE_STARTED 1
|
||||
/* should we sync-commit this handle? */
|
||||
#define OCFS2_HANDLE_SYNC 2
|
||||
static inline int ocfs2_handle_started(struct ocfs2_journal_handle *handle)
|
||||
{
|
||||
return handle->flags & OCFS2_HANDLE_STARTED;
|
||||
}
|
||||
|
||||
static inline void ocfs2_handle_set_sync(struct ocfs2_journal_handle *handle, int sync)
|
||||
{
|
||||
if (sync)
|
||||
handle->flags |= OCFS2_HANDLE_SYNC;
|
||||
else
|
||||
handle->flags &= ~OCFS2_HANDLE_SYNC;
|
||||
}
|
||||
|
||||
/* Exported only for the journal struct init code in super.c. Do not call. */
|
||||
void ocfs2_complete_recovery(void *data);
|
||||
|
||||
@ -231,15 +192,14 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
|
||||
* Transaction Handling:
|
||||
* Manage the lifetime of a transaction handle.
|
||||
*
|
||||
* ocfs2_alloc_handle - Only allocate a handle so we can start putting
|
||||
* cluster locks on it. To actually change blocks,
|
||||
* call ocfs2_start_trans with the handle returned
|
||||
* from this function. You may call ocfs2_commit_trans
|
||||
* at any time in the lifetime of a handle.
|
||||
* ocfs2_start_trans - Begin a transaction. Give it an upper estimate of
|
||||
* the number of blocks that will be changed during
|
||||
* this handle.
|
||||
* ocfs2_commit_trans - Complete a handle.
|
||||
* ocfs2_commit_trans - Complete a handle. It might return -EIO if
|
||||
* the journal was aborted. The majority of paths don't
|
||||
* check the return value as an error there comes too
|
||||
* late to do anything (and will be picked up in a
|
||||
* later transaction).
|
||||
* ocfs2_extend_trans - Extend a handle by nblocks credits. This may
|
||||
* commit the handle to disk in the process, but will
|
||||
* not release any locks taken during the transaction.
|
||||
@ -249,24 +209,16 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
|
||||
* ocfs2_journal_dirty - Mark a journalled buffer as having dirty data.
|
||||
* ocfs2_journal_dirty_data - Indicate that a data buffer should go out before
|
||||
* the current handle commits.
|
||||
* ocfs2_handle_add_lock - Sometimes we need to delay lock release
|
||||
* until after a transaction has been completed. Use
|
||||
* ocfs2_handle_add_lock to indicate that a lock needs
|
||||
* to be released at the end of that handle. Locks
|
||||
* will be released in the order that they are added.
|
||||
* ocfs2_handle_add_inode - Add a locked inode to a transaction.
|
||||
*/
|
||||
|
||||
/* You must always start_trans with a number of buffs > 0, but it's
|
||||
* perfectly legal to go through an entire transaction without having
|
||||
* dirtied any buffers. */
|
||||
struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb);
|
||||
struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *ocfs2_start_trans(struct ocfs2_super *osb,
|
||||
int max_buffs);
|
||||
void ocfs2_commit_trans(struct ocfs2_journal_handle *handle);
|
||||
int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
|
||||
int nblocks);
|
||||
int ocfs2_commit_trans(struct ocfs2_super *osb,
|
||||
handle_t *handle);
|
||||
int ocfs2_extend_trans(handle_t *handle, int nblocks);
|
||||
|
||||
/*
|
||||
* Create access is for when we get a newly created buffer and we're
|
||||
@ -283,7 +235,7 @@ int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
|
||||
#define OCFS2_JOURNAL_ACCESS_WRITE 1
|
||||
#define OCFS2_JOURNAL_ACCESS_UNDO 2
|
||||
|
||||
int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_journal_access(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh,
|
||||
int type);
|
||||
@ -306,18 +258,10 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
|
||||
* <modify the bh>
|
||||
* ocfs2_journal_dirty(handle, bh);
|
||||
*/
|
||||
int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_journal_dirty(handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle,
|
||||
struct inode *inode);
|
||||
/*
|
||||
* Use this to protect from other processes reading buffer state while
|
||||
* it's in flight.
|
||||
*/
|
||||
void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle,
|
||||
struct inode *inode);
|
||||
|
||||
/*
|
||||
* Credit Macros:
|
||||
|
@ -58,19 +58,18 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
|
||||
static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc);
|
||||
|
||||
static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_dinode *alloc,
|
||||
struct inode *main_bm_inode,
|
||||
struct buffer_head *main_bm_bh);
|
||||
|
||||
static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_alloc_context **ac,
|
||||
struct inode **bitmap_inode,
|
||||
struct buffer_head **bitmap_bh);
|
||||
|
||||
static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac);
|
||||
|
||||
static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
|
||||
@ -196,7 +195,7 @@ bail:
|
||||
void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
{
|
||||
int status;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle;
|
||||
struct inode *local_alloc_inode = NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct buffer_head *main_bm_bh = NULL;
|
||||
@ -207,7 +206,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
mlog_entry_void();
|
||||
|
||||
if (osb->local_alloc_state == OCFS2_LA_UNUSED)
|
||||
goto bail;
|
||||
goto out;
|
||||
|
||||
local_alloc_inode =
|
||||
ocfs2_get_system_file_inode(osb,
|
||||
@ -216,40 +215,34 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
if (!local_alloc_inode) {
|
||||
status = -ENOENT;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
osb->local_alloc_state = OCFS2_LA_DISABLED;
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
main_bm_inode = ocfs2_get_system_file_inode(osb,
|
||||
GLOBAL_BITMAP_SYSTEM_INODE,
|
||||
OCFS2_INVALID_SLOT);
|
||||
if (!main_bm_inode) {
|
||||
status = -EINVAL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ocfs2_handle_add_inode(handle, main_bm_inode);
|
||||
status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1);
|
||||
mutex_lock(&main_bm_inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(main_bm_inode, &main_bm_bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_mutex;
|
||||
}
|
||||
|
||||
/* WINDOW_MOVE_CREDITS is a bit heavy... */
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
mlog_errno(PTR_ERR(handle));
|
||||
handle = NULL;
|
||||
goto bail;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
bh = osb->local_alloc_bh;
|
||||
@ -258,7 +251,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
alloc_copy = kmalloc(bh->b_size, GFP_KERNEL);
|
||||
if (!alloc_copy) {
|
||||
status = -ENOMEM;
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
memcpy(alloc_copy, alloc, bh->b_size);
|
||||
|
||||
@ -266,7 +259,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
ocfs2_clear_local_alloc(alloc);
|
||||
@ -274,7 +267,7 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
status = ocfs2_journal_dirty(handle, bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
brelse(bh);
|
||||
@ -286,16 +279,20 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
out_commit:
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
out_unlock:
|
||||
if (main_bm_bh)
|
||||
brelse(main_bm_bh);
|
||||
|
||||
if (main_bm_inode)
|
||||
iput(main_bm_inode);
|
||||
ocfs2_meta_unlock(main_bm_inode, 1);
|
||||
|
||||
out_mutex:
|
||||
mutex_unlock(&main_bm_inode->i_mutex);
|
||||
iput(main_bm_inode);
|
||||
|
||||
out:
|
||||
if (local_alloc_inode)
|
||||
iput(local_alloc_inode);
|
||||
|
||||
@ -385,61 +382,59 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
|
||||
struct ocfs2_dinode *alloc)
|
||||
{
|
||||
int status;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle;
|
||||
struct buffer_head *main_bm_bh = NULL;
|
||||
struct inode *main_bm_inode = NULL;
|
||||
struct inode *main_bm_inode;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
main_bm_inode = ocfs2_get_system_file_inode(osb,
|
||||
GLOBAL_BITMAP_SYSTEM_INODE,
|
||||
OCFS2_INVALID_SLOT);
|
||||
if (!main_bm_inode) {
|
||||
status = -EINVAL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ocfs2_handle_add_inode(handle, main_bm_inode);
|
||||
status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1);
|
||||
mutex_lock(&main_bm_inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(main_bm_inode, &main_bm_bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_mutex;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* we want the bitmap change to be recorded on disk asap */
|
||||
ocfs2_handle_set_sync(handle, 1);
|
||||
handle->h_sync = 1;
|
||||
|
||||
status = ocfs2_sync_local_to_main(osb, handle, alloc,
|
||||
main_bm_inode, main_bm_bh);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
out_unlock:
|
||||
ocfs2_meta_unlock(main_bm_inode, 1);
|
||||
|
||||
out_mutex:
|
||||
mutex_unlock(&main_bm_inode->i_mutex);
|
||||
|
||||
if (main_bm_bh)
|
||||
brelse(main_bm_bh);
|
||||
|
||||
if (main_bm_inode)
|
||||
iput(main_bm_inode);
|
||||
iput(main_bm_inode);
|
||||
|
||||
out:
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
@ -452,7 +447,6 @@ bail:
|
||||
* our own in order to shift windows.
|
||||
*/
|
||||
int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *passed_handle,
|
||||
u32 bits_wanted,
|
||||
struct ocfs2_alloc_context *ac)
|
||||
{
|
||||
@ -463,9 +457,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
BUG_ON(!passed_handle);
|
||||
BUG_ON(!ac);
|
||||
BUG_ON(passed_handle->flags & OCFS2_HANDLE_STARTED);
|
||||
|
||||
local_alloc_inode =
|
||||
ocfs2_get_system_file_inode(osb,
|
||||
@ -476,7 +468,11 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
ocfs2_handle_add_inode(passed_handle, local_alloc_inode);
|
||||
|
||||
mutex_lock(&local_alloc_inode->i_mutex);
|
||||
|
||||
ac->ac_inode = local_alloc_inode;
|
||||
ac->ac_which = OCFS2_AC_USE_LOCAL;
|
||||
|
||||
if (osb->local_alloc_state != OCFS2_LA_ENABLED) {
|
||||
status = -ENOSPC;
|
||||
@ -515,21 +511,17 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
|
||||
}
|
||||
}
|
||||
|
||||
ac->ac_inode = igrab(local_alloc_inode);
|
||||
get_bh(osb->local_alloc_bh);
|
||||
ac->ac_bh = osb->local_alloc_bh;
|
||||
ac->ac_which = OCFS2_AC_USE_LOCAL;
|
||||
status = 0;
|
||||
bail:
|
||||
if (local_alloc_inode)
|
||||
iput(local_alloc_inode);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 min_bits,
|
||||
u32 *bit_off,
|
||||
@ -707,7 +699,7 @@ static void ocfs2_verify_zero_bits(unsigned long *bitmap,
|
||||
* passed is used for caching.
|
||||
*/
|
||||
static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_dinode *alloc,
|
||||
struct inode *main_bm_inode,
|
||||
struct buffer_head *main_bm_bh)
|
||||
@ -778,7 +770,6 @@ bail:
|
||||
}
|
||||
|
||||
static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_alloc_context **ac,
|
||||
struct inode **bitmap_inode,
|
||||
struct buffer_head **bitmap_bh)
|
||||
@ -792,7 +783,6 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
(*ac)->ac_handle = handle;
|
||||
(*ac)->ac_bits_wanted = ocfs2_local_alloc_window_bits(osb);
|
||||
|
||||
status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
|
||||
@ -821,7 +811,7 @@ bail:
|
||||
* pass it the bitmap lock in lock_bh if you have it.
|
||||
*/
|
||||
static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac)
|
||||
{
|
||||
int status = 0;
|
||||
@ -888,23 +878,15 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
|
||||
int status = 0;
|
||||
struct buffer_head *main_bm_bh = NULL;
|
||||
struct inode *main_bm_inode = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_dinode *alloc;
|
||||
struct ocfs2_dinode *alloc_copy = NULL;
|
||||
struct ocfs2_alloc_context *ac = NULL;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* This will lock the main bitmap for us. */
|
||||
status = ocfs2_local_alloc_reserve_for_window(osb,
|
||||
handle,
|
||||
&ac,
|
||||
&main_bm_inode,
|
||||
&main_bm_bh);
|
||||
@ -914,7 +896,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -972,7 +954,7 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
|
||||
status = 0;
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (main_bm_bh)
|
||||
brelse(main_bm_bh);
|
||||
|
@ -42,12 +42,11 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb,
|
||||
|
||||
struct ocfs2_alloc_context;
|
||||
int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *passed_handle,
|
||||
u32 bits_wanted,
|
||||
struct ocfs2_alloc_context *ac);
|
||||
|
||||
int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 min_bits,
|
||||
u32 *bit_off,
|
||||
|
@ -82,6 +82,8 @@ static struct vm_operations_struct ocfs2_file_vm_ops = {
|
||||
|
||||
int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
int ret = 0, lock_level = 0;
|
||||
|
||||
/* We don't want to support shared writable mappings yet. */
|
||||
if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
|
||||
&& ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
|
||||
@ -91,7 +93,14 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
file_accessed(file);
|
||||
ret = ocfs2_meta_lock_atime(file->f_dentry->d_inode,
|
||||
file->f_vfsmnt, &lock_level);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
|
||||
out:
|
||||
vma->vm_ops = &ocfs2_file_vm_ops;
|
||||
return 0;
|
||||
}
|
||||
|
296
fs/ocfs2/namei.c
296
fs/ocfs2/namei.c
@ -75,12 +75,12 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh,
|
||||
unsigned long offset,
|
||||
struct ocfs2_dir_entry **res_dir);
|
||||
|
||||
static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_delete_entry(handle_t *handle,
|
||||
struct inode *dir,
|
||||
struct ocfs2_dir_entry *de_del,
|
||||
struct buffer_head *bh);
|
||||
|
||||
static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
|
||||
static int __ocfs2_add_entry(handle_t *handle,
|
||||
struct inode *dir,
|
||||
const char *name, int namelen,
|
||||
struct inode *inode, u64 blkno,
|
||||
@ -93,43 +93,37 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||
dev_t dev,
|
||||
struct buffer_head **new_fe_bh,
|
||||
struct buffer_head *parent_fe_bh,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode **ret_inode,
|
||||
struct ocfs2_alloc_context *inode_ac);
|
||||
|
||||
static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *parent,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_alloc_context *data_ac);
|
||||
|
||||
static int ocfs2_double_lock(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **bh1,
|
||||
struct inode *inode1,
|
||||
struct buffer_head **bh2,
|
||||
struct inode *inode2);
|
||||
|
||||
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct inode **ret_orphan_dir,
|
||||
struct inode *inode,
|
||||
char *name,
|
||||
struct buffer_head **de_bh);
|
||||
|
||||
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct ocfs2_dinode *fe,
|
||||
char *name,
|
||||
struct buffer_head *de_bh);
|
||||
struct buffer_head *de_bh,
|
||||
struct inode *orphan_dir_inode);
|
||||
|
||||
static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
const char *symname);
|
||||
|
||||
static inline int ocfs2_add_entry(struct ocfs2_journal_handle *handle,
|
||||
static inline int ocfs2_add_entry(handle_t *handle,
|
||||
struct dentry *dentry,
|
||||
struct inode *inode, u64 blkno,
|
||||
struct buffer_head *parent_fe_bh,
|
||||
@ -165,7 +159,7 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
|
||||
mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
|
||||
dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
|
||||
|
||||
status = ocfs2_meta_lock(dir, NULL, NULL, 0);
|
||||
status = ocfs2_meta_lock(dir, NULL, 0);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
@ -242,7 +236,7 @@ bail:
|
||||
}
|
||||
|
||||
static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *parent,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
@ -317,7 +311,7 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
{
|
||||
int status = 0;
|
||||
struct buffer_head *parent_fe_bh = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_super *osb;
|
||||
struct ocfs2_dinode *dirfe;
|
||||
struct buffer_head *new_fe_bh = NULL;
|
||||
@ -333,18 +327,11 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
/* get our super block */
|
||||
osb = OCFS2_SB(dir->i_sb);
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
|
||||
status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
|
||||
@ -374,7 +361,7 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
}
|
||||
|
||||
/* reserve an inode spot */
|
||||
status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
|
||||
status = ocfs2_reserve_new_inode(osb, &inode_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -384,7 +371,7 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
/* are we making a directory? If so, reserve a cluster for his
|
||||
* 1st extent. */
|
||||
if (S_ISDIR(mode)) {
|
||||
status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
|
||||
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -392,7 +379,7 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_MKNOD_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -453,7 +440,9 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
status = 0;
|
||||
leave:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
ocfs2_meta_unlock(dir, 1);
|
||||
|
||||
if (status == -ENOSPC)
|
||||
mlog(0, "Disk is full\n");
|
||||
@ -487,7 +476,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||
dev_t dev,
|
||||
struct buffer_head **new_fe_bh,
|
||||
struct buffer_head *parent_fe_bh,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode **ret_inode,
|
||||
struct ocfs2_alloc_context *inode_ac)
|
||||
{
|
||||
@ -653,7 +642,7 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle;
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
int err;
|
||||
struct buffer_head *fe_bh = NULL;
|
||||
@ -666,68 +655,60 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
old_dentry->d_name.len, old_dentry->d_name.name,
|
||||
dentry->d_name.len, dentry->d_name.name);
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
err = -EPERM;
|
||||
goto bail;
|
||||
}
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
return -EPERM;
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
err = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
|
||||
err = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
|
||||
if (err < 0) {
|
||||
if (err != -ENOENT)
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!dir->i_nlink) {
|
||||
err = -ENOENT;
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
|
||||
dentry->d_name.len);
|
||||
if (err)
|
||||
goto bail;
|
||||
goto out;
|
||||
|
||||
err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
|
||||
dentry->d_name.name,
|
||||
dentry->d_name.len, &de_bh);
|
||||
if (err < 0) {
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
|
||||
err = ocfs2_meta_lock(inode, &fe_bh, 1);
|
||||
if (err < 0) {
|
||||
if (err != -ENOENT)
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fe = (struct ocfs2_dinode *) fe_bh->b_data;
|
||||
if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) {
|
||||
err = -EMLINK;
|
||||
goto bail;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_LINK_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
err = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
|
||||
err = ocfs2_journal_access(handle, inode, fe_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (err < 0) {
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
inc_nlink(inode);
|
||||
@ -741,7 +722,7 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
le16_add_cpu(&fe->i_links_count, -1);
|
||||
drop_nlink(inode);
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
err = ocfs2_add_entry(handle, dentry, inode,
|
||||
@ -751,21 +732,27 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
le16_add_cpu(&fe->i_links_count, -1);
|
||||
drop_nlink(inode);
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
|
||||
if (err) {
|
||||
mlog_errno(err);
|
||||
goto bail;
|
||||
goto out_commit;
|
||||
}
|
||||
|
||||
atomic_inc(&inode->i_count);
|
||||
dentry->d_op = &ocfs2_dentry_ops;
|
||||
d_instantiate(dentry, inode);
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
|
||||
out_commit:
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out_unlock_inode:
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
|
||||
out:
|
||||
ocfs2_meta_unlock(dir, 1);
|
||||
|
||||
if (de_bh)
|
||||
brelse(de_bh);
|
||||
if (fe_bh)
|
||||
@ -812,13 +799,15 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
int status;
|
||||
int child_locked = 0;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct inode *orphan_dir = NULL;
|
||||
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
|
||||
u64 blkno;
|
||||
struct ocfs2_dinode *fe = NULL;
|
||||
struct buffer_head *fe_bh = NULL;
|
||||
struct buffer_head *parent_node_bh = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_dir_entry *dirent = NULL;
|
||||
struct buffer_head *dirent_bh = NULL;
|
||||
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
|
||||
@ -833,22 +822,14 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
|
||||
if (inode == osb->root_inode) {
|
||||
mlog(0, "Cannot delete the root directory\n");
|
||||
status = -EPERM;
|
||||
goto leave;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(dir, handle, &parent_node_bh, 1);
|
||||
status = ocfs2_meta_lock(dir, &parent_node_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ocfs2_find_files_on_disk(dentry->d_name.name,
|
||||
@ -869,12 +850,13 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
|
||||
status = ocfs2_meta_lock(inode, &fe_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
child_locked = 1;
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
if (!ocfs2_empty_dir(inode)) {
|
||||
@ -895,7 +877,7 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
}
|
||||
|
||||
if (inode_is_unlinkable(inode)) {
|
||||
status = ocfs2_prepare_orphan_dir(osb, handle, inode,
|
||||
status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, inode,
|
||||
orphan_name,
|
||||
&orphan_entry_bh);
|
||||
if (status < 0) {
|
||||
@ -904,7 +886,7 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_UNLINK_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -923,7 +905,7 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
|
||||
if (inode_is_unlinkable(inode)) {
|
||||
status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
|
||||
orphan_entry_bh);
|
||||
orphan_entry_bh, orphan_dir);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
@ -960,7 +942,19 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
|
||||
leave:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (child_locked)
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
|
||||
ocfs2_meta_unlock(dir, 1);
|
||||
|
||||
if (orphan_dir) {
|
||||
/* This was locked for us in ocfs2_prepare_orphan_dir() */
|
||||
ocfs2_meta_unlock(orphan_dir, 1);
|
||||
mutex_unlock(&orphan_dir->i_mutex);
|
||||
iput(orphan_dir);
|
||||
}
|
||||
|
||||
if (fe_bh)
|
||||
brelse(fe_bh);
|
||||
@ -984,7 +978,6 @@ leave:
|
||||
* if they have the same id, then the 1st one is the only one locked.
|
||||
*/
|
||||
static int ocfs2_double_lock(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct buffer_head **bh1,
|
||||
struct inode *inode1,
|
||||
struct buffer_head **bh2,
|
||||
@ -1000,8 +993,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
|
||||
(unsigned long long)oi1->ip_blkno,
|
||||
(unsigned long long)oi2->ip_blkno);
|
||||
|
||||
BUG_ON(!handle);
|
||||
|
||||
if (*bh1)
|
||||
*bh1 = NULL;
|
||||
if (*bh2)
|
||||
@ -1021,25 +1012,41 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
|
||||
inode1 = tmpinode;
|
||||
}
|
||||
/* lock id2 */
|
||||
status = ocfs2_meta_lock(inode2, handle, bh2, 1);
|
||||
status = ocfs2_meta_lock(inode2, bh2, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
/* lock id1 */
|
||||
status = ocfs2_meta_lock(inode1, handle, bh1, 1);
|
||||
status = ocfs2_meta_lock(inode1, bh1, 1);
|
||||
if (status < 0) {
|
||||
/*
|
||||
* An error return must mean that no cluster locks
|
||||
* were held on function exit.
|
||||
*/
|
||||
if (oi1->ip_blkno != oi2->ip_blkno)
|
||||
ocfs2_meta_unlock(inode2, 1);
|
||||
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
bail:
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
|
||||
{
|
||||
ocfs2_meta_unlock(inode1, 1);
|
||||
|
||||
if (inode1 != inode2)
|
||||
ocfs2_meta_unlock(inode2, 1);
|
||||
}
|
||||
|
||||
#define PARENT_INO(buffer) \
|
||||
((struct ocfs2_dir_entry *) \
|
||||
((char *)buffer + \
|
||||
@ -1050,9 +1057,11 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
struct inode *new_dir,
|
||||
struct dentry *new_dentry)
|
||||
{
|
||||
int status = 0, rename_lock = 0;
|
||||
int status = 0, rename_lock = 0, parents_locked = 0;
|
||||
int old_child_locked = 0, new_child_locked = 0;
|
||||
struct inode *old_inode = old_dentry->d_inode;
|
||||
struct inode *new_inode = new_dentry->d_inode;
|
||||
struct inode *orphan_dir = NULL;
|
||||
struct ocfs2_dinode *newfe = NULL;
|
||||
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
|
||||
struct buffer_head *orphan_entry_bh = NULL;
|
||||
@ -1060,7 +1069,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
struct buffer_head *insert_entry_bh = NULL;
|
||||
struct ocfs2_super *osb = NULL;
|
||||
u64 newfe_blkno;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct buffer_head *old_dir_bh = NULL;
|
||||
struct buffer_head *new_dir_bh = NULL;
|
||||
struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry
|
||||
@ -1105,21 +1114,14 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
rename_lock = 1;
|
||||
}
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* if old and new are the same, this'll just do one lock. */
|
||||
status = ocfs2_double_lock(osb, handle,
|
||||
&old_dir_bh, old_dir,
|
||||
&new_dir_bh, new_dir);
|
||||
status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
|
||||
&new_dir_bh, new_dir);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
parents_locked = 1;
|
||||
|
||||
/* make sure both dirs have bhs
|
||||
* get an extra ref on old_dir_bh if old==new */
|
||||
@ -1140,12 +1142,13 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
* the vote thread on other nodes won't have to concurrently
|
||||
* downconvert the inode and the dentry locks.
|
||||
*/
|
||||
status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
|
||||
status = ocfs2_meta_lock(old_inode, NULL, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
old_child_locked = 1;
|
||||
|
||||
status = ocfs2_remote_dentry_delete(old_dentry);
|
||||
if (status < 0) {
|
||||
@ -1231,12 +1234,13 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1);
|
||||
status = ocfs2_meta_lock(new_inode, &newfe_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
new_child_locked = 1;
|
||||
|
||||
status = ocfs2_remote_dentry_delete(new_dentry);
|
||||
if (status < 0) {
|
||||
@ -1252,7 +1256,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
(unsigned long long)newfe_bh->b_blocknr : 0ULL);
|
||||
|
||||
if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
|
||||
status = ocfs2_prepare_orphan_dir(osb, handle,
|
||||
status = ocfs2_prepare_orphan_dir(osb, &orphan_dir,
|
||||
new_inode,
|
||||
orphan_name,
|
||||
&orphan_entry_bh);
|
||||
@ -1280,7 +1284,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, OCFS2_RENAME_CREDITS);
|
||||
handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -1307,7 +1311,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
(newfe->i_links_count == cpu_to_le16(1))){
|
||||
status = ocfs2_orphan_add(osb, handle, new_inode,
|
||||
newfe, orphan_name,
|
||||
orphan_entry_bh);
|
||||
orphan_entry_bh, orphan_dir);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@ -1424,7 +1428,23 @@ bail:
|
||||
ocfs2_rename_unlock(osb);
|
||||
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (parents_locked)
|
||||
ocfs2_double_unlock(old_dir, new_dir);
|
||||
|
||||
if (old_child_locked)
|
||||
ocfs2_meta_unlock(old_inode, 1);
|
||||
|
||||
if (new_child_locked)
|
||||
ocfs2_meta_unlock(new_inode, 1);
|
||||
|
||||
if (orphan_dir) {
|
||||
/* This was locked for us in ocfs2_prepare_orphan_dir() */
|
||||
ocfs2_meta_unlock(orphan_dir, 1);
|
||||
mutex_unlock(&orphan_dir->i_mutex);
|
||||
iput(orphan_dir);
|
||||
}
|
||||
|
||||
if (new_inode)
|
||||
sync_mapping_buffers(old_inode->i_mapping);
|
||||
@ -1458,7 +1478,7 @@ bail:
|
||||
* data, including the null terminator.
|
||||
*/
|
||||
static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
const char *symname)
|
||||
{
|
||||
@ -1573,7 +1593,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
struct buffer_head *parent_fe_bh = NULL;
|
||||
struct ocfs2_dinode *fe = NULL;
|
||||
struct ocfs2_dinode *dirfe;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct ocfs2_alloc_context *inode_ac = NULL;
|
||||
struct ocfs2_alloc_context *data_ac = NULL;
|
||||
|
||||
@ -1587,19 +1607,12 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
|
||||
credits = ocfs2_calc_symlink_credits(sb);
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (handle == NULL) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* lock the parent directory */
|
||||
status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
|
||||
status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
|
||||
if (status < 0) {
|
||||
if (status != -ENOENT)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
return status;
|
||||
}
|
||||
|
||||
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
|
||||
@ -1622,7 +1635,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
|
||||
status = ocfs2_reserve_new_inode(osb, &inode_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -1631,7 +1644,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
|
||||
/* don't reserve bitmap space for fast symlinks. */
|
||||
if (l > ocfs2_fast_symlink_chars(sb)) {
|
||||
status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
|
||||
status = ocfs2_reserve_clusters(osb, 1, &data_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -1639,7 +1652,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
}
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, handle, credits);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -1717,7 +1730,10 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
d_instantiate(dentry, inode);
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
ocfs2_meta_unlock(dir, 1);
|
||||
|
||||
if (new_fe_bh)
|
||||
brelse(new_fe_bh);
|
||||
if (parent_fe_bh)
|
||||
@ -1768,7 +1784,7 @@ int ocfs2_check_dir_entry(struct inode * dir,
|
||||
* If you pass me insert_bh, I'll skip the search of the other dir
|
||||
* blocks and put the record in there.
|
||||
*/
|
||||
static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
|
||||
static int __ocfs2_add_entry(handle_t *handle,
|
||||
struct inode *dir,
|
||||
const char *name, int namelen,
|
||||
struct inode *inode, u64 blkno,
|
||||
@ -1854,7 +1870,7 @@ bail:
|
||||
* ocfs2_delete_entry deletes a directory entry by merging it with the
|
||||
* previous entry
|
||||
*/
|
||||
static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_delete_entry(handle_t *handle,
|
||||
struct inode *dir,
|
||||
struct ocfs2_dir_entry *de_del,
|
||||
struct buffer_head *bh)
|
||||
@ -2085,19 +2101,19 @@ bail:
|
||||
}
|
||||
|
||||
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct inode **ret_orphan_dir,
|
||||
struct inode *inode,
|
||||
char *name,
|
||||
struct buffer_head **de_bh)
|
||||
{
|
||||
struct inode *orphan_dir_inode = NULL;
|
||||
struct inode *orphan_dir_inode;
|
||||
struct buffer_head *orphan_dir_bh = NULL;
|
||||
int status = 0;
|
||||
|
||||
status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
return status;
|
||||
}
|
||||
|
||||
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
||||
@ -2106,11 +2122,12 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||
if (!orphan_dir_inode) {
|
||||
status = -ENOENT;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
return status;
|
||||
}
|
||||
|
||||
ocfs2_handle_add_inode(handle, orphan_dir_inode);
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, handle, &orphan_dir_bh, 1);
|
||||
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
@ -2120,13 +2137,19 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
|
||||
orphan_dir_bh, name,
|
||||
OCFS2_ORPHAN_NAMELEN, de_bh);
|
||||
if (status < 0) {
|
||||
ocfs2_meta_unlock(orphan_dir_inode, 1);
|
||||
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
*ret_orphan_dir = orphan_dir_inode;
|
||||
|
||||
leave:
|
||||
if (orphan_dir_inode)
|
||||
if (status) {
|
||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||
iput(orphan_dir_inode);
|
||||
}
|
||||
|
||||
if (orphan_dir_bh)
|
||||
brelse(orphan_dir_bh);
|
||||
@ -2136,28 +2159,19 @@ leave:
|
||||
}
|
||||
|
||||
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct ocfs2_dinode *fe,
|
||||
char *name,
|
||||
struct buffer_head *de_bh)
|
||||
struct buffer_head *de_bh,
|
||||
struct inode *orphan_dir_inode)
|
||||
{
|
||||
struct inode *orphan_dir_inode = NULL;
|
||||
struct buffer_head *orphan_dir_bh = NULL;
|
||||
int status = 0;
|
||||
struct ocfs2_dinode *orphan_fe;
|
||||
|
||||
mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
|
||||
|
||||
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
||||
ORPHAN_DIR_SYSTEM_INODE,
|
||||
osb->slot_num);
|
||||
if (!orphan_dir_inode) {
|
||||
status = -ENOENT;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_read_block(osb,
|
||||
OCFS2_I(orphan_dir_inode)->ip_blkno,
|
||||
&orphan_dir_bh, OCFS2_BH_CACHED,
|
||||
@ -2209,9 +2223,6 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
|
||||
|
||||
leave:
|
||||
if (orphan_dir_inode)
|
||||
iput(orphan_dir_inode);
|
||||
|
||||
if (orphan_dir_bh)
|
||||
brelse(orphan_dir_bh);
|
||||
|
||||
@ -2221,7 +2232,7 @@ leave:
|
||||
|
||||
/* unlike orphan_add, we expect the orphan dir to already be locked here. */
|
||||
int ocfs2_orphan_del(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *orphan_dir_inode,
|
||||
struct inode *inode,
|
||||
struct buffer_head *orphan_dir_bh)
|
||||
@ -2300,4 +2311,5 @@ struct inode_operations ocfs2_dir_iops = {
|
||||
.rename = ocfs2_rename,
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
};
|
||||
|
@ -39,7 +39,7 @@ struct buffer_head *ocfs2_find_entry(const char *name,
|
||||
struct inode *dir,
|
||||
struct ocfs2_dir_entry **res_dir);
|
||||
int ocfs2_orphan_del(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct inode *orphan_dir_inode,
|
||||
struct inode *inode,
|
||||
struct buffer_head *orphan_dir_bh);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/jbd.h>
|
||||
|
||||
#include "cluster/nodemanager.h"
|
||||
#include "cluster/heartbeat.h"
|
||||
@ -179,9 +180,9 @@ enum ocfs2_mount_options
|
||||
#define OCFS2_OSB_SOFT_RO 0x0001
|
||||
#define OCFS2_OSB_HARD_RO 0x0002
|
||||
#define OCFS2_OSB_ERROR_FS 0x0004
|
||||
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
|
||||
|
||||
struct ocfs2_journal;
|
||||
struct ocfs2_journal_handle;
|
||||
struct ocfs2_super
|
||||
{
|
||||
struct task_struct *commit_task;
|
||||
@ -218,6 +219,7 @@ struct ocfs2_super
|
||||
unsigned long osb_flags;
|
||||
|
||||
unsigned long s_mount_opt;
|
||||
unsigned int s_atime_quantum;
|
||||
|
||||
u16 max_slots;
|
||||
s16 node_num;
|
||||
|
@ -49,7 +49,7 @@
|
||||
static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
|
||||
static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
|
||||
static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
|
||||
static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_block_group_fill(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *bg_bh,
|
||||
u64 group_blkno,
|
||||
@ -59,9 +59,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *bh);
|
||||
|
||||
static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_alloc_context *ac);
|
||||
|
||||
static int ocfs2_cluster_group_search(struct inode *inode,
|
||||
struct buffer_head *group_bh,
|
||||
u32 bits_wanted, u32 min_bits,
|
||||
@ -72,6 +69,7 @@ static int ocfs2_block_group_search(struct inode *inode,
|
||||
u16 *bit_off, u16 *bits_found);
|
||||
static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
handle_t *handle,
|
||||
u32 bits_wanted,
|
||||
u32 min_bits,
|
||||
u16 *bit_off,
|
||||
@ -79,20 +77,20 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
u64 *bg_blkno);
|
||||
static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
|
||||
int nr);
|
||||
static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
|
||||
static inline int ocfs2_block_group_set_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct ocfs2_group_desc *bg,
|
||||
struct buffer_head *group_bh,
|
||||
unsigned int bit_off,
|
||||
unsigned int num_bits);
|
||||
static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
|
||||
static inline int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct ocfs2_group_desc *bg,
|
||||
struct buffer_head *group_bh,
|
||||
unsigned int bit_off,
|
||||
unsigned int num_bits);
|
||||
|
||||
static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_relink_block_group(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct buffer_head *bg_bh,
|
||||
@ -100,7 +98,7 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
|
||||
u16 chain);
|
||||
static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
|
||||
u32 wanted);
|
||||
static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_free_suballoc_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *alloc_bh,
|
||||
unsigned int start_bit,
|
||||
@ -120,8 +118,16 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
|
||||
|
||||
void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
|
||||
{
|
||||
if (ac->ac_inode)
|
||||
iput(ac->ac_inode);
|
||||
struct inode *inode = ac->ac_inode;
|
||||
|
||||
if (inode) {
|
||||
if (ac->ac_which != OCFS2_AC_USE_LOCAL)
|
||||
ocfs2_meta_unlock(inode, 1);
|
||||
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
iput(inode);
|
||||
}
|
||||
if (ac->ac_bh)
|
||||
brelse(ac->ac_bh);
|
||||
kfree(ac);
|
||||
@ -190,7 +196,7 @@ static int ocfs2_check_group_descriptor(struct super_block *sb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_block_group_fill(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *bg_bh,
|
||||
u64 group_blkno,
|
||||
@ -273,7 +279,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
|
||||
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
|
||||
struct ocfs2_chain_list *cl;
|
||||
struct ocfs2_alloc_context *ac = NULL;
|
||||
struct ocfs2_journal_handle *handle = NULL;
|
||||
handle_t *handle = NULL;
|
||||
u32 bit_off, num_bits;
|
||||
u16 alloc_rec;
|
||||
u64 bg_blkno;
|
||||
@ -284,16 +290,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
handle = ocfs2_alloc_handle(osb);
|
||||
if (!handle) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
cl = &fe->id2.i_chain;
|
||||
status = ocfs2_reserve_clusters(osb,
|
||||
handle,
|
||||
le16_to_cpu(cl->cl_cpg),
|
||||
&ac);
|
||||
if (status < 0) {
|
||||
@ -304,7 +302,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
|
||||
|
||||
credits = ocfs2_calc_group_alloc_credits(osb->sb,
|
||||
le16_to_cpu(cl->cl_cpg));
|
||||
handle = ocfs2_start_trans(osb, handle, credits);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
@ -389,7 +387,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
|
||||
status = 0;
|
||||
bail:
|
||||
if (handle)
|
||||
ocfs2_commit_trans(handle);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
if (ac)
|
||||
ocfs2_free_alloc_context(ac);
|
||||
@ -402,27 +400,38 @@ bail:
|
||||
}
|
||||
|
||||
static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_alloc_context *ac)
|
||||
struct ocfs2_alloc_context *ac,
|
||||
int type,
|
||||
u32 slot)
|
||||
{
|
||||
int status;
|
||||
u32 bits_wanted = ac->ac_bits_wanted;
|
||||
struct inode *alloc_inode = ac->ac_inode;
|
||||
struct inode *alloc_inode;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct ocfs2_journal_handle *handle = ac->ac_handle;
|
||||
struct ocfs2_dinode *fe;
|
||||
u32 free_bits;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
BUG_ON(handle->flags & OCFS2_HANDLE_STARTED);
|
||||
|
||||
ocfs2_handle_add_inode(handle, alloc_inode);
|
||||
status = ocfs2_meta_lock(alloc_inode, handle, &bh, 1);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
alloc_inode = ocfs2_get_system_file_inode(osb, type, slot);
|
||||
if (!alloc_inode) {
|
||||
mlog_errno(-EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&alloc_inode->i_mutex);
|
||||
|
||||
status = ocfs2_meta_lock(alloc_inode, &bh, 1);
|
||||
if (status < 0) {
|
||||
mutex_unlock(&alloc_inode->i_mutex);
|
||||
iput(alloc_inode);
|
||||
|
||||
mlog_errno(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ac->ac_inode = alloc_inode;
|
||||
|
||||
fe = (struct ocfs2_dinode *) bh->b_data;
|
||||
if (!OCFS2_IS_VALID_DINODE(fe)) {
|
||||
OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
|
||||
@ -473,12 +482,11 @@ bail:
|
||||
}
|
||||
|
||||
int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_dinode *fe,
|
||||
struct ocfs2_alloc_context **ac)
|
||||
{
|
||||
int status;
|
||||
struct inode *alloc_inode = NULL;
|
||||
u32 slot;
|
||||
|
||||
*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
|
||||
if (!(*ac)) {
|
||||
@ -488,28 +496,18 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
(*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
|
||||
(*ac)->ac_handle = handle;
|
||||
(*ac)->ac_which = OCFS2_AC_USE_META;
|
||||
|
||||
#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
|
||||
alloc_inode = ocfs2_get_system_file_inode(osb,
|
||||
EXTENT_ALLOC_SYSTEM_INODE,
|
||||
0);
|
||||
slot = 0;
|
||||
#else
|
||||
alloc_inode = ocfs2_get_system_file_inode(osb,
|
||||
EXTENT_ALLOC_SYSTEM_INODE,
|
||||
osb->slot_num);
|
||||
slot = osb->slot_num;
|
||||
#endif
|
||||
if (!alloc_inode) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
(*ac)->ac_inode = igrab(alloc_inode);
|
||||
(*ac)->ac_group_search = ocfs2_block_group_search;
|
||||
|
||||
status = ocfs2_reserve_suballoc_bits(osb, (*ac));
|
||||
status = ocfs2_reserve_suballoc_bits(osb, (*ac),
|
||||
EXTENT_ALLOC_SYSTEM_INODE, slot);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -523,19 +521,14 @@ bail:
|
||||
*ac = NULL;
|
||||
}
|
||||
|
||||
if (alloc_inode)
|
||||
iput(alloc_inode);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_alloc_context **ac)
|
||||
{
|
||||
int status;
|
||||
struct inode *alloc_inode = NULL;
|
||||
|
||||
*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
|
||||
if (!(*ac)) {
|
||||
@ -545,22 +538,13 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
(*ac)->ac_bits_wanted = 1;
|
||||
(*ac)->ac_handle = handle;
|
||||
(*ac)->ac_which = OCFS2_AC_USE_INODE;
|
||||
|
||||
alloc_inode = ocfs2_get_system_file_inode(osb,
|
||||
INODE_ALLOC_SYSTEM_INODE,
|
||||
osb->slot_num);
|
||||
if (!alloc_inode) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
(*ac)->ac_inode = igrab(alloc_inode);
|
||||
(*ac)->ac_group_search = ocfs2_block_group_search;
|
||||
|
||||
status = ocfs2_reserve_suballoc_bits(osb, *ac);
|
||||
status = ocfs2_reserve_suballoc_bits(osb, *ac,
|
||||
INODE_ALLOC_SYSTEM_INODE,
|
||||
osb->slot_num);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@ -574,9 +558,6 @@ bail:
|
||||
*ac = NULL;
|
||||
}
|
||||
|
||||
if (alloc_inode)
|
||||
iput(alloc_inode);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
@ -588,20 +569,17 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
|
||||
{
|
||||
int status;
|
||||
|
||||
ac->ac_inode = ocfs2_get_system_file_inode(osb,
|
||||
GLOBAL_BITMAP_SYSTEM_INODE,
|
||||
OCFS2_INVALID_SLOT);
|
||||
if (!ac->ac_inode) {
|
||||
status = -EINVAL;
|
||||
mlog(ML_ERROR, "Could not get bitmap inode!\n");
|
||||
goto bail;
|
||||
}
|
||||
ac->ac_which = OCFS2_AC_USE_MAIN;
|
||||
ac->ac_group_search = ocfs2_cluster_group_search;
|
||||
|
||||
status = ocfs2_reserve_suballoc_bits(osb, ac);
|
||||
if (status < 0 && status != -ENOSPC)
|
||||
status = ocfs2_reserve_suballoc_bits(osb, ac,
|
||||
GLOBAL_BITMAP_SYSTEM_INODE,
|
||||
OCFS2_INVALID_SLOT);
|
||||
if (status < 0 && status != -ENOSPC) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
bail:
|
||||
return status;
|
||||
}
|
||||
@ -610,7 +588,6 @@ bail:
|
||||
* use so we figure it out for them, but unfortunately this clutters
|
||||
* things a bit. */
|
||||
int ocfs2_reserve_clusters(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
u32 bits_wanted,
|
||||
struct ocfs2_alloc_context **ac)
|
||||
{
|
||||
@ -618,8 +595,6 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
BUG_ON(!handle);
|
||||
|
||||
*ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
|
||||
if (!(*ac)) {
|
||||
status = -ENOMEM;
|
||||
@ -628,12 +603,10 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
(*ac)->ac_bits_wanted = bits_wanted;
|
||||
(*ac)->ac_handle = handle;
|
||||
|
||||
status = -ENOSPC;
|
||||
if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
|
||||
status = ocfs2_reserve_local_alloc_bits(osb,
|
||||
handle,
|
||||
bits_wanted,
|
||||
*ac);
|
||||
if ((status < 0) && (status != -ENOSPC)) {
|
||||
@ -774,7 +747,7 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
|
||||
static inline int ocfs2_block_group_set_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct ocfs2_group_desc *bg,
|
||||
struct buffer_head *group_bh,
|
||||
@ -845,7 +818,7 @@ static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl)
|
||||
return best;
|
||||
}
|
||||
|
||||
static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_relink_block_group(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct buffer_head *bg_bh,
|
||||
@ -1025,7 +998,7 @@ static int ocfs2_block_group_search(struct inode *inode,
|
||||
}
|
||||
|
||||
static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct buffer_head *di_bh,
|
||||
u32 num_bits,
|
||||
u16 chain)
|
||||
@ -1055,6 +1028,7 @@ out:
|
||||
}
|
||||
|
||||
static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
|
||||
handle_t *handle,
|
||||
u32 bits_wanted,
|
||||
u32 min_bits,
|
||||
u16 *bit_off,
|
||||
@ -1067,7 +1041,6 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
|
||||
struct buffer_head *group_bh = NULL;
|
||||
struct ocfs2_group_desc *gd;
|
||||
struct inode *alloc_inode = ac->ac_inode;
|
||||
struct ocfs2_journal_handle *handle = ac->ac_handle;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
|
||||
&group_bh, OCFS2_BH_CACHED, alloc_inode);
|
||||
@ -1115,6 +1088,7 @@ out:
|
||||
}
|
||||
|
||||
static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
|
||||
handle_t *handle,
|
||||
u32 bits_wanted,
|
||||
u32 min_bits,
|
||||
u16 *bit_off,
|
||||
@ -1126,7 +1100,6 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
|
||||
u16 chain, tmp_bits;
|
||||
u32 tmp_used;
|
||||
u64 next_group;
|
||||
struct ocfs2_journal_handle *handle = ac->ac_handle;
|
||||
struct inode *alloc_inode = ac->ac_inode;
|
||||
struct buffer_head *group_bh = NULL;
|
||||
struct buffer_head *prev_group_bh = NULL;
|
||||
@ -1272,6 +1245,7 @@ bail:
|
||||
/* will give out up to bits_wanted contiguous bits. */
|
||||
static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
handle_t *handle,
|
||||
u32 bits_wanted,
|
||||
u32 min_bits,
|
||||
u16 *bit_off,
|
||||
@ -1313,8 +1287,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
* by jumping straight to the most recently used
|
||||
* allocation group. This helps us mantain some
|
||||
* contiguousness across allocations. */
|
||||
status = ocfs2_search_one_group(ac, bits_wanted, min_bits,
|
||||
bit_off, num_bits,
|
||||
status = ocfs2_search_one_group(ac, handle, bits_wanted,
|
||||
min_bits, bit_off, num_bits,
|
||||
hint_blkno, &bits_left);
|
||||
if (!status) {
|
||||
/* Be careful to update *bg_blkno here as the
|
||||
@ -1336,7 +1310,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
ac->ac_chain = victim;
|
||||
ac->ac_allow_chain_relink = 1;
|
||||
|
||||
status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
|
||||
status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off,
|
||||
num_bits, bg_blkno, &bits_left);
|
||||
if (!status)
|
||||
goto set_hint;
|
||||
@ -1360,7 +1334,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
|
||||
continue;
|
||||
|
||||
ac->ac_chain = i;
|
||||
status = ocfs2_search_chain(ac, bits_wanted, min_bits,
|
||||
status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
|
||||
bit_off, num_bits, bg_blkno,
|
||||
&bits_left);
|
||||
if (!status)
|
||||
@ -1388,7 +1362,7 @@ bail:
|
||||
}
|
||||
|
||||
int ocfs2_claim_metadata(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 bits_wanted,
|
||||
u16 *suballoc_bit_start,
|
||||
@ -1401,10 +1375,10 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
|
||||
BUG_ON(!ac);
|
||||
BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
|
||||
BUG_ON(ac->ac_which != OCFS2_AC_USE_META);
|
||||
BUG_ON(ac->ac_handle != handle);
|
||||
|
||||
status = ocfs2_claim_suballoc_bits(osb,
|
||||
ac,
|
||||
handle,
|
||||
bits_wanted,
|
||||
1,
|
||||
suballoc_bit_start,
|
||||
@ -1425,7 +1399,7 @@ bail:
|
||||
}
|
||||
|
||||
int ocfs2_claim_new_inode(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u16 *suballoc_bit,
|
||||
u64 *fe_blkno)
|
||||
@ -1440,10 +1414,10 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
|
||||
BUG_ON(ac->ac_bits_given != 0);
|
||||
BUG_ON(ac->ac_bits_wanted != 1);
|
||||
BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE);
|
||||
BUG_ON(ac->ac_handle != handle);
|
||||
|
||||
status = ocfs2_claim_suballoc_bits(osb,
|
||||
ac,
|
||||
handle,
|
||||
1,
|
||||
1,
|
||||
suballoc_bit,
|
||||
@ -1528,7 +1502,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
|
||||
* of any size.
|
||||
*/
|
||||
int ocfs2_claim_clusters(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 min_clusters,
|
||||
u32 *cluster_start,
|
||||
@ -1546,7 +1520,6 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
|
||||
|
||||
BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
|
||||
&& ac->ac_which != OCFS2_AC_USE_MAIN);
|
||||
BUG_ON(ac->ac_handle != handle);
|
||||
|
||||
if (ac->ac_which == OCFS2_AC_USE_LOCAL) {
|
||||
status = ocfs2_claim_local_alloc_bits(osb,
|
||||
@ -1572,6 +1545,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
|
||||
|
||||
status = ocfs2_claim_suballoc_bits(osb,
|
||||
ac,
|
||||
handle,
|
||||
bits_wanted,
|
||||
min_clusters,
|
||||
&bg_bit_off,
|
||||
@ -1598,7 +1572,7 @@ bail:
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
|
||||
static inline int ocfs2_block_group_clear_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct ocfs2_group_desc *bg,
|
||||
struct buffer_head *group_bh,
|
||||
@ -1653,7 +1627,7 @@ bail:
|
||||
/*
|
||||
* expects the suballoc inode to already be locked.
|
||||
*/
|
||||
static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
|
||||
static int ocfs2_free_suballoc_bits(handle_t *handle,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *alloc_bh,
|
||||
unsigned int start_bit,
|
||||
@ -1737,7 +1711,7 @@ static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
|
||||
return group;
|
||||
}
|
||||
|
||||
int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_dinode(handle_t *handle,
|
||||
struct inode *inode_alloc_inode,
|
||||
struct buffer_head *inode_alloc_bh,
|
||||
struct ocfs2_dinode *di)
|
||||
@ -1750,7 +1724,7 @@ int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
|
||||
inode_alloc_bh, bit, bg_blkno, 1);
|
||||
}
|
||||
|
||||
int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_extent_block(handle_t *handle,
|
||||
struct inode *eb_alloc_inode,
|
||||
struct buffer_head *eb_alloc_bh,
|
||||
struct ocfs2_extent_block *eb)
|
||||
@ -1763,7 +1737,7 @@ int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
|
||||
bit, bg_blkno, 1);
|
||||
}
|
||||
|
||||
int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_clusters(handle_t *handle,
|
||||
struct inode *bitmap_inode,
|
||||
struct buffer_head *bitmap_bh,
|
||||
u64 start_blk,
|
||||
|
@ -43,7 +43,6 @@ struct ocfs2_alloc_context {
|
||||
#define OCFS2_AC_USE_INODE 3
|
||||
#define OCFS2_AC_USE_META 4
|
||||
u32 ac_which;
|
||||
struct ocfs2_journal_handle *ac_handle;
|
||||
|
||||
/* these are used by the chain search */
|
||||
u16 ac_chain;
|
||||
@ -60,45 +59,42 @@ static inline int ocfs2_alloc_context_bits_left(struct ocfs2_alloc_context *ac)
|
||||
}
|
||||
|
||||
int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_dinode *fe,
|
||||
struct ocfs2_alloc_context **ac);
|
||||
int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
struct ocfs2_alloc_context **ac);
|
||||
int ocfs2_reserve_clusters(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
u32 bits_wanted,
|
||||
struct ocfs2_alloc_context **ac);
|
||||
|
||||
int ocfs2_claim_metadata(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 bits_wanted,
|
||||
u16 *suballoc_bit_start,
|
||||
u32 *num_bits,
|
||||
u64 *blkno_start);
|
||||
int ocfs2_claim_new_inode(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u16 *suballoc_bit,
|
||||
u64 *fe_blkno);
|
||||
int ocfs2_claim_clusters(struct ocfs2_super *osb,
|
||||
struct ocfs2_journal_handle *handle,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *ac,
|
||||
u32 min_clusters,
|
||||
u32 *cluster_start,
|
||||
u32 *num_clusters);
|
||||
|
||||
int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_dinode(handle_t *handle,
|
||||
struct inode *inode_alloc_inode,
|
||||
struct buffer_head *inode_alloc_bh,
|
||||
struct ocfs2_dinode *di);
|
||||
int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_extent_block(handle_t *handle,
|
||||
struct inode *eb_alloc_inode,
|
||||
struct buffer_head *eb_alloc_bh,
|
||||
struct ocfs2_extent_block *eb);
|
||||
int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
|
||||
int ocfs2_free_clusters(handle_t *handle,
|
||||
struct inode *bitmap_inode,
|
||||
struct buffer_head *bitmap_bh,
|
||||
u64 start_blk,
|
||||
|
@ -70,8 +70,6 @@
|
||||
|
||||
static kmem_cache_t *ocfs2_inode_cachep = NULL;
|
||||
|
||||
kmem_cache_t *ocfs2_lock_cache = NULL;
|
||||
|
||||
/* OCFS2 needs to schedule several differnt types of work which
|
||||
* require cluster locking, disk I/O, recovery waits, etc. Since these
|
||||
* types of work tend to be heavy we avoid using the kernel events
|
||||
@ -141,6 +139,7 @@ enum {
|
||||
Opt_hb_local,
|
||||
Opt_data_ordered,
|
||||
Opt_data_writeback,
|
||||
Opt_atime_quantum,
|
||||
Opt_err,
|
||||
};
|
||||
|
||||
@ -154,6 +153,7 @@ static match_table_t tokens = {
|
||||
{Opt_hb_local, OCFS2_HB_LOCAL},
|
||||
{Opt_data_ordered, "data=ordered"},
|
||||
{Opt_data_writeback, "data=writeback"},
|
||||
{Opt_atime_quantum, "atime_quantum=%u"},
|
||||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
@ -707,6 +707,7 @@ static int ocfs2_parse_options(struct super_block *sb,
|
||||
while ((p = strsep(&options, ",")) != NULL) {
|
||||
int token, option;
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
struct ocfs2_super * osb = OCFS2_SB(sb);
|
||||
|
||||
if (!*p)
|
||||
continue;
|
||||
@ -747,6 +748,16 @@ static int ocfs2_parse_options(struct super_block *sb,
|
||||
case Opt_data_writeback:
|
||||
*mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK;
|
||||
break;
|
||||
case Opt_atime_quantum:
|
||||
if (match_int(&args[0], &option)) {
|
||||
status = 0;
|
||||
goto bail;
|
||||
}
|
||||
if (option >= 0)
|
||||
osb->s_atime_quantum = option;
|
||||
else
|
||||
osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
|
||||
break;
|
||||
default:
|
||||
mlog(ML_ERROR,
|
||||
"Unrecognized mount option \"%s\" "
|
||||
@ -867,7 +878,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_meta_lock(inode, NULL, &bh, 0);
|
||||
status = ocfs2_meta_lock(inode, &bh, 0);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@ -914,9 +925,7 @@ static void ocfs2_inode_init_once(void *data,
|
||||
oi->ip_open_count = 0;
|
||||
spin_lock_init(&oi->ip_lock);
|
||||
ocfs2_extent_map_init(&oi->vfs_inode);
|
||||
INIT_LIST_HEAD(&oi->ip_handle_list);
|
||||
INIT_LIST_HEAD(&oi->ip_io_markers);
|
||||
oi->ip_handle = NULL;
|
||||
oi->ip_created_trans = 0;
|
||||
oi->ip_last_trans = 0;
|
||||
oi->ip_dir_start_lookup = 0;
|
||||
@ -948,14 +957,6 @@ static int ocfs2_initialize_mem_caches(void)
|
||||
if (!ocfs2_inode_cachep)
|
||||
return -ENOMEM;
|
||||
|
||||
ocfs2_lock_cache = kmem_cache_create("ocfs2_lock",
|
||||
sizeof(struct ocfs2_journal_lock),
|
||||
0,
|
||||
SLAB_HWCACHE_ALIGN,
|
||||
NULL, NULL);
|
||||
if (!ocfs2_lock_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -963,11 +964,8 @@ static void ocfs2_free_mem_caches(void)
|
||||
{
|
||||
if (ocfs2_inode_cachep)
|
||||
kmem_cache_destroy(ocfs2_inode_cachep);
|
||||
if (ocfs2_lock_cache)
|
||||
kmem_cache_destroy(ocfs2_lock_cache);
|
||||
|
||||
ocfs2_inode_cachep = NULL;
|
||||
ocfs2_lock_cache = NULL;
|
||||
}
|
||||
|
||||
static int ocfs2_get_sector(struct super_block *sb,
|
||||
@ -1280,6 +1278,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
|
||||
init_waitqueue_head(&osb->checkpoint_event);
|
||||
atomic_set(&osb->needs_checkpoint, 0);
|
||||
|
||||
osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
|
||||
|
||||
osb->node_num = O2NM_INVALID_NODE_NUM;
|
||||
osb->slot_num = OCFS2_INVALID_SLOT;
|
||||
|
||||
|
@ -126,6 +126,10 @@ static int ocfs2_readlink(struct dentry *dentry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Without vfsmount we can't update atime now,
|
||||
* but we will update atime here ultimately.
|
||||
*/
|
||||
ret = vfs_readlink(dentry, buffer, buflen, link);
|
||||
|
||||
brelse(bh);
|
||||
|
@ -1893,6 +1893,7 @@ int should_remove_suid(struct dentry *dentry)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(should_remove_suid);
|
||||
|
||||
int __remove_suid(struct dentry *dentry, int kill)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user