#include "xfs_filestream.h"
#include "xfs_trace.h"
-#define TRACE_AG_SCAN(mp, ag, ag2)
-#define TRACE_AG_PICK1(mp, max_ag, maxfree)
-#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag)
-#define TRACE_FREE(mp, ip, pip, ag, cnt)
-#define TRACE_LOOKUP(mp, ip, pip, ag, cnt)
-
-static kmem_zone_t *item_zone;
-
struct xfs_fstrm_item {
struct xfs_mru_cache_elem mru;
struct xfs_inode *ip;
* the cache that reference per-ag array elements that have since been
* reallocated.
*/
-static int
+int
xfs_filestream_peek_ag(
xfs_mount_t *mp,
xfs_agnumber_t agno)
xfs_filestream_put_ag(item->ip->i_mount, item->ag);
- TRACE_FREE(mp, ip, NULL, item->ag,
- xfs_filestream_peek_ag(mp, item->ag));
+ trace_xfs_filestream_free(item->ip, item->ag);
- kmem_zone_free(item_zone, item);
+ kmem_free(item);
}
/*
struct xfs_mount *mp = ip->i_mount;
struct xfs_fstrm_item *item;
struct xfs_perag *pag;
- xfs_extlen_t longest, free, minfree, maxfree = 0;
+ xfs_extlen_t longest, free = 0, minfree, maxfree = 0;
xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
- int streams, max_streams;
int err, trylock, nscan;
ASSERT(S_ISDIR(ip->i_d.di_mode));
trylock = XFS_ALLOC_FLAG_TRYLOCK;
for (nscan = 0; 1; nscan++) {
+ trace_xfs_filestream_scan(ip, ag);
+
pag = xfs_perag_get(mp, ag);
- TRACE_AG_SCAN(mp, ag, atomic_read(&pag->pagf_fstrms));
if (!pag->pagf_init) {
err = xfs_alloc_pagf_init(mp, NULL, ag, trylock);
/* Keep track of the AG with the most free blocks. */
if (pag->pagf_freeblks > maxfree) {
maxfree = pag->pagf_freeblks;
- max_streams = atomic_read(&pag->pagf_fstrms);
max_ag = ag;
}
/* Break out, retaining the reference on the AG. */
free = pag->pagf_freeblks;
- streams = atomic_read(&pag->pagf_fstrms);
xfs_perag_put(pag);
*agp = ag;
break;
*/
if (max_ag != NULLAGNUMBER) {
xfs_filestream_get_ag(mp, max_ag);
- TRACE_AG_PICK1(mp, max_ag, maxfree);
- streams = max_streams;
free = maxfree;
*agp = max_ag;
break;
}
/* take AG 0 if none matched */
- TRACE_AG_PICK1(mp, max_ag, maxfree);
+ trace_xfs_filestream_pick(ip, *agp, free, nscan);
*agp = 0;
return 0;
}
- TRACE_AG_PICK2(mp, startag, *agp, streams, free, nscan, flags);
+ trace_xfs_filestream_pick(ip, *agp, free, nscan);
if (*agp == NULLAGNUMBER)
return 0;
- err = ENOMEM;
- item = kmem_zone_zalloc(item_zone, KM_MAYFAIL);
+ err = -ENOMEM;
+ item = kmem_alloc(sizeof(*item), KM_MAYFAIL);
if (!item)
goto out_put_ag;
err = xfs_mru_cache_insert(mp->m_filestream, ip->i_ino, &item->mru);
if (err) {
- if (err == EEXIST)
+ if (err == -EEXIST)
err = 0;
goto out_free_item;
}
return 0;
out_free_item:
- kmem_zone_free(item_zone, item);
+ kmem_free(item);
out_put_ag:
xfs_filestream_put_ag(mp, *agp);
return err;
}
/*
- * Return the AG of the filestream the file or directory belongs to, or
- * NULLAGNUMBER otherwise.
+ * Find the right allocation group for a file, either by finding an
+ * existing file stream or creating a new one.
+ *
+ * Returns NULLAGNUMBER in case of an error.
*/
xfs_agnumber_t
xfs_filestream_lookup_ag(
struct xfs_inode *ip)
{
struct xfs_mount *mp = ip->i_mount;
- struct xfs_fstrm_item *item;
struct xfs_inode *pip = NULL;
- xfs_agnumber_t ag = NULLAGNUMBER;
- int ref = 0;
+ xfs_agnumber_t startag, ag = NULLAGNUMBER;
struct xfs_mru_cache_elem *mru;
ASSERT(S_ISREG(ip->i_d.di_mode));
goto out;
mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
- if (!mru)
- goto out;
-
- item = container_of(mru, struct xfs_fstrm_item, mru);
-
- ag = item->ag;
- xfs_mru_cache_done(mp->m_filestream);
-
- ref = xfs_filestream_peek_ag(ip->i_mount, ag);
-out:
- TRACE_LOOKUP(mp, ip, pip, ag, ref);
- IRELE(pip);
- return ag;
-}
-
-/*
- * Make sure a directory has a filestream associated with it.
- *
- * This is called when creating regular files in an directory that has
- * filestreams enabled, so that a stream is ready by the time we need it
- * in the allocator for the files inside the directory.
- */
-int
-xfs_filestream_associate(
- struct xfs_inode *pip)
-{
- struct xfs_mount *mp = pip->i_mount;
- struct xfs_mru_cache_elem *mru;
- xfs_agnumber_t startag, ag;
-
- ASSERT(S_ISDIR(pip->i_d.di_mode));
-
- /*
- * If the directory already has a file stream associated we're done.
- */
- mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
if (mru) {
+ ag = container_of(mru, struct xfs_fstrm_item, mru)->ag;
xfs_mru_cache_done(mp->m_filestream);
- return 0;
+
+ trace_xfs_filestream_lookup(ip, ag);
+ goto out;
}
/*
} else
startag = XFS_INO_TO_AGNO(mp, pip->i_ino);
- return xfs_filestream_pick_ag(pip, startag, &ag, 0, 0);
+ if (xfs_filestream_pick_ag(pip, startag, &ag, 0, 0))
+ ag = NULLAGNUMBER;
+out:
+ IRELE(pip);
+ return ag;
}
/*
{
xfs_mru_cache_destroy(mp->m_filestream);
}
-
-
-/* needs to return a positive errno for the init path */
-int
-xfs_filestream_init(void)
-{
- item_zone = kmem_zone_init(sizeof(struct xfs_fstrm_item), "fstrm_item");
- if (!item_zone)
- return -ENOMEM;
- return 0;
-}
-
-void
-xfs_filestream_uninit(void)
-{
- kmem_zone_destroy(item_zone);
-}