Loading fs/xfs/xfs_bmap.c +117 −85 Original line number Diff line number Diff line Loading @@ -3515,6 +3515,67 @@ xfs_bmap_adjacent( #undef ISVALID } static int xfs_bmap_longest_free_extent( struct xfs_trans *tp, xfs_agnumber_t ag, xfs_extlen_t *blen, int *notinit) { struct xfs_mount *mp = tp->t_mountp; struct xfs_perag *pag; xfs_extlen_t longest; int error = 0; pag = xfs_perag_get(mp, ag); if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); if (error) goto out; if (!pag->pagf_init) { *notinit = 1; goto out; } } longest = xfs_alloc_longest_free_extent(mp, pag); if (*blen < longest) *blen = longest; out: xfs_perag_put(pag); return error; } static void xfs_bmap_select_minlen( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen, int notinit) { if (notinit || *blen < ap->minlen) { /* * Since we did a BUF_TRYLOCK above, it is possible that * there is space for this request. */ args->minlen = ap->minlen; } else if (*blen < args->maxlen) { /* * If the best seen length is less than the request length, * use the best as the minimum. */ args->minlen = *blen; } else { /* * Otherwise we've seen an extent as big as maxlen, use that * as the minimum. */ args->minlen = args->maxlen; } } STATIC int xfs_bmap_btalloc_nullfb( struct xfs_bmalloca *ap, Loading @@ -3522,111 +3583,74 @@ xfs_bmap_btalloc_nullfb( xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; struct xfs_perag *pag; xfs_agnumber_t ag, startag; int notinit = 0; int error; if (ap->userdata && xfs_inode_is_filestream(ap->ip)) args->type = XFS_ALLOCTYPE_NEAR_BNO; else args->type = XFS_ALLOCTYPE_START_BNO; args->total = ap->total; /* * Search for an allocation group with a single extent large enough * for the request. If one isn't found, then adjust the minimum * allocation size to the largest space found. */ startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (startag == NULLAGNUMBER) startag = ag = 0; pag = xfs_perag_get(mp, ag); while (*blen < args->maxlen) { if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, args->tp, ag, XFS_ALLOC_FLAG_TRYLOCK); if (error) { xfs_perag_put(pag); error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (++ag == mp->m_sb.sb_agcount) ag = 0; if (ag == startag) break; } xfs_bmap_select_minlen(ap, args, blen, notinit); return 0; } /* * See xfs_alloc_fix_freelist... */ if (pag->pagf_init) { xfs_extlen_t longest; longest = xfs_alloc_longest_free_extent(mp, pag); if (*blen < longest) *blen = longest; } else notinit = 1; STATIC int xfs_bmap_btalloc_filestreams( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; xfs_agnumber_t ag; int notinit = 0; int error; if (xfs_inode_is_filestream(ap->ip)) { if (*blen >= args->maxlen) break; args->type = XFS_ALLOCTYPE_NEAR_BNO; args->total = ap->total; if (ap->userdata) { /* * If startag is an invalid AG, we've * come here once before and * xfs_filestream_new_ag picked the * best currently available. * * Don't continue looping, since we * could loop forever. */ if (startag == NULLAGNUMBER) break; ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (ag == NULLAGNUMBER) ag = 0; error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (*blen < args->maxlen) { error = xfs_filestream_new_ag(ap, &ag); xfs_perag_put(pag); if (error) return error; /* loop again to set 'blen'*/ startag = NULLAGNUMBER; pag = xfs_perag_get(mp, ag); continue; } } if (++ag == mp->m_sb.sb_agcount) ag = 0; if (ag == startag) break; xfs_perag_put(pag); pag = xfs_perag_get(mp, ag); error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; } xfs_perag_put(pag); /* * Since the above loop did a BUF_TRYLOCK, it is * possible that there is space for this request. */ if (notinit || *blen < ap->minlen) args->minlen = ap->minlen; /* * If the best seen length is less than the request * length, use the best as the minimum. */ else if (*blen < args->maxlen) args->minlen = *blen; /* * Otherwise we've seen an extent as big as maxlen, * use that as the minimum. */ else args->minlen = args->maxlen; xfs_bmap_select_minlen(ap, args, blen, notinit); /* * set the failure fallback case to look in the selected * AG as the stream may have moved. * Set the failure fallback case to look in the selected AG as stream * may have moved. */ if (xfs_inode_is_filestream(ap->ip)) ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); return 0; } Loading Loading @@ -3706,6 +3730,14 @@ xfs_bmap_btalloc( args.firstblock = *ap->firstblock; blen = 0; if (nullfb) { /* * Search for an allocation group with a single extent large * enough for the request. If one isn't found, then adjust * the minimum allocation size to the largest space found. */ if (ap->userdata && xfs_inode_is_filestream(ap->ip)) error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); else error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; Loading fs/xfs/xfs_filestream.c +147 −537 File changed.Preview size limit exceeded, changes collapsed. Show changes fs/xfs/xfs_filestream.h +2 −32 Original line number Diff line number Diff line Loading @@ -20,50 +20,20 @@ struct xfs_mount; struct xfs_inode; struct xfs_perag; struct xfs_bmalloca; #ifdef XFS_FILESTREAMS_TRACE #define XFS_FSTRM_KTRACE_INFO 1 #define XFS_FSTRM_KTRACE_AGSCAN 2 #define XFS_FSTRM_KTRACE_AGPICK1 3 #define XFS_FSTRM_KTRACE_AGPICK2 4 #define XFS_FSTRM_KTRACE_UPDATE 5 #define XFS_FSTRM_KTRACE_FREE 6 #define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7 #define XFS_FSTRM_KTRACE_ASSOCIATE 8 #define XFS_FSTRM_KTRACE_MOVEAG 9 #define XFS_FSTRM_KTRACE_ORPHAN 10 #define XFS_FSTRM_KTRACE_SIZE 16384 extern ktrace_t *xfs_filestreams_trace_buf; #endif /* allocation selection flags */ typedef enum xfs_fstrm_alloc { XFS_PICK_USERDATA = 1, XFS_PICK_LOWSPACE = 2, } xfs_fstrm_alloc_t; /* prototypes for filestream.c */ int xfs_filestream_init(void); void xfs_filestream_uninit(void); int xfs_filestream_mount(struct xfs_mount *mp); void xfs_filestream_unmount(struct xfs_mount *mp); xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip); void xfs_filestream_deassociate(struct xfs_inode *ip); xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp); int xfs_filestream_peek_ag(struct xfs_mount *mp, xfs_agnumber_t agno); /* filestreams for the inode? */ static inline int xfs_inode_is_filestream( struct xfs_inode *ip) { return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) || xfs_iflags_test(ip, XFS_IFILESTREAM) || (ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM); } Loading fs/xfs/xfs_inode.c +1 −34 Original line number Diff line number Diff line Loading @@ -655,7 +655,6 @@ xfs_ialloc( uint flags; int error; timespec_t tv; int filestreams = 0; /* * Call the space management code to pick Loading Loading @@ -772,13 +771,6 @@ xfs_ialloc( flags |= XFS_ILOG_DEV; break; case S_IFREG: /* * we can't set up filestreams until after the VFS inode * is set up properly. */ if (pip && xfs_inode_is_filestream(pip)) filestreams = 1; /* fall through */ case S_IFDIR: if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { uint di_flags = 0; Loading Loading @@ -844,15 +836,6 @@ xfs_ialloc( /* now that we have an i_mode we can setup inode ops and unlock */ xfs_setup_inode(ip); /* now we have set up the vfs inode we can associate the filestream */ if (filestreams) { error = xfs_filestream_associate(pip, ip); if (error < 0) return -error; if (!error) xfs_iflags_set(ip, XFS_IFILESTREAM); } *ipp = ip; return 0; } Loading Loading @@ -1698,16 +1681,6 @@ xfs_release( if (!XFS_FORCED_SHUTDOWN(mp)) { int truncated; /* * If we are using filestreams, and we have an unlinked * file that we are processing the last close on, then nothing * will be able to reopen and write to this file. Purge this * inode from the filestreams cache so that it doesn't delay * teardown of the inode. */ if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip)) xfs_filestream_deassociate(ip); /* * If we previously truncated this file and removed old data * in the process, we want to initiate "early" writeout on Loading Loading @@ -2664,13 +2637,7 @@ xfs_remove( if (error) goto std_return; /* * If we are using filestreams, kill the stream association. * If the file is still open it may get a new one but that * will get killed on last close in xfs_close() so we don't * have to worry about that. */ if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) if (is_dir && xfs_inode_is_filestream(ip)) xfs_filestream_deassociate(ip); return 0; Loading fs/xfs/xfs_inode.h +1 −3 Original line number Diff line number Diff line Loading @@ -209,7 +209,6 @@ xfs_get_initial_prid(struct xfs_inode *dp) #define XFS_ISTALE (1 << 1) /* inode has been staled */ #define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */ #define XFS_INEW (1 << 3) /* inode has just been allocated */ #define XFS_IFILESTREAM (1 << 4) /* inode is in a filestream dir. */ #define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */ #define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */ #define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */ Loading @@ -225,8 +224,7 @@ xfs_get_initial_prid(struct xfs_inode *dp) */ #define XFS_IRECLAIM_RESET_FLAGS \ (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ XFS_IFILESTREAM); XFS_IDIRTY_RELEASE | XFS_ITRUNCATED) /* * Synchronize processes attempting to flush the in-core inode back to disk. Loading Loading
fs/xfs/xfs_bmap.c +117 −85 Original line number Diff line number Diff line Loading @@ -3515,6 +3515,67 @@ xfs_bmap_adjacent( #undef ISVALID } static int xfs_bmap_longest_free_extent( struct xfs_trans *tp, xfs_agnumber_t ag, xfs_extlen_t *blen, int *notinit) { struct xfs_mount *mp = tp->t_mountp; struct xfs_perag *pag; xfs_extlen_t longest; int error = 0; pag = xfs_perag_get(mp, ag); if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); if (error) goto out; if (!pag->pagf_init) { *notinit = 1; goto out; } } longest = xfs_alloc_longest_free_extent(mp, pag); if (*blen < longest) *blen = longest; out: xfs_perag_put(pag); return error; } static void xfs_bmap_select_minlen( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen, int notinit) { if (notinit || *blen < ap->minlen) { /* * Since we did a BUF_TRYLOCK above, it is possible that * there is space for this request. */ args->minlen = ap->minlen; } else if (*blen < args->maxlen) { /* * If the best seen length is less than the request length, * use the best as the minimum. */ args->minlen = *blen; } else { /* * Otherwise we've seen an extent as big as maxlen, use that * as the minimum. */ args->minlen = args->maxlen; } } STATIC int xfs_bmap_btalloc_nullfb( struct xfs_bmalloca *ap, Loading @@ -3522,111 +3583,74 @@ xfs_bmap_btalloc_nullfb( xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; struct xfs_perag *pag; xfs_agnumber_t ag, startag; int notinit = 0; int error; if (ap->userdata && xfs_inode_is_filestream(ap->ip)) args->type = XFS_ALLOCTYPE_NEAR_BNO; else args->type = XFS_ALLOCTYPE_START_BNO; args->total = ap->total; /* * Search for an allocation group with a single extent large enough * for the request. If one isn't found, then adjust the minimum * allocation size to the largest space found. */ startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (startag == NULLAGNUMBER) startag = ag = 0; pag = xfs_perag_get(mp, ag); while (*blen < args->maxlen) { if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, args->tp, ag, XFS_ALLOC_FLAG_TRYLOCK); if (error) { xfs_perag_put(pag); error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (++ag == mp->m_sb.sb_agcount) ag = 0; if (ag == startag) break; } xfs_bmap_select_minlen(ap, args, blen, notinit); return 0; } /* * See xfs_alloc_fix_freelist... */ if (pag->pagf_init) { xfs_extlen_t longest; longest = xfs_alloc_longest_free_extent(mp, pag); if (*blen < longest) *blen = longest; } else notinit = 1; STATIC int xfs_bmap_btalloc_filestreams( struct xfs_bmalloca *ap, struct xfs_alloc_arg *args, xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; xfs_agnumber_t ag; int notinit = 0; int error; if (xfs_inode_is_filestream(ap->ip)) { if (*blen >= args->maxlen) break; args->type = XFS_ALLOCTYPE_NEAR_BNO; args->total = ap->total; if (ap->userdata) { /* * If startag is an invalid AG, we've * come here once before and * xfs_filestream_new_ag picked the * best currently available. * * Don't continue looping, since we * could loop forever. */ if (startag == NULLAGNUMBER) break; ag = XFS_FSB_TO_AGNO(mp, args->fsbno); if (ag == NULLAGNUMBER) ag = 0; error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; if (*blen < args->maxlen) { error = xfs_filestream_new_ag(ap, &ag); xfs_perag_put(pag); if (error) return error; /* loop again to set 'blen'*/ startag = NULLAGNUMBER; pag = xfs_perag_get(mp, ag); continue; } } if (++ag == mp->m_sb.sb_agcount) ag = 0; if (ag == startag) break; xfs_perag_put(pag); pag = xfs_perag_get(mp, ag); error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); if (error) return error; } xfs_perag_put(pag); /* * Since the above loop did a BUF_TRYLOCK, it is * possible that there is space for this request. */ if (notinit || *blen < ap->minlen) args->minlen = ap->minlen; /* * If the best seen length is less than the request * length, use the best as the minimum. */ else if (*blen < args->maxlen) args->minlen = *blen; /* * Otherwise we've seen an extent as big as maxlen, * use that as the minimum. */ else args->minlen = args->maxlen; xfs_bmap_select_minlen(ap, args, blen, notinit); /* * set the failure fallback case to look in the selected * AG as the stream may have moved. * Set the failure fallback case to look in the selected AG as stream * may have moved. */ if (xfs_inode_is_filestream(ap->ip)) ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); return 0; } Loading Loading @@ -3706,6 +3730,14 @@ xfs_bmap_btalloc( args.firstblock = *ap->firstblock; blen = 0; if (nullfb) { /* * Search for an allocation group with a single extent large * enough for the request. If one isn't found, then adjust * the minimum allocation size to the largest space found. */ if (ap->userdata && xfs_inode_is_filestream(ap->ip)) error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); else error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; Loading
fs/xfs/xfs_filestream.c +147 −537 File changed.Preview size limit exceeded, changes collapsed. Show changes
fs/xfs/xfs_filestream.h +2 −32 Original line number Diff line number Diff line Loading @@ -20,50 +20,20 @@ struct xfs_mount; struct xfs_inode; struct xfs_perag; struct xfs_bmalloca; #ifdef XFS_FILESTREAMS_TRACE #define XFS_FSTRM_KTRACE_INFO 1 #define XFS_FSTRM_KTRACE_AGSCAN 2 #define XFS_FSTRM_KTRACE_AGPICK1 3 #define XFS_FSTRM_KTRACE_AGPICK2 4 #define XFS_FSTRM_KTRACE_UPDATE 5 #define XFS_FSTRM_KTRACE_FREE 6 #define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7 #define XFS_FSTRM_KTRACE_ASSOCIATE 8 #define XFS_FSTRM_KTRACE_MOVEAG 9 #define XFS_FSTRM_KTRACE_ORPHAN 10 #define XFS_FSTRM_KTRACE_SIZE 16384 extern ktrace_t *xfs_filestreams_trace_buf; #endif /* allocation selection flags */ typedef enum xfs_fstrm_alloc { XFS_PICK_USERDATA = 1, XFS_PICK_LOWSPACE = 2, } xfs_fstrm_alloc_t; /* prototypes for filestream.c */ int xfs_filestream_init(void); void xfs_filestream_uninit(void); int xfs_filestream_mount(struct xfs_mount *mp); void xfs_filestream_unmount(struct xfs_mount *mp); xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip); void xfs_filestream_deassociate(struct xfs_inode *ip); xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip); int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp); int xfs_filestream_peek_ag(struct xfs_mount *mp, xfs_agnumber_t agno); /* filestreams for the inode? */ static inline int xfs_inode_is_filestream( struct xfs_inode *ip) { return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) || xfs_iflags_test(ip, XFS_IFILESTREAM) || (ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM); } Loading
fs/xfs/xfs_inode.c +1 −34 Original line number Diff line number Diff line Loading @@ -655,7 +655,6 @@ xfs_ialloc( uint flags; int error; timespec_t tv; int filestreams = 0; /* * Call the space management code to pick Loading Loading @@ -772,13 +771,6 @@ xfs_ialloc( flags |= XFS_ILOG_DEV; break; case S_IFREG: /* * we can't set up filestreams until after the VFS inode * is set up properly. */ if (pip && xfs_inode_is_filestream(pip)) filestreams = 1; /* fall through */ case S_IFDIR: if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { uint di_flags = 0; Loading Loading @@ -844,15 +836,6 @@ xfs_ialloc( /* now that we have an i_mode we can setup inode ops and unlock */ xfs_setup_inode(ip); /* now we have set up the vfs inode we can associate the filestream */ if (filestreams) { error = xfs_filestream_associate(pip, ip); if (error < 0) return -error; if (!error) xfs_iflags_set(ip, XFS_IFILESTREAM); } *ipp = ip; return 0; } Loading Loading @@ -1698,16 +1681,6 @@ xfs_release( if (!XFS_FORCED_SHUTDOWN(mp)) { int truncated; /* * If we are using filestreams, and we have an unlinked * file that we are processing the last close on, then nothing * will be able to reopen and write to this file. Purge this * inode from the filestreams cache so that it doesn't delay * teardown of the inode. */ if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip)) xfs_filestream_deassociate(ip); /* * If we previously truncated this file and removed old data * in the process, we want to initiate "early" writeout on Loading Loading @@ -2664,13 +2637,7 @@ xfs_remove( if (error) goto std_return; /* * If we are using filestreams, kill the stream association. * If the file is still open it may get a new one but that * will get killed on last close in xfs_close() so we don't * have to worry about that. */ if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) if (is_dir && xfs_inode_is_filestream(ip)) xfs_filestream_deassociate(ip); return 0; Loading
fs/xfs/xfs_inode.h +1 −3 Original line number Diff line number Diff line Loading @@ -209,7 +209,6 @@ xfs_get_initial_prid(struct xfs_inode *dp) #define XFS_ISTALE (1 << 1) /* inode has been staled */ #define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */ #define XFS_INEW (1 << 3) /* inode has just been allocated */ #define XFS_IFILESTREAM (1 << 4) /* inode is in a filestream dir. */ #define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */ #define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */ #define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */ Loading @@ -225,8 +224,7 @@ xfs_get_initial_prid(struct xfs_inode *dp) */ #define XFS_IRECLAIM_RESET_FLAGS \ (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ XFS_IFILESTREAM); XFS_IDIRTY_RELEASE | XFS_ITRUNCATED) /* * Synchronize processes attempting to flush the in-core inode back to disk. Loading