void ocfs2_init_steal_slots(struct ocfs2_super *osb) { ocfs2_init_inode_steal_slot(osb); ocfs2_init_meta_steal_slot(osb); }
/* * Step 2: By now, we've completed the journal recovery, we've stamped * a clean local alloc on disk and dropped the node out of the * recovery map. Dlm locks will no longer stall, so lets clear out the * main bitmap. */ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, struct ocfs2_dinode *alloc) { int status; handle_t *handle; struct buffer_head *main_bm_bh = NULL; struct inode *main_bm_inode; mlog_entry_void(); 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 out; } mutex_lock(&main_bm_inode->i_mutex); status = ocfs2_inode_lock(main_bm_inode, &main_bm_bh, 1); if (status < 0) { mlog_errno(status); goto out_mutex; } handle = ocfs2_start_trans(osb, OCFS2_WINDOW_MOVE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); goto out_unlock; } /* we want the bitmap change to be recorded on disk asap */ 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); ocfs2_commit_trans(osb, handle); out_unlock: ocfs2_inode_unlock(main_bm_inode, 1); out_mutex: mutex_unlock(&main_bm_inode->i_mutex); brelse(main_bm_bh); iput(main_bm_inode); out: if (!status) ocfs2_init_inode_steal_slot(osb); mlog_exit(status); return status; }
int ocfs2_reserve_new_inode(struct ocfs2_super *osb, struct ocfs2_alloc_context **ac) { int status; int slot = ocfs2_get_inode_steal_slot(osb); u64 alloc_group; *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = 1; (*ac)->ac_which = OCFS2_AC_USE_INODE; (*ac)->ac_group_search = ocfs2_block_group_search; /* * stat(2) can't handle i_ino > 32bits, so we tell the * lower levels not to allocate us a block group past that * limit. The 'inode64' mount option avoids this behavior. */ if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64)) (*ac)->ac_max_block = (u32)~0U; /* * slot is set when we successfully steal inode from other nodes. * It is reset in 3 places: * 1. when we flush the truncate log * 2. when we complete local alloc recovery. * 3. when we successfully allocate from our own slot. * After it is set, we will go on stealing inodes until we find the * need to check our slots to see whether there is some space for us. */ if (slot != OCFS2_INVALID_SLOT && atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_TO_STEAL) goto inode_steal; atomic_set(&osb->s_num_inodes_stolen, 0); alloc_group = osb->osb_inode_alloc_group; status = ocfs2_reserve_suballoc_bits(osb, *ac, INODE_ALLOC_SYSTEM_INODE, (u32)osb->slot_num, &alloc_group, ALLOC_NEW_GROUP | ALLOC_GROUPS_FROM_GLOBAL); if (status >= 0) { status = 0; spin_lock(&osb->osb_lock); osb->osb_inode_alloc_group = alloc_group; spin_unlock(&osb->osb_lock); trace_ocfs2_reserve_new_inode_new_group( (unsigned long long)alloc_group); /* * Some inodes must be freed by us, so try to allocate * from our own next time. */ if (slot != OCFS2_INVALID_SLOT) ocfs2_init_inode_steal_slot(osb); goto bail; } else if (status < 0 && status != -ENOSPC) { mlog_errno(status); goto bail; } ocfs2_free_ac_resource(*ac); inode_steal: status = ocfs2_steal_inode(osb, *ac); atomic_inc(&osb->s_num_inodes_stolen); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } status = 0; bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } if (status) mlog_errno(status); return status; }