Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
[linux-2.6-microblaze.git] / fs / xfs / xfs_attr_list.c
1 /*
2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3  * Copyright (c) 2013 Red Hat, Inc.
4  * All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it would be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write the Free Software Foundation,
17  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 #include "xfs.h"
20 #include "xfs_fs.h"
21 #include "xfs_types.h"
22 #include "xfs_bit.h"
23 #include "xfs_log.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_mount.h"
28 #include "xfs_da_btree.h"
29 #include "xfs_bmap_btree.h"
30 #include "xfs_alloc_btree.h"
31 #include "xfs_ialloc_btree.h"
32 #include "xfs_alloc.h"
33 #include "xfs_btree.h"
34 #include "xfs_attr_sf.h"
35 #include "xfs_attr_remote.h"
36 #include "xfs_dinode.h"
37 #include "xfs_inode.h"
38 #include "xfs_inode_item.h"
39 #include "xfs_bmap.h"
40 #include "xfs_attr.h"
41 #include "xfs_attr_leaf.h"
42 #include "xfs_error.h"
43 #include "xfs_trace.h"
44 #include "xfs_buf_item.h"
45 #include "xfs_cksum.h"
46
47 STATIC int
48 xfs_attr_shortform_compare(const void *a, const void *b)
49 {
50         xfs_attr_sf_sort_t *sa, *sb;
51
52         sa = (xfs_attr_sf_sort_t *)a;
53         sb = (xfs_attr_sf_sort_t *)b;
54         if (sa->hash < sb->hash) {
55                 return(-1);
56         } else if (sa->hash > sb->hash) {
57                 return(1);
58         } else {
59                 return(sa->entno - sb->entno);
60         }
61 }
62
63 #define XFS_ISRESET_CURSOR(cursor) \
64         (!((cursor)->initted) && !((cursor)->hashval) && \
65          !((cursor)->blkno) && !((cursor)->offset))
66 /*
67  * Copy out entries of shortform attribute lists for attr_list().
68  * Shortform attribute lists are not stored in hashval sorted order.
69  * If the output buffer is not large enough to hold them all, then we
70  * we have to calculate each entries' hashvalue and sort them before
71  * we can begin returning them to the user.
72  */
73 int
74 xfs_attr_shortform_list(xfs_attr_list_context_t *context)
75 {
76         attrlist_cursor_kern_t *cursor;
77         xfs_attr_sf_sort_t *sbuf, *sbp;
78         xfs_attr_shortform_t *sf;
79         xfs_attr_sf_entry_t *sfe;
80         xfs_inode_t *dp;
81         int sbsize, nsbuf, count, i;
82         int error;
83
84         ASSERT(context != NULL);
85         dp = context->dp;
86         ASSERT(dp != NULL);
87         ASSERT(dp->i_afp != NULL);
88         sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
89         ASSERT(sf != NULL);
90         if (!sf->hdr.count)
91                 return(0);
92         cursor = context->cursor;
93         ASSERT(cursor != NULL);
94
95         trace_xfs_attr_list_sf(context);
96
97         /*
98          * If the buffer is large enough and the cursor is at the start,
99          * do not bother with sorting since we will return everything in
100          * one buffer and another call using the cursor won't need to be
101          * made.
102          * Note the generous fudge factor of 16 overhead bytes per entry.
103          * If bufsize is zero then put_listent must be a search function
104          * and can just scan through what we have.
105          */
106         if (context->bufsize == 0 ||
107             (XFS_ISRESET_CURSOR(cursor) &&
108              (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
109                 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
110                         error = context->put_listent(context,
111                                            sfe->flags,
112                                            sfe->nameval,
113                                            (int)sfe->namelen,
114                                            (int)sfe->valuelen,
115                                            &sfe->nameval[sfe->namelen]);
116
117                         /*
118                          * Either search callback finished early or
119                          * didn't fit it all in the buffer after all.
120                          */
121                         if (context->seen_enough)
122                                 break;
123
124                         if (error)
125                                 return error;
126                         sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
127                 }
128                 trace_xfs_attr_list_sf_all(context);
129                 return(0);
130         }
131
132         /* do no more for a search callback */
133         if (context->bufsize == 0)
134                 return 0;
135
136         /*
137          * It didn't all fit, so we have to sort everything on hashval.
138          */
139         sbsize = sf->hdr.count * sizeof(*sbuf);
140         sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP | KM_NOFS);
141
142         /*
143          * Scan the attribute list for the rest of the entries, storing
144          * the relevant info from only those that match into a buffer.
145          */
146         nsbuf = 0;
147         for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
148                 if (unlikely(
149                     ((char *)sfe < (char *)sf) ||
150                     ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
151                         XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
152                                              XFS_ERRLEVEL_LOW,
153                                              context->dp->i_mount, sfe);
154                         kmem_free(sbuf);
155                         return XFS_ERROR(EFSCORRUPTED);
156                 }
157
158                 sbp->entno = i;
159                 sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen);
160                 sbp->name = sfe->nameval;
161                 sbp->namelen = sfe->namelen;
162                 /* These are bytes, and both on-disk, don't endian-flip */
163                 sbp->valuelen = sfe->valuelen;
164                 sbp->flags = sfe->flags;
165                 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
166                 sbp++;
167                 nsbuf++;
168         }
169
170         /*
171          * Sort the entries on hash then entno.
172          */
173         xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
174
175         /*
176          * Re-find our place IN THE SORTED LIST.
177          */
178         count = 0;
179         cursor->initted = 1;
180         cursor->blkno = 0;
181         for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {
182                 if (sbp->hash == cursor->hashval) {
183                         if (cursor->offset == count) {
184                                 break;
185                         }
186                         count++;
187                 } else if (sbp->hash > cursor->hashval) {
188                         break;
189                 }
190         }
191         if (i == nsbuf) {
192                 kmem_free(sbuf);
193                 return(0);
194         }
195
196         /*
197          * Loop putting entries into the user buffer.
198          */
199         for ( ; i < nsbuf; i++, sbp++) {
200                 if (cursor->hashval != sbp->hash) {
201                         cursor->hashval = sbp->hash;
202                         cursor->offset = 0;
203                 }
204                 error = context->put_listent(context,
205                                         sbp->flags,
206                                         sbp->name,
207                                         sbp->namelen,
208                                         sbp->valuelen,
209                                         &sbp->name[sbp->namelen]);
210                 if (error)
211                         return error;
212                 if (context->seen_enough)
213                         break;
214                 cursor->offset++;
215         }
216
217         kmem_free(sbuf);
218         return(0);
219 }
220
221 STATIC int
222 xfs_attr_node_list(xfs_attr_list_context_t *context)
223 {
224         attrlist_cursor_kern_t *cursor;
225         xfs_attr_leafblock_t *leaf;
226         xfs_da_intnode_t *node;
227         struct xfs_attr3_icleaf_hdr leafhdr;
228         struct xfs_da3_icnode_hdr nodehdr;
229         struct xfs_da_node_entry *btree;
230         int error, i;
231         struct xfs_buf *bp;
232
233         trace_xfs_attr_node_list(context);
234
235         cursor = context->cursor;
236         cursor->initted = 1;
237
238         /*
239          * Do all sorts of validation on the passed-in cursor structure.
240          * If anything is amiss, ignore the cursor and look up the hashval
241          * starting from the btree root.
242          */
243         bp = NULL;
244         if (cursor->blkno > 0) {
245                 error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1,
246                                               &bp, XFS_ATTR_FORK);
247                 if ((error != 0) && (error != EFSCORRUPTED))
248                         return(error);
249                 if (bp) {
250                         struct xfs_attr_leaf_entry *entries;
251
252                         node = bp->b_addr;
253                         switch (be16_to_cpu(node->hdr.info.magic)) {
254                         case XFS_DA_NODE_MAGIC:
255                         case XFS_DA3_NODE_MAGIC:
256                                 trace_xfs_attr_list_wrong_blk(context);
257                                 xfs_trans_brelse(NULL, bp);
258                                 bp = NULL;
259                                 break;
260                         case XFS_ATTR_LEAF_MAGIC:
261                         case XFS_ATTR3_LEAF_MAGIC:
262                                 leaf = bp->b_addr;
263                                 xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
264                                 entries = xfs_attr3_leaf_entryp(leaf);
265                                 if (cursor->hashval > be32_to_cpu(
266                                                 entries[leafhdr.count - 1].hashval)) {
267                                         trace_xfs_attr_list_wrong_blk(context);
268                                         xfs_trans_brelse(NULL, bp);
269                                         bp = NULL;
270                                 } else if (cursor->hashval <= be32_to_cpu(
271                                                 entries[0].hashval)) {
272                                         trace_xfs_attr_list_wrong_blk(context);
273                                         xfs_trans_brelse(NULL, bp);
274                                         bp = NULL;
275                                 }
276                                 break;
277                         default:
278                                 trace_xfs_attr_list_wrong_blk(context);
279                                 xfs_trans_brelse(NULL, bp);
280                                 bp = NULL;
281                         }
282                 }
283         }
284
285         /*
286          * We did not find what we expected given the cursor's contents,
287          * so we start from the top and work down based on the hash value.
288          * Note that start of node block is same as start of leaf block.
289          */
290         if (bp == NULL) {
291                 cursor->blkno = 0;
292                 for (;;) {
293                         __uint16_t magic;
294
295                         error = xfs_da3_node_read(NULL, context->dp,
296                                                       cursor->blkno, -1, &bp,
297                                                       XFS_ATTR_FORK);
298                         if (error)
299                                 return(error);
300                         node = bp->b_addr;
301                         magic = be16_to_cpu(node->hdr.info.magic);
302                         if (magic == XFS_ATTR_LEAF_MAGIC ||
303                             magic == XFS_ATTR3_LEAF_MAGIC)
304                                 break;
305                         if (magic != XFS_DA_NODE_MAGIC &&
306                             magic != XFS_DA3_NODE_MAGIC) {
307                                 XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
308                                                      XFS_ERRLEVEL_LOW,
309                                                      context->dp->i_mount,
310                                                      node);
311                                 xfs_trans_brelse(NULL, bp);
312                                 return XFS_ERROR(EFSCORRUPTED);
313                         }
314
315                         xfs_da3_node_hdr_from_disk(&nodehdr, node);
316                         btree = xfs_da3_node_tree_p(node);
317                         for (i = 0; i < nodehdr.count; btree++, i++) {
318                                 if (cursor->hashval
319                                                 <= be32_to_cpu(btree->hashval)) {
320                                         cursor->blkno = be32_to_cpu(btree->before);
321                                         trace_xfs_attr_list_node_descend(context,
322                                                                          btree);
323                                         break;
324                                 }
325                         }
326                         if (i == nodehdr.count) {
327                                 xfs_trans_brelse(NULL, bp);
328                                 return 0;
329                         }
330                         xfs_trans_brelse(NULL, bp);
331                 }
332         }
333         ASSERT(bp != NULL);
334
335         /*
336          * Roll upward through the blocks, processing each leaf block in
337          * order.  As long as there is space in the result buffer, keep
338          * adding the information.
339          */
340         for (;;) {
341                 leaf = bp->b_addr;
342                 error = xfs_attr3_leaf_list_int(bp, context);
343                 if (error) {
344                         xfs_trans_brelse(NULL, bp);
345                         return error;
346                 }
347                 xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
348                 if (context->seen_enough || leafhdr.forw == 0)
349                         break;
350                 cursor->blkno = leafhdr.forw;
351                 xfs_trans_brelse(NULL, bp);
352                 error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1,
353                                            &bp);
354                 if (error)
355                         return error;
356         }
357         xfs_trans_brelse(NULL, bp);
358         return 0;
359 }
360
361 /*
362  * Copy out attribute list entries for attr_list(), for leaf attribute lists.
363  */
364 int
365 xfs_attr3_leaf_list_int(
366         struct xfs_buf                  *bp,
367         struct xfs_attr_list_context    *context)
368 {
369         struct attrlist_cursor_kern     *cursor;
370         struct xfs_attr_leafblock       *leaf;
371         struct xfs_attr3_icleaf_hdr     ichdr;
372         struct xfs_attr_leaf_entry      *entries;
373         struct xfs_attr_leaf_entry      *entry;
374         int                             retval;
375         int                             i;
376
377         trace_xfs_attr_list_leaf(context);
378
379         leaf = bp->b_addr;
380         xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
381         entries = xfs_attr3_leaf_entryp(leaf);
382
383         cursor = context->cursor;
384         cursor->initted = 1;
385
386         /*
387          * Re-find our place in the leaf block if this is a new syscall.
388          */
389         if (context->resynch) {
390                 entry = &entries[0];
391                 for (i = 0; i < ichdr.count; entry++, i++) {
392                         if (be32_to_cpu(entry->hashval) == cursor->hashval) {
393                                 if (cursor->offset == context->dupcnt) {
394                                         context->dupcnt = 0;
395                                         break;
396                                 }
397                                 context->dupcnt++;
398                         } else if (be32_to_cpu(entry->hashval) >
399                                         cursor->hashval) {
400                                 context->dupcnt = 0;
401                                 break;
402                         }
403                 }
404                 if (i == ichdr.count) {
405                         trace_xfs_attr_list_notfound(context);
406                         return 0;
407                 }
408         } else {
409                 entry = &entries[0];
410                 i = 0;
411         }
412         context->resynch = 0;
413
414         /*
415          * We have found our place, start copying out the new attributes.
416          */
417         retval = 0;
418         for (; i < ichdr.count; entry++, i++) {
419                 if (be32_to_cpu(entry->hashval) != cursor->hashval) {
420                         cursor->hashval = be32_to_cpu(entry->hashval);
421                         cursor->offset = 0;
422                 }
423
424                 if (entry->flags & XFS_ATTR_INCOMPLETE)
425                         continue;               /* skip incomplete entries */
426
427                 if (entry->flags & XFS_ATTR_LOCAL) {
428                         xfs_attr_leaf_name_local_t *name_loc =
429                                 xfs_attr3_leaf_name_local(leaf, i);
430
431                         retval = context->put_listent(context,
432                                                 entry->flags,
433                                                 name_loc->nameval,
434                                                 (int)name_loc->namelen,
435                                                 be16_to_cpu(name_loc->valuelen),
436                                                 &name_loc->nameval[name_loc->namelen]);
437                         if (retval)
438                                 return retval;
439                 } else {
440                         xfs_attr_leaf_name_remote_t *name_rmt =
441                                 xfs_attr3_leaf_name_remote(leaf, i);
442
443                         int valuelen = be32_to_cpu(name_rmt->valuelen);
444
445                         if (context->put_value) {
446                                 xfs_da_args_t args;
447
448                                 memset((char *)&args, 0, sizeof(args));
449                                 args.dp = context->dp;
450                                 args.whichfork = XFS_ATTR_FORK;
451                                 args.valuelen = valuelen;
452                                 args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS);
453                                 args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
454                                 args.rmtblkcnt = xfs_attr3_rmt_blocks(
455                                                         args.dp->i_mount, valuelen);
456                                 retval = xfs_attr_rmtval_get(&args);
457                                 if (retval)
458                                         return retval;
459                                 retval = context->put_listent(context,
460                                                 entry->flags,
461                                                 name_rmt->name,
462                                                 (int)name_rmt->namelen,
463                                                 valuelen,
464                                                 args.value);
465                                 kmem_free(args.value);
466                         } else {
467                                 retval = context->put_listent(context,
468                                                 entry->flags,
469                                                 name_rmt->name,
470                                                 (int)name_rmt->namelen,
471                                                 valuelen,
472                                                 NULL);
473                         }
474                         if (retval)
475                                 return retval;
476                 }
477                 if (context->seen_enough)
478                         break;
479                 cursor->offset++;
480         }
481         trace_xfs_attr_list_leaf_end(context);
482         return retval;
483 }
484
485 /*
486  * Copy out attribute entries for attr_list(), for leaf attribute lists.
487  */
488 STATIC int
489 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
490 {
491         int error;
492         struct xfs_buf *bp;
493
494         trace_xfs_attr_leaf_list(context);
495
496         context->cursor->blkno = 0;
497         error = xfs_attr3_leaf_read(NULL, context->dp, 0, -1, &bp);
498         if (error)
499                 return XFS_ERROR(error);
500
501         error = xfs_attr3_leaf_list_int(bp, context);
502         xfs_trans_brelse(NULL, bp);
503         return XFS_ERROR(error);
504 }
505
506 int
507 xfs_attr_list_int(
508         xfs_attr_list_context_t *context)
509 {
510         int error;
511         xfs_inode_t *dp = context->dp;
512
513         XFS_STATS_INC(xs_attr_list);
514
515         if (XFS_FORCED_SHUTDOWN(dp->i_mount))
516                 return EIO;
517
518         xfs_ilock(dp, XFS_ILOCK_SHARED);
519
520         /*
521          * Decide on what work routines to call based on the inode size.
522          */
523         if (!xfs_inode_hasattr(dp)) {
524                 error = 0;
525         } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
526                 error = xfs_attr_shortform_list(context);
527         } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
528                 error = xfs_attr_leaf_list(context);
529         } else {
530                 error = xfs_attr_node_list(context);
531         }
532
533         xfs_iunlock(dp, XFS_ILOCK_SHARED);
534
535         return error;
536 }
537
538 #define ATTR_ENTBASESIZE                /* minimum bytes used by an attr */ \
539         (((struct attrlist_ent *) 0)->a_name - (char *) 0)
540 #define ATTR_ENTSIZE(namelen)           /* actual bytes used by an attr */ \
541         ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
542          & ~(sizeof(u_int32_t)-1))
543
544 /*
545  * Format an attribute and copy it out to the user's buffer.
546  * Take care to check values and protect against them changing later,
547  * we may be reading them directly out of a user buffer.
548  */
549 STATIC int
550 xfs_attr_put_listent(
551         xfs_attr_list_context_t *context,
552         int             flags,
553         unsigned char   *name,
554         int             namelen,
555         int             valuelen,
556         unsigned char   *value)
557 {
558         struct attrlist *alist = (struct attrlist *)context->alist;
559         attrlist_ent_t *aep;
560         int arraytop;
561
562         ASSERT(!(context->flags & ATTR_KERNOVAL));
563         ASSERT(context->count >= 0);
564         ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
565         ASSERT(context->firstu >= sizeof(*alist));
566         ASSERT(context->firstu <= context->bufsize);
567
568         /*
569          * Only list entries in the right namespace.
570          */
571         if (((context->flags & ATTR_SECURE) == 0) !=
572             ((flags & XFS_ATTR_SECURE) == 0))
573                 return 0;
574         if (((context->flags & ATTR_ROOT) == 0) !=
575             ((flags & XFS_ATTR_ROOT) == 0))
576                 return 0;
577
578         arraytop = sizeof(*alist) +
579                         context->count * sizeof(alist->al_offset[0]);
580         context->firstu -= ATTR_ENTSIZE(namelen);
581         if (context->firstu < arraytop) {
582                 trace_xfs_attr_list_full(context);
583                 alist->al_more = 1;
584                 context->seen_enough = 1;
585                 return 1;
586         }
587
588         aep = (attrlist_ent_t *)&context->alist[context->firstu];
589         aep->a_valuelen = valuelen;
590         memcpy(aep->a_name, name, namelen);
591         aep->a_name[namelen] = 0;
592         alist->al_offset[context->count++] = context->firstu;
593         alist->al_count = context->count;
594         trace_xfs_attr_list_add(context);
595         return 0;
596 }
597
598 /*
599  * Generate a list of extended attribute names and optionally
600  * also value lengths.  Positive return value follows the XFS
601  * convention of being an error, zero or negative return code
602  * is the length of the buffer returned (negated), indicating
603  * success.
604  */
605 int
606 xfs_attr_list(
607         xfs_inode_t     *dp,
608         char            *buffer,
609         int             bufsize,
610         int             flags,
611         attrlist_cursor_kern_t *cursor)
612 {
613         xfs_attr_list_context_t context;
614         struct attrlist *alist;
615         int error;
616
617         /*
618          * Validate the cursor.
619          */
620         if (cursor->pad1 || cursor->pad2)
621                 return(XFS_ERROR(EINVAL));
622         if ((cursor->initted == 0) &&
623             (cursor->hashval || cursor->blkno || cursor->offset))
624                 return XFS_ERROR(EINVAL);
625
626         /*
627          * Check for a properly aligned buffer.
628          */
629         if (((long)buffer) & (sizeof(int)-1))
630                 return XFS_ERROR(EFAULT);
631         if (flags & ATTR_KERNOVAL)
632                 bufsize = 0;
633
634         /*
635          * Initialize the output buffer.
636          */
637         memset(&context, 0, sizeof(context));
638         context.dp = dp;
639         context.cursor = cursor;
640         context.resynch = 1;
641         context.flags = flags;
642         context.alist = buffer;
643         context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
644         context.firstu = context.bufsize;
645         context.put_listent = xfs_attr_put_listent;
646
647         alist = (struct attrlist *)context.alist;
648         alist->al_count = 0;
649         alist->al_more = 0;
650         alist->al_offset[0] = context.bufsize;
651
652         error = xfs_attr_list_int(&context);
653         ASSERT(error >= 0);
654         return error;
655 }