@@ -2712,7 +2712,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
*/
if (!was_dirty) {
/* Schedule writeback on first wb_ctx */
- struct wb_ctx *p_wb_ctx = ctx_wb_struct(wb, 0);
+ struct wb_ctx *p_wb_ctx;
struct list_head *dirty_list;
bool wakeup_bdi = false;
@@ -2720,17 +2720,27 @@ void __mark_inode_dirty(struct inode *inode, int flags)
if (dirtytime)
inode->dirtied_time_when = jiffies;
-
- if (inode->i_state & I_DIRTY)
- dirty_list = ctx_b_dirty_list(wb, 0);
- else
- dirty_list = ctx_b_dirty_time_list(wb,
- 0);
-
- wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
- dirty_list,
- p_wb_ctx);
-
+ if (!sb->s_op->get_wb_ctx) {
+ p_wb_ctx = ctx_wb_struct(wb, 0);
+
+ if (inode->i_state & I_DIRTY)
+ dirty_list = ctx_b_dirty_list(wb, 0);
+ else
+ dirty_list = ctx_b_dirty_time_list(wb,
+ 0);
+ wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
+ dirty_list,
+ p_wb_ctx);
+ } else {
+ p_wb_ctx = sb->s_op->get_wb_ctx(inode);
+ if (inode->i_state & I_DIRTY)
+ dirty_list = &p_wb_ctx->pctx_b_dirty;
+ else
+ dirty_list = &p_wb_ctx->pctx_b_dirty_time;
+ wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
+ dirty_list,
+ p_wb_ctx);
+ }
spin_unlock(&wb->list_lock);
spin_unlock(&inode->i_lock);
trace_writeback_dirty_inode_enqueue(inode);
@@ -214,6 +214,11 @@ xfs_update_last_ag_size(
return 0;
}
+static struct backing_dev_info *xfs_mp_to_bdi(struct xfs_mount *mp)
+{
+ return mp->m_super->s_bdi;
+}
+
static int
xfs_perag_alloc(
struct xfs_mount *mp,
@@ -221,12 +226,22 @@ xfs_perag_alloc(
xfs_agnumber_t agcount,
xfs_rfsblock_t dblocks)
{
+ struct backing_dev_info *bdi = xfs_mp_to_bdi(mp);
+ struct bdi_writeback *wb = &bdi->wb;
+ struct wb_ctx *p_wb_ctx;
struct xfs_perag *pag;
int error;
pag = kzalloc(sizeof(*pag), GFP_KERNEL);
if (!pag)
return -ENOMEM;
+ spin_lock(&wb->list_lock);
+ if (wb->wb_idx >= NR_WB_CTX)
+ wb->wb_idx = 0;
+ p_wb_ctx = &wb->wb_ctx_list[wb->wb_idx];
+ wb->wb_idx++;
+ spin_unlock(&wb->list_lock);
+ pag->pag_wb_ctx = p_wb_ctx;
#ifdef __KERNEL__
/* Place kernel structure only init below this point. */
@@ -261,6 +276,7 @@ xfs_perag_alloc(
return error;
}
+
int
xfs_initialize_perag(
struct xfs_mount *mp,
@@ -89,6 +89,7 @@ struct xfs_perag {
/* background prealloc block trimming */
struct delayed_work pag_blockgc_work;
+ struct wb_ctx *pag_wb_ctx;
#endif /* __KERNEL__ */
};
@@ -1210,6 +1210,25 @@ xfs_fs_shutdown(
xfs_force_shutdown(XFS_M(sb), SHUTDOWN_DEVICE_REMOVED);
}
+static struct wb_ctx *
+ xfs_get_wb_ctx(
+ struct inode *inode)
+{
+ struct xfs_inode *xfs_inode = XFS_I(inode);
+ struct xfs_perag *pag = xfs_perag_get(xfs_inode->i_mount,
+ XFS_INO_TO_AGNO(xfs_inode->i_mount, xfs_inode->i_ino));
+ struct wb_ctx *p_wb_ctx;
+
+ if (!pag) {
+ /* There had better still be a perag structure! */
+ ASSERT(0);
+ return NULL;
+ }
+ p_wb_ctx = pag->pag_wb_ctx;
+ xfs_perag_put(pag);
+ return p_wb_ctx;
+}
+
static const struct super_operations xfs_super_operations = {
.alloc_inode = xfs_fs_alloc_inode,
.destroy_inode = xfs_fs_destroy_inode,
@@ -1224,6 +1243,7 @@ static const struct super_operations xfs_super_operations = {
.nr_cached_objects = xfs_fs_nr_cached_objects,
.free_cached_objects = xfs_fs_free_cached_objects,
.shutdown = xfs_fs_shutdown,
+ .get_wb_ctx = xfs_get_wb_ctx,
};
static int
@@ -2307,6 +2307,7 @@ struct super_operations {
long (*free_cached_objects)(struct super_block *,
struct shrink_control *);
void (*shutdown)(struct super_block *sb);
+ struct wb_ctx *(*get_wb_ctx)(struct inode *);
};
/*