162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2006-2007 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * Copyright (c) 2014 Christoph Hellwig. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include "xfs.h" 862306a36Sopenharmony_ci#include "xfs_shared.h" 962306a36Sopenharmony_ci#include "xfs_format.h" 1062306a36Sopenharmony_ci#include "xfs_log_format.h" 1162306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1262306a36Sopenharmony_ci#include "xfs_mount.h" 1362306a36Sopenharmony_ci#include "xfs_inode.h" 1462306a36Sopenharmony_ci#include "xfs_bmap.h" 1562306a36Sopenharmony_ci#include "xfs_bmap_util.h" 1662306a36Sopenharmony_ci#include "xfs_alloc.h" 1762306a36Sopenharmony_ci#include "xfs_mru_cache.h" 1862306a36Sopenharmony_ci#include "xfs_trace.h" 1962306a36Sopenharmony_ci#include "xfs_ag.h" 2062306a36Sopenharmony_ci#include "xfs_ag_resv.h" 2162306a36Sopenharmony_ci#include "xfs_trans.h" 2262306a36Sopenharmony_ci#include "xfs_filestream.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct xfs_fstrm_item { 2562306a36Sopenharmony_ci struct xfs_mru_cache_elem mru; 2662306a36Sopenharmony_ci struct xfs_perag *pag; /* AG in use for this directory */ 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cienum xfs_fstrm_alloc { 3062306a36Sopenharmony_ci XFS_PICK_USERDATA = 1, 3162306a36Sopenharmony_ci XFS_PICK_LOWSPACE = 2, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void 3562306a36Sopenharmony_cixfs_fstrm_free_func( 3662306a36Sopenharmony_ci void *data, 3762306a36Sopenharmony_ci struct xfs_mru_cache_elem *mru) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci struct xfs_fstrm_item *item = 4062306a36Sopenharmony_ci container_of(mru, struct xfs_fstrm_item, mru); 4162306a36Sopenharmony_ci struct xfs_perag *pag = item->pag; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci trace_xfs_filestream_free(pag, mru->key); 4462306a36Sopenharmony_ci atomic_dec(&pag->pagf_fstrms); 4562306a36Sopenharmony_ci xfs_perag_rele(pag); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci kmem_free(item); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* 5162306a36Sopenharmony_ci * Scan the AGs starting at start_agno looking for an AG that isn't in use and 5262306a36Sopenharmony_ci * has at least minlen blocks free. If no AG is found to match the allocation 5362306a36Sopenharmony_ci * requirements, pick the AG with the most free space in it. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cistatic int 5662306a36Sopenharmony_cixfs_filestream_pick_ag( 5762306a36Sopenharmony_ci struct xfs_alloc_arg *args, 5862306a36Sopenharmony_ci xfs_ino_t pino, 5962306a36Sopenharmony_ci xfs_agnumber_t start_agno, 6062306a36Sopenharmony_ci int flags, 6162306a36Sopenharmony_ci xfs_extlen_t *longest) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 6462306a36Sopenharmony_ci struct xfs_perag *pag; 6562306a36Sopenharmony_ci struct xfs_perag *max_pag = NULL; 6662306a36Sopenharmony_ci xfs_extlen_t minlen = *longest; 6762306a36Sopenharmony_ci xfs_extlen_t free = 0, minfree, maxfree = 0; 6862306a36Sopenharmony_ci xfs_agnumber_t agno; 6962306a36Sopenharmony_ci bool first_pass = true; 7062306a36Sopenharmony_ci int err; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* 2% of an AG's blocks must be free for it to be chosen. */ 7362306a36Sopenharmony_ci minfree = mp->m_sb.sb_agblocks / 50; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cirestart: 7662306a36Sopenharmony_ci for_each_perag_wrap(mp, start_agno, agno, pag) { 7762306a36Sopenharmony_ci trace_xfs_filestream_scan(pag, pino); 7862306a36Sopenharmony_ci *longest = 0; 7962306a36Sopenharmony_ci err = xfs_bmap_longest_free_extent(pag, NULL, longest); 8062306a36Sopenharmony_ci if (err) { 8162306a36Sopenharmony_ci if (err != -EAGAIN) 8262306a36Sopenharmony_ci break; 8362306a36Sopenharmony_ci /* Couldn't lock the AGF, skip this AG. */ 8462306a36Sopenharmony_ci err = 0; 8562306a36Sopenharmony_ci continue; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Keep track of the AG with the most free blocks. */ 8962306a36Sopenharmony_ci if (pag->pagf_freeblks > maxfree) { 9062306a36Sopenharmony_ci maxfree = pag->pagf_freeblks; 9162306a36Sopenharmony_ci if (max_pag) 9262306a36Sopenharmony_ci xfs_perag_rele(max_pag); 9362306a36Sopenharmony_ci atomic_inc(&pag->pag_active_ref); 9462306a36Sopenharmony_ci max_pag = pag; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* 9862306a36Sopenharmony_ci * The AG reference count does two things: it enforces mutual 9962306a36Sopenharmony_ci * exclusion when examining the suitability of an AG in this 10062306a36Sopenharmony_ci * loop, and it guards against two filestreams being established 10162306a36Sopenharmony_ci * in the same AG as each other. 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci if (atomic_inc_return(&pag->pagf_fstrms) <= 1) { 10462306a36Sopenharmony_ci if (((minlen && *longest >= minlen) || 10562306a36Sopenharmony_ci (!minlen && pag->pagf_freeblks >= minfree)) && 10662306a36Sopenharmony_ci (!xfs_perag_prefers_metadata(pag) || 10762306a36Sopenharmony_ci !(flags & XFS_PICK_USERDATA) || 10862306a36Sopenharmony_ci (flags & XFS_PICK_LOWSPACE))) { 10962306a36Sopenharmony_ci /* Break out, retaining the reference on the AG. */ 11062306a36Sopenharmony_ci free = pag->pagf_freeblks; 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* Drop the reference on this AG, it's not usable. */ 11662306a36Sopenharmony_ci atomic_dec(&pag->pagf_fstrms); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (err) { 12062306a36Sopenharmony_ci xfs_perag_rele(pag); 12162306a36Sopenharmony_ci if (max_pag) 12262306a36Sopenharmony_ci xfs_perag_rele(max_pag); 12362306a36Sopenharmony_ci return err; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (!pag) { 12762306a36Sopenharmony_ci /* 12862306a36Sopenharmony_ci * Allow a second pass to give xfs_bmap_longest_free_extent() 12962306a36Sopenharmony_ci * another attempt at locking AGFs that it might have skipped 13062306a36Sopenharmony_ci * over before we fail. 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci if (first_pass) { 13362306a36Sopenharmony_ci first_pass = false; 13462306a36Sopenharmony_ci goto restart; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * We must be low on data space, so run a final lowspace 13962306a36Sopenharmony_ci * optimised selection pass if we haven't already. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ci if (!(flags & XFS_PICK_LOWSPACE)) { 14262306a36Sopenharmony_ci flags |= XFS_PICK_LOWSPACE; 14362306a36Sopenharmony_ci goto restart; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * No unassociated AGs are available, so select the AG with the 14862306a36Sopenharmony_ci * most free space, regardless of whether it's already in use by 14962306a36Sopenharmony_ci * another filestream. It none suit, just use whatever AG we can 15062306a36Sopenharmony_ci * grab. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci if (!max_pag) { 15362306a36Sopenharmony_ci for_each_perag_wrap(args->mp, 0, start_agno, args->pag) 15462306a36Sopenharmony_ci break; 15562306a36Sopenharmony_ci atomic_inc(&args->pag->pagf_fstrms); 15662306a36Sopenharmony_ci *longest = 0; 15762306a36Sopenharmony_ci } else { 15862306a36Sopenharmony_ci pag = max_pag; 15962306a36Sopenharmony_ci free = maxfree; 16062306a36Sopenharmony_ci atomic_inc(&pag->pagf_fstrms); 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci } else if (max_pag) { 16362306a36Sopenharmony_ci xfs_perag_rele(max_pag); 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci trace_xfs_filestream_pick(pag, pino, free); 16762306a36Sopenharmony_ci args->pag = pag; 16862306a36Sopenharmony_ci return 0; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic struct xfs_inode * 17362306a36Sopenharmony_cixfs_filestream_get_parent( 17462306a36Sopenharmony_ci struct xfs_inode *ip) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct inode *inode = VFS_I(ip), *dir = NULL; 17762306a36Sopenharmony_ci struct dentry *dentry, *parent; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci dentry = d_find_alias(inode); 18062306a36Sopenharmony_ci if (!dentry) 18162306a36Sopenharmony_ci goto out; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci parent = dget_parent(dentry); 18462306a36Sopenharmony_ci if (!parent) 18562306a36Sopenharmony_ci goto out_dput; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci dir = igrab(d_inode(parent)); 18862306a36Sopenharmony_ci dput(parent); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciout_dput: 19162306a36Sopenharmony_ci dput(dentry); 19262306a36Sopenharmony_ciout: 19362306a36Sopenharmony_ci return dir ? XFS_I(dir) : NULL; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/* 19762306a36Sopenharmony_ci * Lookup the mru cache for an existing association. If one exists and we can 19862306a36Sopenharmony_ci * use it, return with an active perag reference indicating that the allocation 19962306a36Sopenharmony_ci * will proceed with that association. 20062306a36Sopenharmony_ci * 20162306a36Sopenharmony_ci * If we have no association, or we cannot use the current one and have to 20262306a36Sopenharmony_ci * destroy it, return with longest = 0 to tell the caller to create a new 20362306a36Sopenharmony_ci * association. 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_cistatic int 20662306a36Sopenharmony_cixfs_filestream_lookup_association( 20762306a36Sopenharmony_ci struct xfs_bmalloca *ap, 20862306a36Sopenharmony_ci struct xfs_alloc_arg *args, 20962306a36Sopenharmony_ci xfs_ino_t pino, 21062306a36Sopenharmony_ci xfs_extlen_t *longest) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 21362306a36Sopenharmony_ci struct xfs_perag *pag; 21462306a36Sopenharmony_ci struct xfs_mru_cache_elem *mru; 21562306a36Sopenharmony_ci int error = 0; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci *longest = 0; 21862306a36Sopenharmony_ci mru = xfs_mru_cache_lookup(mp->m_filestream, pino); 21962306a36Sopenharmony_ci if (!mru) 22062306a36Sopenharmony_ci return 0; 22162306a36Sopenharmony_ci /* 22262306a36Sopenharmony_ci * Grab the pag and take an extra active reference for the caller whilst 22362306a36Sopenharmony_ci * the mru item cannot go away. This means we'll pin the perag with 22462306a36Sopenharmony_ci * the reference we get here even if the filestreams association is torn 22562306a36Sopenharmony_ci * down immediately after we mark the lookup as done. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci pag = container_of(mru, struct xfs_fstrm_item, mru)->pag; 22862306a36Sopenharmony_ci atomic_inc(&pag->pag_active_ref); 22962306a36Sopenharmony_ci xfs_mru_cache_done(mp->m_filestream); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci trace_xfs_filestream_lookup(pag, ap->ip->i_ino); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci ap->blkno = XFS_AGB_TO_FSB(args->mp, pag->pag_agno, 0); 23462306a36Sopenharmony_ci xfs_bmap_adjacent(ap); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* 23762306a36Sopenharmony_ci * If there is very little free space before we start a filestreams 23862306a36Sopenharmony_ci * allocation, we're almost guaranteed to fail to find a large enough 23962306a36Sopenharmony_ci * free space available so just use the cached AG. 24062306a36Sopenharmony_ci */ 24162306a36Sopenharmony_ci if (ap->tp->t_flags & XFS_TRANS_LOWMODE) { 24262306a36Sopenharmony_ci *longest = 1; 24362306a36Sopenharmony_ci goto out_done; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci error = xfs_bmap_longest_free_extent(pag, args->tp, longest); 24762306a36Sopenharmony_ci if (error == -EAGAIN) 24862306a36Sopenharmony_ci error = 0; 24962306a36Sopenharmony_ci if (error || *longest < args->maxlen) { 25062306a36Sopenharmony_ci /* We aren't going to use this perag */ 25162306a36Sopenharmony_ci *longest = 0; 25262306a36Sopenharmony_ci xfs_perag_rele(pag); 25362306a36Sopenharmony_ci return error; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciout_done: 25762306a36Sopenharmony_ci args->pag = pag; 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int 26262306a36Sopenharmony_cixfs_filestream_create_association( 26362306a36Sopenharmony_ci struct xfs_bmalloca *ap, 26462306a36Sopenharmony_ci struct xfs_alloc_arg *args, 26562306a36Sopenharmony_ci xfs_ino_t pino, 26662306a36Sopenharmony_ci xfs_extlen_t *longest) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 26962306a36Sopenharmony_ci struct xfs_mru_cache_elem *mru; 27062306a36Sopenharmony_ci struct xfs_fstrm_item *item; 27162306a36Sopenharmony_ci xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, pino); 27262306a36Sopenharmony_ci int flags = 0; 27362306a36Sopenharmony_ci int error; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Changing parent AG association now, so remove the existing one. */ 27662306a36Sopenharmony_ci mru = xfs_mru_cache_remove(mp->m_filestream, pino); 27762306a36Sopenharmony_ci if (mru) { 27862306a36Sopenharmony_ci struct xfs_fstrm_item *item = 27962306a36Sopenharmony_ci container_of(mru, struct xfs_fstrm_item, mru); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci agno = (item->pag->pag_agno + 1) % mp->m_sb.sb_agcount; 28262306a36Sopenharmony_ci xfs_fstrm_free_func(mp, mru); 28362306a36Sopenharmony_ci } else if (xfs_is_inode32(mp)) { 28462306a36Sopenharmony_ci xfs_agnumber_t rotorstep = xfs_rotorstep; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci agno = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount; 28762306a36Sopenharmony_ci mp->m_agfrotor = (mp->m_agfrotor + 1) % 28862306a36Sopenharmony_ci (mp->m_sb.sb_agcount * rotorstep); 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci ap->blkno = XFS_AGB_TO_FSB(args->mp, agno, 0); 29262306a36Sopenharmony_ci xfs_bmap_adjacent(ap); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (ap->datatype & XFS_ALLOC_USERDATA) 29562306a36Sopenharmony_ci flags |= XFS_PICK_USERDATA; 29662306a36Sopenharmony_ci if (ap->tp->t_flags & XFS_TRANS_LOWMODE) 29762306a36Sopenharmony_ci flags |= XFS_PICK_LOWSPACE; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci *longest = ap->length; 30062306a36Sopenharmony_ci error = xfs_filestream_pick_ag(args, pino, agno, flags, longest); 30162306a36Sopenharmony_ci if (error) 30262306a36Sopenharmony_ci return error; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* 30562306a36Sopenharmony_ci * We are going to use this perag now, so create an assoication for it. 30662306a36Sopenharmony_ci * xfs_filestream_pick_ag() has already bumped the perag fstrms counter 30762306a36Sopenharmony_ci * for us, so all we need to do here is take another active reference to 30862306a36Sopenharmony_ci * the perag for the cached association. 30962306a36Sopenharmony_ci * 31062306a36Sopenharmony_ci * If we fail to store the association, we need to drop the fstrms 31162306a36Sopenharmony_ci * counter as well as drop the perag reference we take here for the 31262306a36Sopenharmony_ci * item. We do not need to return an error for this failure - as long as 31362306a36Sopenharmony_ci * we return a referenced AG, the allocation can still go ahead just 31462306a36Sopenharmony_ci * fine. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci item = kmem_alloc(sizeof(*item), KM_MAYFAIL); 31762306a36Sopenharmony_ci if (!item) 31862306a36Sopenharmony_ci goto out_put_fstrms; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci atomic_inc(&args->pag->pag_active_ref); 32162306a36Sopenharmony_ci item->pag = args->pag; 32262306a36Sopenharmony_ci error = xfs_mru_cache_insert(mp->m_filestream, pino, &item->mru); 32362306a36Sopenharmony_ci if (error) 32462306a36Sopenharmony_ci goto out_free_item; 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ciout_free_item: 32862306a36Sopenharmony_ci xfs_perag_rele(item->pag); 32962306a36Sopenharmony_ci kmem_free(item); 33062306a36Sopenharmony_ciout_put_fstrms: 33162306a36Sopenharmony_ci atomic_dec(&args->pag->pagf_fstrms); 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci/* 33662306a36Sopenharmony_ci * Search for an allocation group with a single extent large enough for 33762306a36Sopenharmony_ci * the request. First we look for an existing association and use that if it 33862306a36Sopenharmony_ci * is found. Otherwise, we create a new association by selecting an AG that fits 33962306a36Sopenharmony_ci * the allocation criteria. 34062306a36Sopenharmony_ci * 34162306a36Sopenharmony_ci * We return with a referenced perag in args->pag to indicate which AG we are 34262306a36Sopenharmony_ci * allocating into or an error with no references held. 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ciint 34562306a36Sopenharmony_cixfs_filestream_select_ag( 34662306a36Sopenharmony_ci struct xfs_bmalloca *ap, 34762306a36Sopenharmony_ci struct xfs_alloc_arg *args, 34862306a36Sopenharmony_ci xfs_extlen_t *longest) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 35162306a36Sopenharmony_ci struct xfs_inode *pip; 35262306a36Sopenharmony_ci xfs_ino_t ino = 0; 35362306a36Sopenharmony_ci int error = 0; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci *longest = 0; 35662306a36Sopenharmony_ci args->total = ap->total; 35762306a36Sopenharmony_ci pip = xfs_filestream_get_parent(ap->ip); 35862306a36Sopenharmony_ci if (pip) { 35962306a36Sopenharmony_ci ino = pip->i_ino; 36062306a36Sopenharmony_ci error = xfs_filestream_lookup_association(ap, args, ino, 36162306a36Sopenharmony_ci longest); 36262306a36Sopenharmony_ci xfs_irele(pip); 36362306a36Sopenharmony_ci if (error) 36462306a36Sopenharmony_ci return error; 36562306a36Sopenharmony_ci if (*longest >= args->maxlen) 36662306a36Sopenharmony_ci goto out_select; 36762306a36Sopenharmony_ci if (ap->tp->t_flags & XFS_TRANS_LOWMODE) 36862306a36Sopenharmony_ci goto out_select; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci error = xfs_filestream_create_association(ap, args, ino, longest); 37262306a36Sopenharmony_ci if (error) 37362306a36Sopenharmony_ci return error; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciout_select: 37662306a36Sopenharmony_ci ap->blkno = XFS_AGB_TO_FSB(mp, args->pag->pag_agno, 0); 37762306a36Sopenharmony_ci return 0; 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_civoid 38162306a36Sopenharmony_cixfs_filestream_deassociate( 38262306a36Sopenharmony_ci struct xfs_inode *ip) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci xfs_mru_cache_delete(ip->i_mount->m_filestream, ip->i_ino); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ciint 38862306a36Sopenharmony_cixfs_filestream_mount( 38962306a36Sopenharmony_ci xfs_mount_t *mp) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci /* 39262306a36Sopenharmony_ci * The filestream timer tunable is currently fixed within the range of 39362306a36Sopenharmony_ci * one second to four minutes, with five seconds being the default. The 39462306a36Sopenharmony_ci * group count is somewhat arbitrary, but it'd be nice to adhere to the 39562306a36Sopenharmony_ci * timer tunable to within about 10 percent. This requires at least 10 39662306a36Sopenharmony_ci * groups. 39762306a36Sopenharmony_ci */ 39862306a36Sopenharmony_ci return xfs_mru_cache_create(&mp->m_filestream, mp, 39962306a36Sopenharmony_ci xfs_fstrm_centisecs * 10, 10, xfs_fstrm_free_func); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_civoid 40362306a36Sopenharmony_cixfs_filestream_unmount( 40462306a36Sopenharmony_ci xfs_mount_t *mp) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci xfs_mru_cache_destroy(mp->m_filestream); 40762306a36Sopenharmony_ci} 408