// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*/
if (flush_all)
gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
GFS2_LOG_HEAD_FLUSH_NORMAL |
GFS2_LFC_WRITE_INODE); if (bdi->wb.dirty_exceeded)
gfs2_ail1_flush(sdp, wbc); else
filemap_fdatawrite(metamapping); if (flush_all)
ret = filemap_fdatawait(metamapping); if (ret)
mark_inode_dirty_sync(inode); else {
spin_lock(&inode->i_lock); if (!(inode->i_flags & I_DIRTY))
gfs2_ordered_del_inode(ip);
spin_unlock(&inode->i_lock);
} return ret;
}
/** * gfs2_dirty_inode - check for atime updates * @inode: The inode in question * @flags: The type of dirty * * Unfortunately it can be called under any combination of inode * glock and freeze glock, so we have to check carefully. * * At the moment this deals only with atime - it should be possible * to expand that role in future, once a review of the locking has * been carried out.
*/
staticvoid gfs2_dirty_inode(struct inode *inode, int flags)
{ struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *bh; struct gfs2_holder gh; int need_unlock = 0; int need_endtrans = 0; int ret;
/* This can only happen during incomplete inode creation. */ if (unlikely(!ip->i_gl)) return;
if (gfs2_withdrawing_or_withdrawn(sdp)) return; if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); if (ret) {
fs_err(sdp, "dirty_inode: glock %d\n", ret);
gfs2_dump_glock(NULL, ip->i_gl, true); return;
}
need_unlock = 1;
} elseif (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) return;
if (current->journal_info == NULL) {
ret = gfs2_trans_begin(sdp, RES_DINODE, 0); if (ret) {
fs_err(sdp, "dirty_inode: gfs2_trans_begin %d\n", ret); goto out;
}
need_endtrans = 1;
}
ret = gfs2_meta_inode_buffer(ip, &bh); if (ret == 0) {
gfs2_trans_add_meta(ip->i_gl, bh);
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
}
if (need_endtrans)
gfs2_trans_end(sdp);
out: if (need_unlock)
gfs2_glock_dq_uninit(&gh);
}
/** * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one * @sdp: the filesystem * * Returns: errno
*/
void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
{ int log_write_allowed = test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
if (!test_bit(SDF_KILL, &sdp->sd_flags))
gfs2_flush_delete_work(sdp);
gfs2_destroy_threads(sdp);
if (log_write_allowed) {
gfs2_quota_sync(sdp->sd_vfs, 0);
gfs2_statfs_sync(sdp->sd_vfs, 0);
/* We do two log flushes here. The first one commits dirty inodes * and rgrps to the journal, but queues up revokes to the ail list. * The second flush writes out and removes the revokes. * * The first must be done before the FLUSH_SHUTDOWN code * clears the LIVE flag, otherwise it will not be able to start * a transaction to write its revokes, and the error will cause
* a withdraw of the file system. */
gfs2_log_flush(sdp, NULL, GFS2_LFC_MAKE_FS_RO);
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
GFS2_LFC_MAKE_FS_RO);
wait_event_timeout(sdp->sd_log_waitq,
gfs2_log_is_empty(sdp),
HZ * 5);
gfs2_assert_warn(sdp, gfs2_log_is_empty(sdp));
}
gfs2_quota_cleanup(sdp);
}
/** * gfs2_put_super - Unmount the filesystem * @sb: The VFS superblock *
*/
if (!sdp->sd_args.ar_spectator) { if (gfs2_holder_initialized(&sdp->sd_journal_gh))
gfs2_glock_dq_uninit(&sdp->sd_journal_gh); if (gfs2_holder_initialized(&sdp->sd_jinode_gh))
gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
brelse(sdp->sd_sc_bh);
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
free_local_statfs_inodes(sdp);
iput(sdp->sd_qc_inode);
}
gfs2_glock_dq_uninit(&sdp->sd_live_gh);
gfs2_clear_rgrpd(sdp);
gfs2_jindex_free(sdp); /* Take apart glock structures and buffer lists */
gfs2_gl_hash_clear(sdp);
iput(sdp->sd_inode);
gfs2_delete_debugfs_file(sdp);
gfs2_sys_fs_del(sdp);
free_sbd(sdp);
}
/** * gfs2_sync_fs - sync the filesystem * @sb: the superblock * @wait: true to wait for completion * * Flushes the log to disk.
*/
/** * gfs2_freeze_super - prevent further writes to the filesystem * @sb: the VFS structure for the filesystem * @who: freeze flags * @freeze_owner: owner of the freeze *
*/
if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
GFS2_LFC_FREEZE_GO_SYNC); if (gfs2_withdrawing_or_withdrawn(sdp)) return -EIO;
} return 0;
}
/** * gfs2_thaw_super - reallow writes to the filesystem * @sb: the VFS structure for the filesystem * @who: freeze flags * @freeze_owner: owner of the freeze *
*/
mutex_lock(&sdp->sd_freeze_mutex); if (!test_bit(SDF_FREEZE_INITIATOR, &sdp->sd_flags)) goto out;
gfs2_freeze_unlock(sdp);
out:
mutex_unlock(&sdp->sd_freeze_mutex);
}
/** * statfs_slow_fill - fill in the sg for a given RG * @rgd: the RG * @sc: the sc structure * * Returns: 0 on success, -ESTALE if the LVB is invalid
*/
/** * gfs2_statfs_slow - Stat a filesystem using asynchronous locking * @sdp: the filesystem * @sc: the sc info that will be returned * * Any error (other than a signal) will cause this routine to fall back * to the synchronous version. * * FIXME: This really shouldn't busy wait like this. * * Returns: errno
*/
if (sc->sc_free < 0)
sc->sc_free = 0; if (sc->sc_free > sc->sc_total)
sc->sc_free = sc->sc_total; if (sc->sc_dinodes < 0)
sc->sc_dinodes = 0;
return 0;
}
/** * gfs2_statfs - Gather and return stats about the filesystem * @dentry: The name of the link * @buf: The buffer * * Returns: 0 on success or error code
*/
/** * gfs2_drop_inode - Drop an inode (test for remote unlink) * @inode: The inode to drop * * If we've received a callback on an iopen lock then it's because a * remote node tried to deallocate the inode but failed due to this node * still having the inode open. Here we mark the link count zero * since we know that it must have reached zero if the GLF_DEMOTE flag * is set on the iopen glock. If we didn't do a disk read since the * remote node removed the final link then we might otherwise miss * this event. This check ensures that this node will deallocate the * inode's blocks, or alternatively pass the baton on to another * node for later deallocation.
*/
if (inode->i_nlink &&
gfs2_holder_initialized(&ip->i_iopen_gh)) { struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; if (glock_needs_demote(gl))
clear_nlink(inode);
}
/* * When under memory pressure when an inode's link count has dropped to * zero, defer deleting the inode to the delete workqueue. This avoids * calling into DLM under memory pressure, which can deadlock.
*/ if (!inode->i_nlink &&
unlikely(current->flags & PF_MEMALLOC) &&
gfs2_holder_initialized(&ip->i_iopen_gh)) { struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
gfs2_glock_hold(gl); if (!gfs2_queue_verify_delete(gl, true))
gfs2_glock_put_async(gl); return 0;
}
/* * No longer cache inodes when trying to evict them all.
*/ if (test_bit(SDF_EVICTING, &sdp->sd_flags)) return 1;
return generic_drop_inode(inode);
}
/** * gfs2_show_options - Show mount options for /proc/mounts * @s: seq_file structure * @root: root of this (sub)tree * * Returns: 0 on success or error code
*/
if (is_subdir(root, sdp->sd_master_dir))
seq_puts(s, ",meta"); if (args->ar_lockproto[0])
seq_show_option(s, "lockproto", args->ar_lockproto); if (args->ar_locktable[0])
seq_show_option(s, "locktable", args->ar_locktable); if (args->ar_hostdata[0])
seq_show_option(s, "hostdata", args->ar_hostdata); if (args->ar_spectator)
seq_puts(s, ",spectator"); if (args->ar_localflocks)
seq_puts(s, ",localflocks"); if (args->ar_debug)
seq_puts(s, ",debug"); if (args->ar_posix_acl)
seq_puts(s, ",acl"); if (args->ar_quota != GFS2_QUOTA_DEFAULT) { char *state; switch (args->ar_quota) { case GFS2_QUOTA_OFF:
state = "off"; break; case GFS2_QUOTA_ACCOUNT:
state = "account"; break; case GFS2_QUOTA_ON:
state = "on"; break; case GFS2_QUOTA_QUIET:
state = "quiet"; break; default:
state = "unknown"; break;
}
seq_printf(s, ",quota=%s", state);
} if (args->ar_suiddir)
seq_puts(s, ",suiddir"); if (args->ar_data != GFS2_DATA_DEFAULT) { char *state; switch (args->ar_data) { case GFS2_DATA_WRITEBACK:
state = "writeback"; break; case GFS2_DATA_ORDERED:
state = "ordered"; break; default:
state = "unknown"; break;
}
seq_printf(s, ",data=%s", state);
} if (args->ar_discard)
seq_puts(s, ",discard"); if (logd_secs != 30)
seq_printf(s, ",commit=%d", logd_secs); if (statfs_quantum != 30)
seq_printf(s, ",statfs_quantum=%d", statfs_quantum); elseif (statfs_slow)
seq_puts(s, ",statfs_quantum=0"); if (quota_quantum != 60)
seq_printf(s, ",quota_quantum=%d", quota_quantum); if (args->ar_statfs_percent)
seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent); if (args->ar_errors != GFS2_ERRORS_DEFAULT) { constchar *state;
switch (args->ar_errors) { case GFS2_ERRORS_WITHDRAW:
state = "withdraw"; break; case GFS2_ERRORS_PANIC:
state = "panic"; break; default:
state = "unknown"; break;
}
seq_printf(s, ",errors=%s", state);
} if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
seq_puts(s, ",nobarrier"); if (test_bit(SDF_DEMOTE, &sdp->sd_flags))
seq_puts(s, ",demote_interface_used"); if (args->ar_rgrplvb)
seq_puts(s, ",rgrplvb"); if (args->ar_loccookie)
seq_puts(s, ",loccookie"); return 0;
}
/** * gfs2_glock_put_eventually * @gl: The glock to put * * When under memory pressure, trigger a deferred glock put to make sure we * won't call into DLM and deadlock. Otherwise, put the glock directly.
*/
/* * If there are no other lock holders, we will immediately get * exclusive access to the iopen glock here. * * Otherwise, the other nodes holding the lock will be notified about * our locking request (see iopen_go_callback()). If they do not have * the inode open, they are expected to evict the cached inode and * release the lock, allowing us to proceed. * * Otherwise, if they cannot evict the inode, they are expected to poke * the inode glock (note: not the iopen glock). We will notice that * and stop waiting for the iopen glock immediately. The other node(s) * are then expected to take care of deleting the inode when they no * longer use it. * * As a last resort, if another node keeps holding the iopen glock * without showing any activity on the inode glock, we will eventually * time out and fail the iopen glock upgrade.
*/
wait_event_interruptible_timeout(sdp->sd_async_glock_wait,
!test_bit(HIF_WAIT, &gh->gh_iflags) ||
glock_needs_demote(ip->i_gl),
5 * HZ); if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) {
gfs2_glock_dq(gh); if (glock_needs_demote(ip->i_gl)) return EVICT_SHOULD_SKIP_DELETE; return EVICT_SHOULD_DEFER_DELETE;
}
error = gfs2_glock_holder_ready(gh); if (error) return EVICT_SHOULD_SKIP_DELETE; return EVICT_SHOULD_DELETE;
}
/** * evict_should_delete - determine whether the inode is eligible for deletion * @inode: The inode to evict * @gh: The glock holder structure * * This function determines whether the evicted inode is eligible to be deleted * and locks the inode glock. * * Returns: the fate of the dinode
*/ staticenum evict_behavior evict_should_delete(struct inode *inode, struct gfs2_holder *gh)
{ struct gfs2_inode *ip = GFS2_I(inode); struct super_block *sb = inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; int ret;
if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
test_bit(GLF_DEFER_DELETE, &ip->i_iopen_gh.gh_gl->gl_flags)) return EVICT_SHOULD_DEFER_DELETE;
/* Deletes should never happen under memory pressure anymore. */ if (WARN_ON_ONCE(current->flags & PF_MEMALLOC)) return EVICT_SHOULD_DEFER_DELETE;
/* Must not read inode block until block type has been verified */
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, gh); if (unlikely(ret)) return EVICT_SHOULD_SKIP_DELETE;
if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino)) return EVICT_SHOULD_SKIP_DELETE;
ret = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); if (ret) return EVICT_SHOULD_SKIP_DELETE;
ret = gfs2_instantiate(gh); if (ret) return EVICT_SHOULD_SKIP_DELETE;
/* * The inode may have been recreated in the meantime.
*/ if (inode->i_nlink) return EVICT_SHOULD_SKIP_DELETE;
if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) return gfs2_upgrade_iopen_glock(inode); return EVICT_SHOULD_DELETE;
}
/** * evict_unlinked_inode - delete the pieces of an unlinked evicted inode * @inode: The inode to evict
*/ staticint evict_unlinked_inode(struct inode *inode)
{ struct gfs2_inode *ip = GFS2_I(inode); int ret;
if (S_ISDIR(inode->i_mode) &&
(ip->i_diskflags & GFS2_DIF_EXHASH)) {
ret = gfs2_dir_exhash_dealloc(ip); if (ret) goto out;
}
if (ip->i_eattr) {
ret = gfs2_ea_dealloc(ip, true); if (ret) goto out;
}
if (!gfs2_is_stuffed(ip)) {
ret = gfs2_file_dealloc(ip); if (ret) goto out;
}
/* * As soon as we clear the bitmap for the dinode, gfs2_create_inode() * can get called to recreate it, or even gfs2_inode_lookup() if the * inode was recreated on another node in the meantime. * * However, inserting the new inode into the inode hash table will not * succeed until the old inode is removed, and that only happens after * ->evict_inode() returns. The new inode is attached to its inode and * iopen glocks after inserting it into the inode hash table, so at * that point we can be sure that both glocks are unused.
*/
ret = gfs2_dinode_dealloc(ip); if (!ret && ip->i_gl)
gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
out: return ret;
}
/* * evict_linked_inode - evict an inode whose dinode has not been unlinked * @inode: The inode to evict
*/ staticint evict_linked_inode(struct inode *inode)
{ struct super_block *sb = inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_inode *ip = GFS2_I(inode); struct address_space *metamapping; int ret;
ret = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); if (ret) return ret;
/* Needs to be done before glock release & also in a transaction */
truncate_inode_pages(&inode->i_data, 0);
truncate_inode_pages(metamapping, 0);
gfs2_trans_end(sdp); return 0;
}
/** * gfs2_evict_inode - Remove an inode from cache * @inode: The inode to evict * * There are three cases to consider: * 1. i_nlink == 0, we are final opener (and must deallocate) * 2. i_nlink == 0, we are not the final opener (and cannot deallocate) * 3. i_nlink > 0 * * If the fs is read only, then we have to treat all cases as per #3 * since we are unable to do any deallocation. The inode will be * deallocated by the next read/write node to attempt an allocation * in the same resource group * * We have to (at the moment) hold the inodes main lock to cover * the gap between unlocking the shared lock on the iopen lock and * taking the exclusive lock. I'd rather do a shared -> exclusive * conversion on the iopen lock, but we can change that later. This * is safe, just less efficient.
*/
gfs2_holder_mark_uninitialized(&gh); if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr) goto out;
/* * In case of an incomplete mount, gfs2_evict_inode() may be called for * system files without having an active journal to write to. In that * case, skip the filesystem evict.
*/ if (!sdp->sd_jdesc) goto out;
/* Run through the statfs inodes list to iput and free memory */
list_for_each_entry_safe(lsi, safe, &sdp->sd_sc_inodes_list, si_list) { if (lsi->si_jid == sdp->sd_jdesc->jd_jid)
sdp->sd_sc_inode = NULL; /* belongs to this node */ if (lsi->si_sc_inode)
iput(lsi->si_sc_inode);
list_del(&lsi->si_list);
kfree(lsi);
}
}
/* Return the local (per node) statfs inode in the
* sdp->sd_sc_inodes_list corresponding to the 'index'. */
list_for_each_entry(lsi, &sdp->sd_sc_inodes_list, si_list) { if (lsi->si_jid == index) return lsi->si_sc_inode;
} return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.