aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r--fs/xfs/xfs_attr.c317
1 files changed, 1 insertions, 316 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 0d92e21ca33c..e9fd5acb4305 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -63,7 +63,6 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
63STATIC int xfs_attr_leaf_get(xfs_da_args_t *args); 63STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
64STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args); 64STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
65STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args); 65STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
66STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
67 66
68/* 67/*
69 * Internal routines when attribute list is more than one block. 68 * Internal routines when attribute list is more than one block.
@@ -71,7 +70,6 @@ STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
71STATIC int xfs_attr_node_get(xfs_da_args_t *args); 70STATIC int xfs_attr_node_get(xfs_da_args_t *args);
72STATIC int xfs_attr_node_addname(xfs_da_args_t *args); 71STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
73STATIC int xfs_attr_node_removename(xfs_da_args_t *args); 72STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
74STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
75STATIC int xfs_attr_fillstate(xfs_da_state_t *state); 73STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
76STATIC int xfs_attr_refillstate(xfs_da_state_t *state); 74STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
77 75
@@ -91,7 +89,7 @@ xfs_attr_name_to_xname(
91 return 0; 89 return 0;
92} 90}
93 91
94STATIC int 92int
95xfs_inode_hasattr( 93xfs_inode_hasattr(
96 struct xfs_inode *ip) 94 struct xfs_inode *ip)
97{ 95{
@@ -612,157 +610,6 @@ xfs_attr_remove(
612 return xfs_attr_remove_int(dp, &xname, flags); 610 return xfs_attr_remove_int(dp, &xname, flags);
613} 611}
614 612
615int
616xfs_attr_list_int(xfs_attr_list_context_t *context)
617{
618 int error;
619 xfs_inode_t *dp = context->dp;
620
621 XFS_STATS_INC(xs_attr_list);
622
623 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
624 return EIO;
625
626 xfs_ilock(dp, XFS_ILOCK_SHARED);
627
628 /*
629 * Decide on what work routines to call based on the inode size.
630 */
631 if (!xfs_inode_hasattr(dp)) {
632 error = 0;
633 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
634 error = xfs_attr_shortform_list(context);
635 } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
636 error = xfs_attr_leaf_list(context);
637 } else {
638 error = xfs_attr_node_list(context);
639 }
640
641 xfs_iunlock(dp, XFS_ILOCK_SHARED);
642
643 return error;
644}
645
646#define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \
647 (((struct attrlist_ent *) 0)->a_name - (char *) 0)
648#define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \
649 ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
650 & ~(sizeof(u_int32_t)-1))
651
652/*
653 * Format an attribute and copy it out to the user's buffer.
654 * Take care to check values and protect against them changing later,
655 * we may be reading them directly out of a user buffer.
656 */
657/*ARGSUSED*/
658STATIC int
659xfs_attr_put_listent(
660 xfs_attr_list_context_t *context,
661 int flags,
662 unsigned char *name,
663 int namelen,
664 int valuelen,
665 unsigned char *value)
666{
667 struct attrlist *alist = (struct attrlist *)context->alist;
668 attrlist_ent_t *aep;
669 int arraytop;
670
671 ASSERT(!(context->flags & ATTR_KERNOVAL));
672 ASSERT(context->count >= 0);
673 ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
674 ASSERT(context->firstu >= sizeof(*alist));
675 ASSERT(context->firstu <= context->bufsize);
676
677 /*
678 * Only list entries in the right namespace.
679 */
680 if (((context->flags & ATTR_SECURE) == 0) !=
681 ((flags & XFS_ATTR_SECURE) == 0))
682 return 0;
683 if (((context->flags & ATTR_ROOT) == 0) !=
684 ((flags & XFS_ATTR_ROOT) == 0))
685 return 0;
686
687 arraytop = sizeof(*alist) +
688 context->count * sizeof(alist->al_offset[0]);
689 context->firstu -= ATTR_ENTSIZE(namelen);
690 if (context->firstu < arraytop) {
691 trace_xfs_attr_list_full(context);
692 alist->al_more = 1;
693 context->seen_enough = 1;
694 return 1;
695 }
696
697 aep = (attrlist_ent_t *)&context->alist[context->firstu];
698 aep->a_valuelen = valuelen;
699 memcpy(aep->a_name, name, namelen);
700 aep->a_name[namelen] = 0;
701 alist->al_offset[context->count++] = context->firstu;
702 alist->al_count = context->count;
703 trace_xfs_attr_list_add(context);
704 return 0;
705}
706
707/*
708 * Generate a list of extended attribute names and optionally
709 * also value lengths. Positive return value follows the XFS
710 * convention of being an error, zero or negative return code
711 * is the length of the buffer returned (negated), indicating
712 * success.
713 */
714int
715xfs_attr_list(
716 xfs_inode_t *dp,
717 char *buffer,
718 int bufsize,
719 int flags,
720 attrlist_cursor_kern_t *cursor)
721{
722 xfs_attr_list_context_t context;
723 struct attrlist *alist;
724 int error;
725
726 /*
727 * Validate the cursor.
728 */
729 if (cursor->pad1 || cursor->pad2)
730 return(XFS_ERROR(EINVAL));
731 if ((cursor->initted == 0) &&
732 (cursor->hashval || cursor->blkno || cursor->offset))
733 return XFS_ERROR(EINVAL);
734
735 /*
736 * Check for a properly aligned buffer.
737 */
738 if (((long)buffer) & (sizeof(int)-1))
739 return XFS_ERROR(EFAULT);
740 if (flags & ATTR_KERNOVAL)
741 bufsize = 0;
742
743 /*
744 * Initialize the output buffer.
745 */
746 memset(&context, 0, sizeof(context));
747 context.dp = dp;
748 context.cursor = cursor;
749 context.resynch = 1;
750 context.flags = flags;
751 context.alist = buffer;
752 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
753 context.firstu = context.bufsize;
754 context.put_listent = xfs_attr_put_listent;
755
756 alist = (struct attrlist *)context.alist;
757 alist->al_count = 0;
758 alist->al_more = 0;
759 alist->al_offset[0] = context.bufsize;
760
761 error = xfs_attr_list_int(&context);
762 ASSERT(error >= 0);
763 return error;
764}
765
766int /* error */ 613int /* error */
767xfs_attr_inactive(xfs_inode_t *dp) 614xfs_attr_inactive(xfs_inode_t *dp)
768{ 615{
@@ -1167,28 +1014,6 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
1167 return error; 1014 return error;
1168} 1015}
1169 1016
1170/*
1171 * Copy out attribute entries for attr_list(), for leaf attribute lists.
1172 */
1173STATIC int
1174xfs_attr_leaf_list(xfs_attr_list_context_t *context)
1175{
1176 int error;
1177 struct xfs_buf *bp;
1178
1179 trace_xfs_attr_leaf_list(context);
1180
1181 context->cursor->blkno = 0;
1182 error = xfs_attr3_leaf_read(NULL, context->dp, 0, -1, &bp);
1183 if (error)
1184 return XFS_ERROR(error);
1185
1186 error = xfs_attr3_leaf_list_int(bp, context);
1187 xfs_trans_brelse(NULL, bp);
1188 return XFS_ERROR(error);
1189}
1190
1191
1192/*======================================================================== 1017/*========================================================================
1193 * External routines when attribute list size > XFS_LBSIZE(mp). 1018 * External routines when attribute list size > XFS_LBSIZE(mp).
1194 *========================================================================*/ 1019 *========================================================================*/
@@ -1781,143 +1606,3 @@ xfs_attr_node_get(xfs_da_args_t *args)
1781 xfs_da_state_free(state); 1606 xfs_da_state_free(state);
1782 return(retval); 1607 return(retval);
1783} 1608}
1784
1785STATIC int /* error */
1786xfs_attr_node_list(xfs_attr_list_context_t *context)
1787{
1788 attrlist_cursor_kern_t *cursor;
1789 xfs_attr_leafblock_t *leaf;
1790 xfs_da_intnode_t *node;
1791 struct xfs_attr3_icleaf_hdr leafhdr;
1792 struct xfs_da3_icnode_hdr nodehdr;
1793 struct xfs_da_node_entry *btree;
1794 int error, i;
1795 struct xfs_buf *bp;
1796
1797 trace_xfs_attr_node_list(context);
1798
1799 cursor = context->cursor;
1800 cursor->initted = 1;
1801
1802 /*
1803 * Do all sorts of validation on the passed-in cursor structure.
1804 * If anything is amiss, ignore the cursor and look up the hashval
1805 * starting from the btree root.
1806 */
1807 bp = NULL;
1808 if (cursor->blkno > 0) {
1809 error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1,
1810 &bp, XFS_ATTR_FORK);
1811 if ((error != 0) && (error != EFSCORRUPTED))
1812 return(error);
1813 if (bp) {
1814 struct xfs_attr_leaf_entry *entries;
1815
1816 node = bp->b_addr;
1817 switch (be16_to_cpu(node->hdr.info.magic)) {
1818 case XFS_DA_NODE_MAGIC:
1819 case XFS_DA3_NODE_MAGIC:
1820 trace_xfs_attr_list_wrong_blk(context);
1821 xfs_trans_brelse(NULL, bp);
1822 bp = NULL;
1823 break;
1824 case XFS_ATTR_LEAF_MAGIC:
1825 case XFS_ATTR3_LEAF_MAGIC:
1826 leaf = bp->b_addr;
1827 xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
1828 entries = xfs_attr3_leaf_entryp(leaf);
1829 if (cursor->hashval > be32_to_cpu(
1830 entries[leafhdr.count - 1].hashval)) {
1831 trace_xfs_attr_list_wrong_blk(context);
1832 xfs_trans_brelse(NULL, bp);
1833 bp = NULL;
1834 } else if (cursor->hashval <= be32_to_cpu(
1835 entries[0].hashval)) {
1836 trace_xfs_attr_list_wrong_blk(context);
1837 xfs_trans_brelse(NULL, bp);
1838 bp = NULL;
1839 }
1840 break;
1841 default:
1842 trace_xfs_attr_list_wrong_blk(context);
1843 xfs_trans_brelse(NULL, bp);
1844 bp = NULL;
1845 }
1846 }
1847 }
1848
1849 /*
1850 * We did not find what we expected given the cursor's contents,
1851 * so we start from the top and work down based on the hash value.
1852 * Note that start of node block is same as start of leaf block.
1853 */
1854 if (bp == NULL) {
1855 cursor->blkno = 0;
1856 for (;;) {
1857 __uint16_t magic;
1858
1859 error = xfs_da3_node_read(NULL, context->dp,
1860 cursor->blkno, -1, &bp,
1861 XFS_ATTR_FORK);
1862 if (error)
1863 return(error);
1864 node = bp->b_addr;
1865 magic = be16_to_cpu(node->hdr.info.magic);
1866 if (magic == XFS_ATTR_LEAF_MAGIC ||
1867 magic == XFS_ATTR3_LEAF_MAGIC)
1868 break;
1869 if (magic != XFS_DA_NODE_MAGIC &&
1870 magic != XFS_DA3_NODE_MAGIC) {
1871 XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1872 XFS_ERRLEVEL_LOW,
1873 context->dp->i_mount,
1874 node);
1875 xfs_trans_brelse(NULL, bp);
1876 return XFS_ERROR(EFSCORRUPTED);
1877 }
1878
1879 xfs_da3_node_hdr_from_disk(&nodehdr, node);
1880 btree = xfs_da3_node_tree_p(node);
1881 for (i = 0; i < nodehdr.count; btree++, i++) {
1882 if (cursor->hashval
1883 <= be32_to_cpu(btree->hashval)) {
1884 cursor->blkno = be32_to_cpu(btree->before);
1885 trace_xfs_attr_list_node_descend(context,
1886 btree);
1887 break;
1888 }
1889 }
1890 if (i == nodehdr.count) {
1891 xfs_trans_brelse(NULL, bp);
1892 return 0;
1893 }
1894 xfs_trans_brelse(NULL, bp);
1895 }
1896 }
1897 ASSERT(bp != NULL);
1898
1899 /*
1900 * Roll upward through the blocks, processing each leaf block in
1901 * order. As long as there is space in the result buffer, keep
1902 * adding the information.
1903 */
1904 for (;;) {
1905 leaf = bp->b_addr;
1906 error = xfs_attr3_leaf_list_int(bp, context);
1907 if (error) {
1908 xfs_trans_brelse(NULL, bp);
1909 return error;
1910 }
1911 xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
1912 if (context->seen_enough || leafhdr.forw == 0)
1913 break;
1914 cursor->blkno = leafhdr.forw;
1915 xfs_trans_brelse(NULL, bp);
1916 error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1,
1917 &bp);
1918 if (error)
1919 return error;
1920 }
1921 xfs_trans_brelse(NULL, bp);
1922 return 0;
1923}