10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 22a82b8beSDavid Chinner /* 32a82b8beSDavid Chinner * Copyright (c) 2006-2007 Silicon Graphics, Inc. 42cd2ef6aSChristoph Hellwig * Copyright (c) 2014 Christoph Hellwig. 52a82b8beSDavid Chinner * All Rights Reserved. 62a82b8beSDavid Chinner */ 72a82b8beSDavid Chinner #include "xfs.h" 85467b34bSDarrick J. Wong #include "xfs_shared.h" 9a4fbe6abSDave Chinner #include "xfs_format.h" 10239880efSDave Chinner #include "xfs_log_format.h" 11239880efSDave Chinner #include "xfs_trans_resv.h" 12239880efSDave Chinner #include "xfs_mount.h" 132a82b8beSDavid Chinner #include "xfs_inode.h" 142a82b8beSDavid Chinner #include "xfs_bmap.h" 158f7747adSDave Chinner #include "xfs_bmap_util.h" 162a82b8beSDavid Chinner #include "xfs_alloc.h" 172a82b8beSDavid Chinner #include "xfs_mru_cache.h" 180b1b213fSChristoph Hellwig #include "xfs_trace.h" 199bbafc71SDave Chinner #include "xfs_ag.h" 203fd129b6SDarrick J. Wong #include "xfs_ag_resv.h" 213e3673e3SBrian Foster #include "xfs_trans.h" 22f368b29bSDarrick J. Wong #include "xfs_filestream.h" 232a82b8beSDavid Chinner 242cd2ef6aSChristoph Hellwig struct xfs_fstrm_item { 2522328d71SChristoph Hellwig struct xfs_mru_cache_elem mru; 263054faceSDave Chinner struct xfs_perag *pag; /* AG in use for this directory */ 272cd2ef6aSChristoph Hellwig }; 282cd2ef6aSChristoph Hellwig 292cd2ef6aSChristoph Hellwig enum xfs_fstrm_alloc { 302cd2ef6aSChristoph Hellwig XFS_PICK_USERDATA = 1, 312cd2ef6aSChristoph Hellwig XFS_PICK_LOWSPACE = 2, 322cd2ef6aSChristoph Hellwig }; 332a82b8beSDavid Chinner 342cd2ef6aSChristoph Hellwig static void 352cd2ef6aSChristoph Hellwig xfs_fstrm_free_func( 367fcd3efaSChristoph Hellwig void *data, 372cd2ef6aSChristoph Hellwig struct xfs_mru_cache_elem *mru) 382cd2ef6aSChristoph Hellwig { 392cd2ef6aSChristoph Hellwig struct xfs_fstrm_item *item = 402cd2ef6aSChristoph Hellwig container_of(mru, struct xfs_fstrm_item, mru); 413054faceSDave Chinner struct xfs_perag *pag = item->pag; 422cd2ef6aSChristoph Hellwig 43571e2592SDave Chinner trace_xfs_filestream_free(pag, mru->key); 443054faceSDave Chinner atomic_dec(&pag->pagf_fstrms); 453054faceSDave Chinner xfs_perag_rele(pag); 462cd2ef6aSChristoph Hellwig 471919addaSChristoph Hellwig kmem_free(item); 482cd2ef6aSChristoph Hellwig } 492cd2ef6aSChristoph Hellwig 502a82b8beSDavid Chinner /* 51*bd4f5d09SDave Chinner * Scan the AGs starting at start_agno looking for an AG that isn't in use and 52*bd4f5d09SDave Chinner * has at least minlen blocks free. If no AG is found to match the allocation 53*bd4f5d09SDave Chinner * requirements, pick the AG with the most free space in it. 542a82b8beSDavid Chinner */ 552a82b8beSDavid Chinner static int 562cd2ef6aSChristoph Hellwig xfs_filestream_pick_ag( 57f8f1ed1aSDave Chinner struct xfs_alloc_arg *args, 58*bd4f5d09SDave Chinner xfs_ino_t pino, 59f8f1ed1aSDave Chinner xfs_agnumber_t start_agno, 602a82b8beSDavid Chinner int flags, 61ba34de8dSDave Chinner xfs_extlen_t *longest) 622a82b8beSDavid Chinner { 63*bd4f5d09SDave Chinner struct xfs_mount *mp = args->mp; 642cd2ef6aSChristoph Hellwig struct xfs_perag *pag; 653054faceSDave Chinner struct xfs_perag *max_pag = NULL; 66ba34de8dSDave Chinner xfs_extlen_t minlen = *longest; 67ba34de8dSDave Chinner xfs_extlen_t free = 0, minfree, maxfree = 0; 68eb70aa2dSDave Chinner xfs_agnumber_t agno; 69*bd4f5d09SDave Chinner bool first_pass = true; 70*bd4f5d09SDave Chinner int err; 712a82b8beSDavid Chinner 722a82b8beSDavid Chinner /* 2% of an AG's blocks must be free for it to be chosen. */ 732a82b8beSDavid Chinner minfree = mp->m_sb.sb_agblocks / 50; 742a82b8beSDavid Chinner 75eb70aa2dSDave Chinner restart: 76eb70aa2dSDave Chinner for_each_perag_wrap(mp, start_agno, agno, pag) { 77*bd4f5d09SDave Chinner trace_xfs_filestream_scan(pag, pino); 78ba34de8dSDave Chinner *longest = 0; 79ba34de8dSDave Chinner err = xfs_bmap_longest_free_extent(pag, NULL, longest); 80f48e2df8SDarrick J. Wong if (err) { 813054faceSDave Chinner xfs_perag_rele(pag); 8205cf492aSDave Chinner if (err != -EAGAIN) 833054faceSDave Chinner break; 84f48e2df8SDarrick J. Wong /* Couldn't lock the AGF, skip this AG. */ 85eb70aa2dSDave Chinner err = 0; 86f8f1ed1aSDave Chinner continue; 872a82b8beSDavid Chinner } 882a82b8beSDavid Chinner 892a82b8beSDavid Chinner /* Keep track of the AG with the most free blocks. */ 902a82b8beSDavid Chinner if (pag->pagf_freeblks > maxfree) { 912a82b8beSDavid Chinner maxfree = pag->pagf_freeblks; 923054faceSDave Chinner if (max_pag) 933054faceSDave Chinner xfs_perag_rele(max_pag); 943054faceSDave Chinner atomic_inc(&pag->pag_active_ref); 953054faceSDave Chinner max_pag = pag; 962a82b8beSDavid Chinner } 972a82b8beSDavid Chinner 982a82b8beSDavid Chinner /* 992a82b8beSDavid Chinner * The AG reference count does two things: it enforces mutual 1002a82b8beSDavid Chinner * exclusion when examining the suitability of an AG in this 1012a82b8beSDavid Chinner * loop, and it guards against two filestreams being established 1022a82b8beSDavid Chinner * in the same AG as each other. 1032a82b8beSDavid Chinner */ 104eb70aa2dSDave Chinner if (atomic_inc_return(&pag->pagf_fstrms) <= 1) { 105ba34de8dSDave Chinner if (((minlen && *longest >= minlen) || 1062a82b8beSDavid Chinner (!minlen && pag->pagf_freeblks >= minfree)) && 1077ac2ff8bSDave Chinner (!xfs_perag_prefers_metadata(pag) || 1087ac2ff8bSDave Chinner !(flags & XFS_PICK_USERDATA) || 1092a82b8beSDavid Chinner (flags & XFS_PICK_LOWSPACE))) { 1102a82b8beSDavid Chinner /* Break out, retaining the reference on the AG. */ 1112a82b8beSDavid Chinner free = pag->pagf_freeblks; 1122a82b8beSDavid Chinner break; 1132a82b8beSDavid Chinner } 114eb70aa2dSDave Chinner } 1152a82b8beSDavid Chinner 1162a82b8beSDavid Chinner /* Drop the reference on this AG, it's not usable. */ 1173054faceSDave Chinner atomic_dec(&pag->pagf_fstrms); 118eb70aa2dSDave Chinner } 1192a82b8beSDavid Chinner 120eb70aa2dSDave Chinner if (err) { 121eb70aa2dSDave Chinner xfs_perag_rele(pag); 122eb70aa2dSDave Chinner if (max_pag) 123eb70aa2dSDave Chinner xfs_perag_rele(max_pag); 124eb70aa2dSDave Chinner return err; 125eb70aa2dSDave Chinner } 1262a82b8beSDavid Chinner 127eb70aa2dSDave Chinner if (!pag) { 128*bd4f5d09SDave Chinner /* 129*bd4f5d09SDave Chinner * Allow a second pass to give xfs_bmap_longest_free_extent() 130*bd4f5d09SDave Chinner * another attempt at locking AGFs that it might have skipped 131*bd4f5d09SDave Chinner * over before we fail. 132*bd4f5d09SDave Chinner */ 133*bd4f5d09SDave Chinner if (first_pass) { 134*bd4f5d09SDave Chinner first_pass = false; 135eb70aa2dSDave Chinner goto restart; 1362a82b8beSDavid Chinner } 1372a82b8beSDavid Chinner 138*bd4f5d09SDave Chinner /* 139*bd4f5d09SDave Chinner * We must be low on data space, so run a final lowspace 140*bd4f5d09SDave Chinner * optimised selection pass if we haven't already. 141*bd4f5d09SDave Chinner */ 1422a82b8beSDavid Chinner if (!(flags & XFS_PICK_LOWSPACE)) { 1432a82b8beSDavid Chinner flags |= XFS_PICK_LOWSPACE; 144eb70aa2dSDave Chinner goto restart; 1452a82b8beSDavid Chinner } 1462a82b8beSDavid Chinner 1472a82b8beSDavid Chinner /* 148eb70aa2dSDave Chinner * No unassociated AGs are available, so select the AG with the 149eb70aa2dSDave Chinner * most free space, regardless of whether it's already in use by 150f8f1ed1aSDave Chinner * another filestream. It none suit, just use whatever AG we can 151f8f1ed1aSDave Chinner * grab. 1522a82b8beSDavid Chinner */ 153eb70aa2dSDave Chinner if (!max_pag) { 154*bd4f5d09SDave Chinner for_each_perag_wrap(args->mp, 0, start_agno, args->pag) 155f8f1ed1aSDave Chinner break; 156*bd4f5d09SDave Chinner atomic_inc(&args->pag->pagf_fstrms); 157f8f1ed1aSDave Chinner *longest = 0; 158f8f1ed1aSDave Chinner } else { 159eb70aa2dSDave Chinner pag = max_pag; 160eb70aa2dSDave Chinner free = maxfree; 161eb70aa2dSDave Chinner atomic_inc(&pag->pagf_fstrms); 162f8f1ed1aSDave Chinner } 163eb70aa2dSDave Chinner } else if (max_pag) { 164eb70aa2dSDave Chinner xfs_perag_rele(max_pag); 165eb70aa2dSDave Chinner } 166eb70aa2dSDave Chinner 167*bd4f5d09SDave Chinner trace_xfs_filestream_pick(pag, pino, free); 168f8f1ed1aSDave Chinner args->pag = pag; 1692cd2ef6aSChristoph Hellwig return 0; 1702cd2ef6aSChristoph Hellwig 1712a82b8beSDavid Chinner } 1722a82b8beSDavid Chinner 1732cd2ef6aSChristoph Hellwig static struct xfs_inode * 1742cd2ef6aSChristoph Hellwig xfs_filestream_get_parent( 1752cd2ef6aSChristoph Hellwig struct xfs_inode *ip) 1762a82b8beSDavid Chinner { 1772cd2ef6aSChristoph Hellwig struct inode *inode = VFS_I(ip), *dir = NULL; 1782cd2ef6aSChristoph Hellwig struct dentry *dentry, *parent; 1792a82b8beSDavid Chinner 1802cd2ef6aSChristoph Hellwig dentry = d_find_alias(inode); 1812cd2ef6aSChristoph Hellwig if (!dentry) 1822cd2ef6aSChristoph Hellwig goto out; 1832a82b8beSDavid Chinner 1842cd2ef6aSChristoph Hellwig parent = dget_parent(dentry); 1852cd2ef6aSChristoph Hellwig if (!parent) 1862cd2ef6aSChristoph Hellwig goto out_dput; 1872a82b8beSDavid Chinner 1882b0143b5SDavid Howells dir = igrab(d_inode(parent)); 1892cd2ef6aSChristoph Hellwig dput(parent); 1902a82b8beSDavid Chinner 1912cd2ef6aSChristoph Hellwig out_dput: 1922cd2ef6aSChristoph Hellwig dput(dentry); 1932cd2ef6aSChristoph Hellwig out: 1942cd2ef6aSChristoph Hellwig return dir ? XFS_I(dir) : NULL; 1952a82b8beSDavid Chinner } 1962a82b8beSDavid Chinner 1972a82b8beSDavid Chinner /* 198f38b46bbSDave Chinner * Lookup the mru cache for an existing association. If one exists and we can 199*bd4f5d09SDave Chinner * use it, return with an active perag reference indicating that the allocation 200*bd4f5d09SDave Chinner * will proceed with that association. 201f38b46bbSDave Chinner * 202f38b46bbSDave Chinner * If we have no association, or we cannot use the current one and have to 203*bd4f5d09SDave Chinner * destroy it, return with longest = 0 to tell the caller to create a new 204*bd4f5d09SDave Chinner * association. 205f38b46bbSDave Chinner */ 206*bd4f5d09SDave Chinner static int 207*bd4f5d09SDave Chinner xfs_filestream_lookup_association( 208f38b46bbSDave Chinner struct xfs_bmalloca *ap, 209f38b46bbSDave Chinner struct xfs_alloc_arg *args, 210*bd4f5d09SDave Chinner xfs_ino_t pino, 211*bd4f5d09SDave Chinner xfs_extlen_t *longest) 212f38b46bbSDave Chinner { 213*bd4f5d09SDave Chinner struct xfs_mount *mp = args->mp; 214f38b46bbSDave Chinner struct xfs_perag *pag; 215f38b46bbSDave Chinner struct xfs_mru_cache_elem *mru; 216*bd4f5d09SDave Chinner int error = 0; 217f38b46bbSDave Chinner 218*bd4f5d09SDave Chinner *longest = 0; 219*bd4f5d09SDave Chinner mru = xfs_mru_cache_lookup(mp->m_filestream, pino); 220f38b46bbSDave Chinner if (!mru) 221*bd4f5d09SDave Chinner return 0; 222f8f1ed1aSDave Chinner /* 223f8f1ed1aSDave Chinner * Grab the pag and take an extra active reference for the caller whilst 224f8f1ed1aSDave Chinner * the mru item cannot go away. This means we'll pin the perag with 225f8f1ed1aSDave Chinner * the reference we get here even if the filestreams association is torn 226f8f1ed1aSDave Chinner * down immediately after we mark the lookup as done. 227f8f1ed1aSDave Chinner */ 2283054faceSDave Chinner pag = container_of(mru, struct xfs_fstrm_item, mru)->pag; 229f8f1ed1aSDave Chinner atomic_inc(&pag->pag_active_ref); 230f38b46bbSDave Chinner xfs_mru_cache_done(mp->m_filestream); 231f38b46bbSDave Chinner 232571e2592SDave Chinner trace_xfs_filestream_lookup(pag, ap->ip->i_ino); 233f38b46bbSDave Chinner 2343054faceSDave Chinner ap->blkno = XFS_AGB_TO_FSB(args->mp, pag->pag_agno, 0); 235f38b46bbSDave Chinner xfs_bmap_adjacent(ap); 236f38b46bbSDave Chinner 237*bd4f5d09SDave Chinner /* 238*bd4f5d09SDave Chinner * If there is very little free space before we start a filestreams 239*bd4f5d09SDave Chinner * allocation, we're almost guaranteed to fail to find a large enough 240*bd4f5d09SDave Chinner * free space available so just use the cached AG. 241*bd4f5d09SDave Chinner */ 242*bd4f5d09SDave Chinner if (ap->tp->t_flags & XFS_TRANS_LOWMODE) { 243*bd4f5d09SDave Chinner *longest = 1; 244*bd4f5d09SDave Chinner goto out_done; 245f38b46bbSDave Chinner } 246f38b46bbSDave Chinner 247*bd4f5d09SDave Chinner error = xfs_bmap_longest_free_extent(pag, args->tp, longest); 248*bd4f5d09SDave Chinner if (error == -EAGAIN) 249*bd4f5d09SDave Chinner error = 0; 250*bd4f5d09SDave Chinner if (error || *longest < args->maxlen) { 251*bd4f5d09SDave Chinner /* We aren't going to use this perag */ 252*bd4f5d09SDave Chinner *longest = 0; 253*bd4f5d09SDave Chinner xfs_perag_rele(pag); 254*bd4f5d09SDave Chinner return error; 255*bd4f5d09SDave Chinner } 256*bd4f5d09SDave Chinner 257*bd4f5d09SDave Chinner out_done: 258f8f1ed1aSDave Chinner args->pag = pag; 259f38b46bbSDave Chinner return 0; 260f8f1ed1aSDave Chinner } 261f38b46bbSDave Chinner 262*bd4f5d09SDave Chinner static int 263*bd4f5d09SDave Chinner xfs_filestream_create_association( 264*bd4f5d09SDave Chinner struct xfs_bmalloca *ap, 265*bd4f5d09SDave Chinner struct xfs_alloc_arg *args, 266*bd4f5d09SDave Chinner xfs_ino_t pino, 267*bd4f5d09SDave Chinner xfs_extlen_t *longest) 268*bd4f5d09SDave Chinner { 269*bd4f5d09SDave Chinner struct xfs_mount *mp = args->mp; 270*bd4f5d09SDave Chinner struct xfs_mru_cache_elem *mru; 271*bd4f5d09SDave Chinner struct xfs_fstrm_item *item; 272*bd4f5d09SDave Chinner xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, pino); 273*bd4f5d09SDave Chinner int flags = 0; 274*bd4f5d09SDave Chinner int error; 275*bd4f5d09SDave Chinner 276f38b46bbSDave Chinner /* Changing parent AG association now, so remove the existing one. */ 277*bd4f5d09SDave Chinner mru = xfs_mru_cache_remove(mp->m_filestream, pino); 278f38b46bbSDave Chinner if (mru) { 279f38b46bbSDave Chinner struct xfs_fstrm_item *item = 280f38b46bbSDave Chinner container_of(mru, struct xfs_fstrm_item, mru); 281f38b46bbSDave Chinner 282*bd4f5d09SDave Chinner agno = (item->pag->pag_agno + 1) % mp->m_sb.sb_agcount; 283*bd4f5d09SDave Chinner xfs_fstrm_free_func(mp, mru); 284*bd4f5d09SDave Chinner } else if (xfs_is_inode32(mp)) { 285f38b46bbSDave Chinner xfs_agnumber_t rotorstep = xfs_rotorstep; 286*bd4f5d09SDave Chinner 287*bd4f5d09SDave Chinner agno = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount; 288f38b46bbSDave Chinner mp->m_agfrotor = (mp->m_agfrotor + 1) % 289f38b46bbSDave Chinner (mp->m_sb.sb_agcount * rotorstep); 290f38b46bbSDave Chinner } 2918f7747adSDave Chinner 292f8f1ed1aSDave Chinner ap->blkno = XFS_AGB_TO_FSB(args->mp, agno, 0); 293f8f1ed1aSDave Chinner xfs_bmap_adjacent(ap); 294*bd4f5d09SDave Chinner 295ba34de8dSDave Chinner if (ap->datatype & XFS_ALLOC_USERDATA) 296ba34de8dSDave Chinner flags |= XFS_PICK_USERDATA; 297ba34de8dSDave Chinner if (ap->tp->t_flags & XFS_TRANS_LOWMODE) 298ba34de8dSDave Chinner flags |= XFS_PICK_LOWSPACE; 299ba34de8dSDave Chinner 300*bd4f5d09SDave Chinner *longest = ap->length; 301*bd4f5d09SDave Chinner error = xfs_filestream_pick_ag(args, pino, agno, flags, longest); 302f8f1ed1aSDave Chinner if (error) 303ba34de8dSDave Chinner return error; 304ba34de8dSDave Chinner 305*bd4f5d09SDave Chinner /* 306*bd4f5d09SDave Chinner * We are going to use this perag now, so create an assoication for it. 307*bd4f5d09SDave Chinner * xfs_filestream_pick_ag() has already bumped the perag fstrms counter 308*bd4f5d09SDave Chinner * for us, so all we need to do here is take another active reference to 309*bd4f5d09SDave Chinner * the perag for the cached association. 310*bd4f5d09SDave Chinner * 311*bd4f5d09SDave Chinner * If we fail to store the association, we need to drop the fstrms 312*bd4f5d09SDave Chinner * counter as well as drop the perag reference we take here for the 313*bd4f5d09SDave Chinner * item. We do not need to return an error for this failure - as long as 314*bd4f5d09SDave Chinner * we return a referenced AG, the allocation can still go ahead just 315*bd4f5d09SDave Chinner * fine. 316*bd4f5d09SDave Chinner */ 317*bd4f5d09SDave Chinner item = kmem_alloc(sizeof(*item), KM_MAYFAIL); 318*bd4f5d09SDave Chinner if (!item) 319*bd4f5d09SDave Chinner goto out_put_fstrms; 320*bd4f5d09SDave Chinner 321*bd4f5d09SDave Chinner atomic_inc(&args->pag->pag_active_ref); 322*bd4f5d09SDave Chinner item->pag = args->pag; 323*bd4f5d09SDave Chinner error = xfs_mru_cache_insert(mp->m_filestream, pino, &item->mru); 324*bd4f5d09SDave Chinner if (error) 325*bd4f5d09SDave Chinner goto out_free_item; 326*bd4f5d09SDave Chinner return 0; 327*bd4f5d09SDave Chinner 328*bd4f5d09SDave Chinner out_free_item: 329*bd4f5d09SDave Chinner xfs_perag_rele(item->pag); 330*bd4f5d09SDave Chinner kmem_free(item); 331*bd4f5d09SDave Chinner out_put_fstrms: 332*bd4f5d09SDave Chinner atomic_dec(&args->pag->pagf_fstrms); 333*bd4f5d09SDave Chinner return 0; 334*bd4f5d09SDave Chinner } 335*bd4f5d09SDave Chinner 336*bd4f5d09SDave Chinner /* 337*bd4f5d09SDave Chinner * Search for an allocation group with a single extent large enough for 338*bd4f5d09SDave Chinner * the request. First we look for an existing association and use that if it 339*bd4f5d09SDave Chinner * is found. Otherwise, we create a new association by selecting an AG that fits 340*bd4f5d09SDave Chinner * the allocation criteria. 341*bd4f5d09SDave Chinner * 342*bd4f5d09SDave Chinner * We return with a referenced perag in args->pag to indicate which AG we are 343*bd4f5d09SDave Chinner * allocating into or an error with no references held. 344*bd4f5d09SDave Chinner */ 345*bd4f5d09SDave Chinner int 346*bd4f5d09SDave Chinner xfs_filestream_select_ag( 347*bd4f5d09SDave Chinner struct xfs_bmalloca *ap, 348*bd4f5d09SDave Chinner struct xfs_alloc_arg *args, 349*bd4f5d09SDave Chinner xfs_extlen_t *longest) 350*bd4f5d09SDave Chinner { 351*bd4f5d09SDave Chinner struct xfs_mount *mp = args->mp; 352*bd4f5d09SDave Chinner struct xfs_inode *pip; 353*bd4f5d09SDave Chinner xfs_ino_t ino = 0; 354*bd4f5d09SDave Chinner int error = 0; 355*bd4f5d09SDave Chinner 356*bd4f5d09SDave Chinner *longest = 0; 357*bd4f5d09SDave Chinner args->total = ap->total; 358*bd4f5d09SDave Chinner pip = xfs_filestream_get_parent(ap->ip); 359*bd4f5d09SDave Chinner if (pip) { 360*bd4f5d09SDave Chinner ino = pip->i_ino; 361*bd4f5d09SDave Chinner error = xfs_filestream_lookup_association(ap, args, ino, 362*bd4f5d09SDave Chinner longest); 363*bd4f5d09SDave Chinner xfs_irele(pip); 364*bd4f5d09SDave Chinner if (error) 365*bd4f5d09SDave Chinner return error; 366*bd4f5d09SDave Chinner if (*longest >= args->maxlen) 367*bd4f5d09SDave Chinner goto out_select; 368*bd4f5d09SDave Chinner if (ap->tp->t_flags & XFS_TRANS_LOWMODE) 369*bd4f5d09SDave Chinner goto out_select; 370*bd4f5d09SDave Chinner } 371*bd4f5d09SDave Chinner 372*bd4f5d09SDave Chinner error = xfs_filestream_create_association(ap, args, ino, longest); 373*bd4f5d09SDave Chinner if (error) 374*bd4f5d09SDave Chinner return error; 375*bd4f5d09SDave Chinner 376*bd4f5d09SDave Chinner out_select: 377*bd4f5d09SDave Chinner ap->blkno = XFS_AGB_TO_FSB(mp, args->pag->pag_agno, 0); 378*bd4f5d09SDave Chinner return 0; 379ba34de8dSDave Chinner } 3808f7747adSDave Chinner 3812a82b8beSDavid Chinner void 3822a82b8beSDavid Chinner xfs_filestream_deassociate( 3832cd2ef6aSChristoph Hellwig struct xfs_inode *ip) 3842a82b8beSDavid Chinner { 38522328d71SChristoph Hellwig xfs_mru_cache_delete(ip->i_mount->m_filestream, ip->i_ino); 3862a82b8beSDavid Chinner } 3872cd2ef6aSChristoph Hellwig 3882cd2ef6aSChristoph Hellwig int 3892cd2ef6aSChristoph Hellwig xfs_filestream_mount( 3902cd2ef6aSChristoph Hellwig xfs_mount_t *mp) 3912cd2ef6aSChristoph Hellwig { 3922cd2ef6aSChristoph Hellwig /* 3932cd2ef6aSChristoph Hellwig * The filestream timer tunable is currently fixed within the range of 3942cd2ef6aSChristoph Hellwig * one second to four minutes, with five seconds being the default. The 3952cd2ef6aSChristoph Hellwig * group count is somewhat arbitrary, but it'd be nice to adhere to the 3962cd2ef6aSChristoph Hellwig * timer tunable to within about 10 percent. This requires at least 10 3972cd2ef6aSChristoph Hellwig * groups. 3982cd2ef6aSChristoph Hellwig */ 3997fcd3efaSChristoph Hellwig return xfs_mru_cache_create(&mp->m_filestream, mp, 4007fcd3efaSChristoph Hellwig xfs_fstrm_centisecs * 10, 10, xfs_fstrm_free_func); 4012cd2ef6aSChristoph Hellwig } 4022cd2ef6aSChristoph Hellwig 4032cd2ef6aSChristoph Hellwig void 4042cd2ef6aSChristoph Hellwig xfs_filestream_unmount( 4052cd2ef6aSChristoph Hellwig xfs_mount_t *mp) 4062cd2ef6aSChristoph Hellwig { 4072cd2ef6aSChristoph Hellwig xfs_mru_cache_destroy(mp->m_filestream); 4082cd2ef6aSChristoph Hellwig } 409