static int _xfs_filestream_update_ag( xfs_inode_t *ip, xfs_inode_t *pip, xfs_agnumber_t ag) { int err = 0; xfs_mount_t *mp; xfs_mru_cache_t *cache; fstrm_item_t *item; xfs_agnumber_t old_ag; xfs_inode_t *old_pip; /* * Either ip is a regular file and pip is a directory, or ip is a * directory and pip is NULL. */ ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip && (pip->i_d.di_mode & S_IFDIR)) || ((ip->i_d.di_mode & S_IFDIR) && !pip))); mp = ip->i_mount; cache = mp->m_filestream; item = xfs_mru_cache_lookup(cache, ip->i_ino); if (item) { ASSERT(item->ip == ip); old_ag = item->ag; item->ag = ag; old_pip = item->pip; item->pip = pip; xfs_mru_cache_done(cache); /* * If the AG has changed, drop the old ref and take a new one, * effectively transferring the reference from old to new AG. */ if (ag != old_ag) { xfs_filestream_put_ag(mp, old_ag); xfs_filestream_get_ag(mp, ag); } /* * If ip is a file and its pip has changed, drop the old ref and * take a new one. */ if (pip && pip != old_pip) { IRELE(old_pip); IHOLD(pip); } TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; } item = kmem_zone_zalloc(item_zone, KM_MAYFAIL); if (!item) return ENOMEM; item->ag = ag; item->ip = ip; item->pip = pip; err = xfs_mru_cache_insert(cache, ip->i_ino, item); if (err) { kmem_zone_free(item_zone, item); return err; } /* Take a reference on the AG. */ xfs_filestream_get_ag(mp, ag); /* * Take a reference on the inode itself regardless of whether it's a * regular file or a directory. */ IHOLD(ip); /* * In the case of a regular file, take a reference on the parent inode * as well to ensure it remains in-core. */ if (pip) IHOLD(pip); TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; }
static int _xfs_filestream_update_ag( xfs_inode_t *ip, xfs_inode_t *pip, xfs_agnumber_t ag) { int err = 0; xfs_mount_t *mp; xfs_mru_cache_t *cache; fstrm_item_t *item; xfs_agnumber_t old_ag; xfs_inode_t *old_pip; ASSERT(ip && ((S_ISREG(ip->i_d.di_mode) && pip && S_ISDIR(pip->i_d.di_mode)) || (S_ISDIR(ip->i_d.di_mode) && !pip))); mp = ip->i_mount; cache = mp->m_filestream; item = xfs_mru_cache_lookup(cache, ip->i_ino); if (item) { ASSERT(item->ip == ip); old_ag = item->ag; item->ag = ag; old_pip = item->pip; item->pip = pip; xfs_mru_cache_done(cache); if (ag != old_ag) { xfs_filestream_put_ag(mp, old_ag); xfs_filestream_get_ag(mp, ag); } if (pip && pip != old_pip) { IRELE(old_pip); IHOLD(pip); } TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; } item = kmem_zone_zalloc(item_zone, KM_MAYFAIL); if (!item) return ENOMEM; item->ag = ag; item->ip = ip; item->pip = pip; err = xfs_mru_cache_insert(cache, ip->i_ino, item); if (err) { kmem_zone_free(item_zone, item); return err; } xfs_filestream_get_ag(mp, ag); IHOLD(ip); if (pip) IHOLD(pip); TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag), ag, xfs_filestream_peek_ag(mp, ag)); return 0; }