Merge tag 'mips_6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
[linux-2.6-microblaze.git] / fs / xfs / xfs_attr_list.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4  * Copyright (c) 2013 Red Hat, Inc.
5  * All Rights Reserved.
6  */
7 #include "xfs.h"
8 #include "xfs_fs.h"
9 #include "xfs_shared.h"
10 #include "xfs_format.h"
11 #include "xfs_log_format.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_da_format.h"
15 #include "xfs_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_bmap.h"
18 #include "xfs_da_btree.h"
19 #include "xfs_attr.h"
20 #include "xfs_attr_sf.h"
21 #include "xfs_attr_leaf.h"
22 #include "xfs_error.h"
23 #include "xfs_trace.h"
24 #include "xfs_dir2.h"
25 #include "xfs_health.h"
26
27 STATIC int
28 xfs_attr_shortform_compare(const void *a, const void *b)
29 {
30         xfs_attr_sf_sort_t *sa, *sb;
31
32         sa = (xfs_attr_sf_sort_t *)a;
33         sb = (xfs_attr_sf_sort_t *)b;
34         if (sa->hash < sb->hash) {
35                 return -1;
36         } else if (sa->hash > sb->hash) {
37                 return 1;
38         } else {
39                 return sa->entno - sb->entno;
40         }
41 }
42
43 #define XFS_ISRESET_CURSOR(cursor) \
44         (!((cursor)->initted) && !((cursor)->hashval) && \
45          !((cursor)->blkno) && !((cursor)->offset))
46 /*
47  * Copy out entries of shortform attribute lists for attr_list().
48  * Shortform attribute lists are not stored in hashval sorted order.
49  * If the output buffer is not large enough to hold them all, then
50  * we have to calculate each entries' hashvalue and sort them before
51  * we can begin returning them to the user.
52  */
53 static int
54 xfs_attr_shortform_list(
55         struct xfs_attr_list_context    *context)
56 {
57         struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
58         struct xfs_inode                *dp = context->dp;
59         struct xfs_attr_sf_sort         *sbuf, *sbp;
60         struct xfs_attr_sf_hdr          *sf = dp->i_af.if_data;
61         struct xfs_attr_sf_entry        *sfe;
62         int                             sbsize, nsbuf, count, i;
63         int                             error = 0;
64
65         ASSERT(sf != NULL);
66         if (!sf->count)
67                 return 0;
68
69         trace_xfs_attr_list_sf(context);
70
71         /*
72          * If the buffer is large enough and the cursor is at the start,
73          * do not bother with sorting since we will return everything in
74          * one buffer and another call using the cursor won't need to be
75          * made.
76          * Note the generous fudge factor of 16 overhead bytes per entry.
77          * If bufsize is zero then put_listent must be a search function
78          * and can just scan through what we have.
79          */
80         if (context->bufsize == 0 ||
81             (XFS_ISRESET_CURSOR(cursor) &&
82              (dp->i_af.if_bytes + sf->count * 16) < context->bufsize)) {
83                 for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) {
84                         if (XFS_IS_CORRUPT(context->dp->i_mount,
85                                            !xfs_attr_namecheck(sfe->nameval,
86                                                                sfe->namelen))) {
87                                 xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
88                                 return -EFSCORRUPTED;
89                         }
90                         context->put_listent(context,
91                                              sfe->flags,
92                                              sfe->nameval,
93                                              (int)sfe->namelen,
94                                              (int)sfe->valuelen);
95                         /*
96                          * Either search callback finished early or
97                          * didn't fit it all in the buffer after all.
98                          */
99                         if (context->seen_enough)
100                                 break;
101                         sfe = xfs_attr_sf_nextentry(sfe);
102                 }
103                 trace_xfs_attr_list_sf_all(context);
104                 return 0;
105         }
106
107         /* do no more for a search callback */
108         if (context->bufsize == 0)
109                 return 0;
110
111         /*
112          * It didn't all fit, so we have to sort everything on hashval.
113          */
114         sbsize = sf->count * sizeof(*sbuf);
115         sbp = sbuf = kmalloc(sbsize, GFP_KERNEL | __GFP_NOFAIL);
116
117         /*
118          * Scan the attribute list for the rest of the entries, storing
119          * the relevant info from only those that match into a buffer.
120          */
121         nsbuf = 0;
122         for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) {
123                 if (unlikely(
124                     ((char *)sfe < (char *)sf) ||
125                     ((char *)sfe >= ((char *)sf + dp->i_af.if_bytes)))) {
126                         XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
127                                              XFS_ERRLEVEL_LOW,
128                                              context->dp->i_mount, sfe,
129                                              sizeof(*sfe));
130                         kfree(sbuf);
131                         xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
132                         return -EFSCORRUPTED;
133                 }
134
135                 sbp->entno = i;
136                 sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen);
137                 sbp->name = sfe->nameval;
138                 sbp->namelen = sfe->namelen;
139                 /* These are bytes, and both on-disk, don't endian-flip */
140                 sbp->valuelen = sfe->valuelen;
141                 sbp->flags = sfe->flags;
142                 sfe = xfs_attr_sf_nextentry(sfe);
143                 sbp++;
144                 nsbuf++;
145         }
146
147         /*
148          * Sort the entries on hash then entno.
149          */
150         xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
151
152         /*
153          * Re-find our place IN THE SORTED LIST.
154          */
155         count = 0;
156         cursor->initted = 1;
157         cursor->blkno = 0;
158         for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {
159                 if (sbp->hash == cursor->hashval) {
160                         if (cursor->offset == count) {
161                                 break;
162                         }
163                         count++;
164                 } else if (sbp->hash > cursor->hashval) {
165                         break;
166                 }
167         }
168         if (i == nsbuf)
169                 goto out;
170
171         /*
172          * Loop putting entries into the user buffer.
173          */
174         for ( ; i < nsbuf; i++, sbp++) {
175                 if (cursor->hashval != sbp->hash) {
176                         cursor->hashval = sbp->hash;
177                         cursor->offset = 0;
178                 }
179                 if (XFS_IS_CORRUPT(context->dp->i_mount,
180                                    !xfs_attr_namecheck(sbp->name,
181                                                        sbp->namelen))) {
182                         xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
183                         error = -EFSCORRUPTED;
184                         goto out;
185                 }
186                 context->put_listent(context,
187                                      sbp->flags,
188                                      sbp->name,
189                                      sbp->namelen,
190                                      sbp->valuelen);
191                 if (context->seen_enough)
192                         break;
193                 cursor->offset++;
194         }
195 out:
196         kfree(sbuf);
197         return error;
198 }
199
200 /*
201  * We didn't find the block & hash mentioned in the cursor state, so
202  * walk down the attr btree looking for the hash.
203  */
204 STATIC int
205 xfs_attr_node_list_lookup(
206         struct xfs_attr_list_context    *context,
207         struct xfs_attrlist_cursor_kern *cursor,
208         struct xfs_buf                  **pbp)
209 {
210         struct xfs_da3_icnode_hdr       nodehdr;
211         struct xfs_da_intnode           *node;
212         struct xfs_da_node_entry        *btree;
213         struct xfs_inode                *dp = context->dp;
214         struct xfs_mount                *mp = dp->i_mount;
215         struct xfs_trans                *tp = context->tp;
216         struct xfs_buf                  *bp;
217         int                             i;
218         int                             error = 0;
219         unsigned int                    expected_level = 0;
220         uint16_t                        magic;
221
222         ASSERT(*pbp == NULL);
223         cursor->blkno = 0;
224         for (;;) {
225                 error = xfs_da3_node_read(tp, dp, cursor->blkno, &bp,
226                                 XFS_ATTR_FORK);
227                 if (error)
228                         return error;
229                 node = bp->b_addr;
230                 magic = be16_to_cpu(node->hdr.info.magic);
231                 if (magic == XFS_ATTR_LEAF_MAGIC ||
232                     magic == XFS_ATTR3_LEAF_MAGIC)
233                         break;
234                 if (magic != XFS_DA_NODE_MAGIC &&
235                     magic != XFS_DA3_NODE_MAGIC) {
236                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
237                                         node, sizeof(*node));
238                         goto out_corruptbuf;
239                 }
240
241                 xfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
242
243                 /* Tree taller than we can handle; bail out! */
244                 if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
245                         goto out_corruptbuf;
246
247                 /* Check the level from the root node. */
248                 if (cursor->blkno == 0)
249                         expected_level = nodehdr.level - 1;
250                 else if (expected_level != nodehdr.level)
251                         goto out_corruptbuf;
252                 else
253                         expected_level--;
254
255                 btree = nodehdr.btree;
256                 for (i = 0; i < nodehdr.count; btree++, i++) {
257                         if (cursor->hashval <= be32_to_cpu(btree->hashval)) {
258                                 cursor->blkno = be32_to_cpu(btree->before);
259                                 trace_xfs_attr_list_node_descend(context,
260                                                 btree);
261                                 break;
262                         }
263                 }
264                 xfs_trans_brelse(tp, bp);
265
266                 if (i == nodehdr.count)
267                         return 0;
268
269                 /* We can't point back to the root. */
270                 if (XFS_IS_CORRUPT(mp, cursor->blkno == 0)) {
271                         xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
272                         return -EFSCORRUPTED;
273                 }
274         }
275
276         if (expected_level != 0)
277                 goto out_corruptbuf;
278
279         *pbp = bp;
280         return 0;
281
282 out_corruptbuf:
283         xfs_buf_mark_corrupt(bp);
284         xfs_trans_brelse(tp, bp);
285         xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
286         return -EFSCORRUPTED;
287 }
288
289 STATIC int
290 xfs_attr_node_list(
291         struct xfs_attr_list_context    *context)
292 {
293         struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
294         struct xfs_attr3_icleaf_hdr     leafhdr;
295         struct xfs_attr_leafblock       *leaf;
296         struct xfs_da_intnode           *node;
297         struct xfs_buf                  *bp;
298         struct xfs_inode                *dp = context->dp;
299         struct xfs_mount                *mp = dp->i_mount;
300         int                             error = 0;
301
302         trace_xfs_attr_node_list(context);
303
304         cursor->initted = 1;
305
306         /*
307          * Do all sorts of validation on the passed-in cursor structure.
308          * If anything is amiss, ignore the cursor and look up the hashval
309          * starting from the btree root.
310          */
311         bp = NULL;
312         if (cursor->blkno > 0) {
313                 error = xfs_da3_node_read(context->tp, dp, cursor->blkno, &bp,
314                                 XFS_ATTR_FORK);
315                 if (xfs_metadata_is_sick(error))
316                         xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
317                 if ((error != 0) && (error != -EFSCORRUPTED))
318                         return error;
319                 if (bp) {
320                         struct xfs_attr_leaf_entry *entries;
321
322                         node = bp->b_addr;
323                         switch (be16_to_cpu(node->hdr.info.magic)) {
324                         case XFS_DA_NODE_MAGIC:
325                         case XFS_DA3_NODE_MAGIC:
326                                 trace_xfs_attr_list_wrong_blk(context);
327                                 xfs_trans_brelse(context->tp, bp);
328                                 bp = NULL;
329                                 break;
330                         case XFS_ATTR_LEAF_MAGIC:
331                         case XFS_ATTR3_LEAF_MAGIC:
332                                 leaf = bp->b_addr;
333                                 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
334                                                              &leafhdr, leaf);
335                                 entries = xfs_attr3_leaf_entryp(leaf);
336                                 if (cursor->hashval > be32_to_cpu(
337                                                 entries[leafhdr.count - 1].hashval)) {
338                                         trace_xfs_attr_list_wrong_blk(context);
339                                         xfs_trans_brelse(context->tp, bp);
340                                         bp = NULL;
341                                 } else if (cursor->hashval <= be32_to_cpu(
342                                                 entries[0].hashval)) {
343                                         trace_xfs_attr_list_wrong_blk(context);
344                                         xfs_trans_brelse(context->tp, bp);
345                                         bp = NULL;
346                                 }
347                                 break;
348                         default:
349                                 trace_xfs_attr_list_wrong_blk(context);
350                                 xfs_trans_brelse(context->tp, bp);
351                                 bp = NULL;
352                         }
353                 }
354         }
355
356         /*
357          * We did not find what we expected given the cursor's contents,
358          * so we start from the top and work down based on the hash value.
359          * Note that start of node block is same as start of leaf block.
360          */
361         if (bp == NULL) {
362                 error = xfs_attr_node_list_lookup(context, cursor, &bp);
363                 if (error || !bp)
364                         return error;
365         }
366         ASSERT(bp != NULL);
367
368         /*
369          * Roll upward through the blocks, processing each leaf block in
370          * order.  As long as there is space in the result buffer, keep
371          * adding the information.
372          */
373         for (;;) {
374                 leaf = bp->b_addr;
375                 error = xfs_attr3_leaf_list_int(bp, context);
376                 if (error)
377                         break;
378                 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
379                 if (context->seen_enough || leafhdr.forw == 0)
380                         break;
381                 cursor->blkno = leafhdr.forw;
382                 xfs_trans_brelse(context->tp, bp);
383                 error = xfs_attr3_leaf_read(context->tp, dp, cursor->blkno,
384                                             &bp);
385                 if (error)
386                         return error;
387         }
388         xfs_trans_brelse(context->tp, bp);
389         return error;
390 }
391
392 /*
393  * Copy out attribute list entries for attr_list(), for leaf attribute lists.
394  */
395 int
396 xfs_attr3_leaf_list_int(
397         struct xfs_buf                  *bp,
398         struct xfs_attr_list_context    *context)
399 {
400         struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
401         struct xfs_attr_leafblock       *leaf;
402         struct xfs_attr3_icleaf_hdr     ichdr;
403         struct xfs_attr_leaf_entry      *entries;
404         struct xfs_attr_leaf_entry      *entry;
405         int                             i;
406         struct xfs_mount                *mp = context->dp->i_mount;
407
408         trace_xfs_attr_list_leaf(context);
409
410         leaf = bp->b_addr;
411         xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
412         entries = xfs_attr3_leaf_entryp(leaf);
413
414         cursor->initted = 1;
415
416         /*
417          * Re-find our place in the leaf block if this is a new syscall.
418          */
419         if (context->resynch) {
420                 entry = &entries[0];
421                 for (i = 0; i < ichdr.count; entry++, i++) {
422                         if (be32_to_cpu(entry->hashval) == cursor->hashval) {
423                                 if (cursor->offset == context->dupcnt) {
424                                         context->dupcnt = 0;
425                                         break;
426                                 }
427                                 context->dupcnt++;
428                         } else if (be32_to_cpu(entry->hashval) >
429                                         cursor->hashval) {
430                                 context->dupcnt = 0;
431                                 break;
432                         }
433                 }
434                 if (i == ichdr.count) {
435                         trace_xfs_attr_list_notfound(context);
436                         return 0;
437                 }
438         } else {
439                 entry = &entries[0];
440                 i = 0;
441         }
442         context->resynch = 0;
443
444         /*
445          * We have found our place, start copying out the new attributes.
446          */
447         for (; i < ichdr.count; entry++, i++) {
448                 char *name;
449                 int namelen, valuelen;
450
451                 if (be32_to_cpu(entry->hashval) != cursor->hashval) {
452                         cursor->hashval = be32_to_cpu(entry->hashval);
453                         cursor->offset = 0;
454                 }
455
456                 if ((entry->flags & XFS_ATTR_INCOMPLETE) &&
457                     !context->allow_incomplete)
458                         continue;
459
460                 if (entry->flags & XFS_ATTR_LOCAL) {
461                         xfs_attr_leaf_name_local_t *name_loc;
462
463                         name_loc = xfs_attr3_leaf_name_local(leaf, i);
464                         name = name_loc->nameval;
465                         namelen = name_loc->namelen;
466                         valuelen = be16_to_cpu(name_loc->valuelen);
467                 } else {
468                         xfs_attr_leaf_name_remote_t *name_rmt;
469
470                         name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
471                         name = name_rmt->name;
472                         namelen = name_rmt->namelen;
473                         valuelen = be32_to_cpu(name_rmt->valuelen);
474                 }
475
476                 if (XFS_IS_CORRUPT(context->dp->i_mount,
477                                    !xfs_attr_namecheck(name, namelen))) {
478                         xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
479                         return -EFSCORRUPTED;
480                 }
481                 context->put_listent(context, entry->flags,
482                                               name, namelen, valuelen);
483                 if (context->seen_enough)
484                         break;
485                 cursor->offset++;
486         }
487         trace_xfs_attr_list_leaf_end(context);
488         return 0;
489 }
490
491 /*
492  * Copy out attribute entries for attr_list(), for leaf attribute lists.
493  */
494 STATIC int
495 xfs_attr_leaf_list(
496         struct xfs_attr_list_context    *context)
497 {
498         struct xfs_buf                  *bp;
499         int                             error;
500
501         trace_xfs_attr_leaf_list(context);
502
503         context->cursor.blkno = 0;
504         error = xfs_attr3_leaf_read(context->tp, context->dp, 0, &bp);
505         if (error)
506                 return error;
507
508         error = xfs_attr3_leaf_list_int(bp, context);
509         xfs_trans_brelse(context->tp, bp);
510         return error;
511 }
512
513 int
514 xfs_attr_list_ilocked(
515         struct xfs_attr_list_context    *context)
516 {
517         struct xfs_inode                *dp = context->dp;
518
519         xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
520
521         /*
522          * Decide on what work routines to call based on the inode size.
523          */
524         if (!xfs_inode_hasattr(dp))
525                 return 0;
526         if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
527                 return xfs_attr_shortform_list(context);
528         if (xfs_attr_is_leaf(dp))
529                 return xfs_attr_leaf_list(context);
530         return xfs_attr_node_list(context);
531 }
532
533 int
534 xfs_attr_list(
535         struct xfs_attr_list_context    *context)
536 {
537         struct xfs_inode                *dp = context->dp;
538         uint                            lock_mode;
539         int                             error;
540
541         XFS_STATS_INC(dp->i_mount, xs_attr_list);
542
543         if (xfs_is_shutdown(dp->i_mount))
544                 return -EIO;
545
546         lock_mode = xfs_ilock_attr_map_shared(dp);
547         error = xfs_attr_list_ilocked(context);
548         xfs_iunlock(dp, lock_mode);
549         return error;
550 }