0001
0002
0003
0004
0005
0006
0007 #include "xfs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_bmap.h"
0015 #include "xfs_alloc.h"
0016 #include "xfs_mru_cache.h"
0017 #include "xfs_trace.h"
0018 #include "xfs_ag.h"
0019 #include "xfs_ag_resv.h"
0020 #include "xfs_trans.h"
0021 #include "xfs_filestream.h"
0022
0023 struct xfs_fstrm_item {
0024 struct xfs_mru_cache_elem mru;
0025 xfs_agnumber_t ag;
0026 };
0027
0028 enum xfs_fstrm_alloc {
0029 XFS_PICK_USERDATA = 1,
0030 XFS_PICK_LOWSPACE = 2,
0031 };
0032
0033
0034
0035
0036
0037
0038 int
0039 xfs_filestream_peek_ag(
0040 xfs_mount_t *mp,
0041 xfs_agnumber_t agno)
0042 {
0043 struct xfs_perag *pag;
0044 int ret;
0045
0046 pag = xfs_perag_get(mp, agno);
0047 ret = atomic_read(&pag->pagf_fstrms);
0048 xfs_perag_put(pag);
0049 return ret;
0050 }
0051
0052 static int
0053 xfs_filestream_get_ag(
0054 xfs_mount_t *mp,
0055 xfs_agnumber_t agno)
0056 {
0057 struct xfs_perag *pag;
0058 int ret;
0059
0060 pag = xfs_perag_get(mp, agno);
0061 ret = atomic_inc_return(&pag->pagf_fstrms);
0062 xfs_perag_put(pag);
0063 return ret;
0064 }
0065
0066 static void
0067 xfs_filestream_put_ag(
0068 xfs_mount_t *mp,
0069 xfs_agnumber_t agno)
0070 {
0071 struct xfs_perag *pag;
0072
0073 pag = xfs_perag_get(mp, agno);
0074 atomic_dec(&pag->pagf_fstrms);
0075 xfs_perag_put(pag);
0076 }
0077
0078 static void
0079 xfs_fstrm_free_func(
0080 void *data,
0081 struct xfs_mru_cache_elem *mru)
0082 {
0083 struct xfs_mount *mp = data;
0084 struct xfs_fstrm_item *item =
0085 container_of(mru, struct xfs_fstrm_item, mru);
0086
0087 xfs_filestream_put_ag(mp, item->ag);
0088 trace_xfs_filestream_free(mp, mru->key, item->ag);
0089
0090 kmem_free(item);
0091 }
0092
0093
0094
0095
0096
0097 static int
0098 xfs_filestream_pick_ag(
0099 struct xfs_inode *ip,
0100 xfs_agnumber_t startag,
0101 xfs_agnumber_t *agp,
0102 int flags,
0103 xfs_extlen_t minlen)
0104 {
0105 struct xfs_mount *mp = ip->i_mount;
0106 struct xfs_fstrm_item *item;
0107 struct xfs_perag *pag;
0108 xfs_extlen_t longest, free = 0, minfree, maxfree = 0;
0109 xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
0110 int err, trylock, nscan;
0111
0112 ASSERT(S_ISDIR(VFS_I(ip)->i_mode));
0113
0114
0115 minfree = mp->m_sb.sb_agblocks / 50;
0116
0117 ag = startag;
0118 *agp = NULLAGNUMBER;
0119
0120
0121 trylock = XFS_ALLOC_FLAG_TRYLOCK;
0122
0123 for (nscan = 0; 1; nscan++) {
0124 trace_xfs_filestream_scan(mp, ip->i_ino, ag);
0125
0126 pag = xfs_perag_get(mp, ag);
0127
0128 if (!pag->pagf_init) {
0129 err = xfs_alloc_read_agf(pag, NULL, trylock, NULL);
0130 if (err) {
0131 if (err != -EAGAIN) {
0132 xfs_perag_put(pag);
0133 return err;
0134 }
0135
0136 goto next_ag;
0137 }
0138 }
0139
0140
0141 if (pag->pagf_freeblks > maxfree) {
0142 maxfree = pag->pagf_freeblks;
0143 max_ag = ag;
0144 }
0145
0146
0147
0148
0149
0150
0151
0152 if (xfs_filestream_get_ag(mp, ag) > 1) {
0153 xfs_filestream_put_ag(mp, ag);
0154 goto next_ag;
0155 }
0156
0157 longest = xfs_alloc_longest_free_extent(pag,
0158 xfs_alloc_min_freelist(mp, pag),
0159 xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE));
0160 if (((minlen && longest >= minlen) ||
0161 (!minlen && pag->pagf_freeblks >= minfree)) &&
0162 (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
0163 (flags & XFS_PICK_LOWSPACE))) {
0164
0165
0166 free = pag->pagf_freeblks;
0167 xfs_perag_put(pag);
0168 *agp = ag;
0169 break;
0170 }
0171
0172
0173 xfs_filestream_put_ag(mp, ag);
0174 next_ag:
0175 xfs_perag_put(pag);
0176
0177 if (++ag >= mp->m_sb.sb_agcount)
0178 ag = 0;
0179
0180
0181 if (ag != startag)
0182 continue;
0183
0184
0185 if (trylock != 0) {
0186 trylock = 0;
0187 continue;
0188 }
0189
0190
0191 if (!(flags & XFS_PICK_LOWSPACE)) {
0192 flags |= XFS_PICK_LOWSPACE;
0193 continue;
0194 }
0195
0196
0197
0198
0199
0200 if (max_ag != NULLAGNUMBER) {
0201 xfs_filestream_get_ag(mp, max_ag);
0202 free = maxfree;
0203 *agp = max_ag;
0204 break;
0205 }
0206
0207
0208 trace_xfs_filestream_pick(ip, *agp, free, nscan);
0209 *agp = 0;
0210 return 0;
0211 }
0212
0213 trace_xfs_filestream_pick(ip, *agp, free, nscan);
0214
0215 if (*agp == NULLAGNUMBER)
0216 return 0;
0217
0218 err = -ENOMEM;
0219 item = kmem_alloc(sizeof(*item), KM_MAYFAIL);
0220 if (!item)
0221 goto out_put_ag;
0222
0223 item->ag = *agp;
0224
0225 err = xfs_mru_cache_insert(mp->m_filestream, ip->i_ino, &item->mru);
0226 if (err) {
0227 if (err == -EEXIST)
0228 err = 0;
0229 goto out_free_item;
0230 }
0231
0232 return 0;
0233
0234 out_free_item:
0235 kmem_free(item);
0236 out_put_ag:
0237 xfs_filestream_put_ag(mp, *agp);
0238 return err;
0239 }
0240
0241 static struct xfs_inode *
0242 xfs_filestream_get_parent(
0243 struct xfs_inode *ip)
0244 {
0245 struct inode *inode = VFS_I(ip), *dir = NULL;
0246 struct dentry *dentry, *parent;
0247
0248 dentry = d_find_alias(inode);
0249 if (!dentry)
0250 goto out;
0251
0252 parent = dget_parent(dentry);
0253 if (!parent)
0254 goto out_dput;
0255
0256 dir = igrab(d_inode(parent));
0257 dput(parent);
0258
0259 out_dput:
0260 dput(dentry);
0261 out:
0262 return dir ? XFS_I(dir) : NULL;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271 xfs_agnumber_t
0272 xfs_filestream_lookup_ag(
0273 struct xfs_inode *ip)
0274 {
0275 struct xfs_mount *mp = ip->i_mount;
0276 struct xfs_inode *pip = NULL;
0277 xfs_agnumber_t startag, ag = NULLAGNUMBER;
0278 struct xfs_mru_cache_elem *mru;
0279
0280 ASSERT(S_ISREG(VFS_I(ip)->i_mode));
0281
0282 pip = xfs_filestream_get_parent(ip);
0283 if (!pip)
0284 return NULLAGNUMBER;
0285
0286 mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
0287 if (mru) {
0288 ag = container_of(mru, struct xfs_fstrm_item, mru)->ag;
0289 xfs_mru_cache_done(mp->m_filestream);
0290
0291 trace_xfs_filestream_lookup(mp, ip->i_ino, ag);
0292 goto out;
0293 }
0294
0295
0296
0297
0298
0299 if (xfs_is_inode32(mp)) {
0300 xfs_agnumber_t rotorstep = xfs_rotorstep;
0301 startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
0302 mp->m_agfrotor = (mp->m_agfrotor + 1) %
0303 (mp->m_sb.sb_agcount * rotorstep);
0304 } else
0305 startag = XFS_INO_TO_AGNO(mp, pip->i_ino);
0306
0307 if (xfs_filestream_pick_ag(pip, startag, &ag, 0, 0))
0308 ag = NULLAGNUMBER;
0309 out:
0310 xfs_irele(pip);
0311 return ag;
0312 }
0313
0314
0315
0316
0317
0318
0319
0320 int
0321 xfs_filestream_new_ag(
0322 struct xfs_bmalloca *ap,
0323 xfs_agnumber_t *agp)
0324 {
0325 struct xfs_inode *ip = ap->ip, *pip;
0326 struct xfs_mount *mp = ip->i_mount;
0327 xfs_extlen_t minlen = ap->length;
0328 xfs_agnumber_t startag = 0;
0329 int flags = 0;
0330 int err = 0;
0331 struct xfs_mru_cache_elem *mru;
0332
0333 *agp = NULLAGNUMBER;
0334
0335 pip = xfs_filestream_get_parent(ip);
0336 if (!pip)
0337 goto exit;
0338
0339 mru = xfs_mru_cache_remove(mp->m_filestream, pip->i_ino);
0340 if (mru) {
0341 struct xfs_fstrm_item *item =
0342 container_of(mru, struct xfs_fstrm_item, mru);
0343 startag = (item->ag + 1) % mp->m_sb.sb_agcount;
0344 }
0345
0346 if (ap->datatype & XFS_ALLOC_USERDATA)
0347 flags |= XFS_PICK_USERDATA;
0348 if (ap->tp->t_flags & XFS_TRANS_LOWMODE)
0349 flags |= XFS_PICK_LOWSPACE;
0350
0351 err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen);
0352
0353
0354
0355
0356 if (mru)
0357 xfs_fstrm_free_func(mp, mru);
0358
0359 xfs_irele(pip);
0360 exit:
0361 if (*agp == NULLAGNUMBER)
0362 *agp = 0;
0363 return err;
0364 }
0365
0366 void
0367 xfs_filestream_deassociate(
0368 struct xfs_inode *ip)
0369 {
0370 xfs_mru_cache_delete(ip->i_mount->m_filestream, ip->i_ino);
0371 }
0372
0373 int
0374 xfs_filestream_mount(
0375 xfs_mount_t *mp)
0376 {
0377
0378
0379
0380
0381
0382
0383
0384 return xfs_mru_cache_create(&mp->m_filestream, mp,
0385 xfs_fstrm_centisecs * 10, 10, xfs_fstrm_free_func);
0386 }
0387
0388 void
0389 xfs_filestream_unmount(
0390 xfs_mount_t *mp)
0391 {
0392 xfs_mru_cache_destroy(mp->m_filestream);
0393 }