drm/tests: Add test for drm_atomic_helper_check_modeset()
[drm/drm-misc.git] / fs / xfs / xfs_handle.c
blobf19fce557354eca77d3fd1d4a0ffe573eb1b59f4
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * Copyright (c) 2022-2024 Oracle.
5 * All rights reserved.
6 */
7 #include "xfs.h"
8 #include "xfs_fs.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_shared.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_bmap_btree.h"
15 #include "xfs_inode.h"
16 #include "xfs_error.h"
17 #include "xfs_trace.h"
18 #include "xfs_trans.h"
19 #include "xfs_da_format.h"
20 #include "xfs_da_btree.h"
21 #include "xfs_attr.h"
22 #include "xfs_ioctl.h"
23 #include "xfs_parent.h"
24 #include "xfs_handle.h"
25 #include "xfs_health.h"
26 #include "xfs_icache.h"
27 #include "xfs_export.h"
28 #include "xfs_xattr.h"
29 #include "xfs_acl.h"
31 #include <linux/namei.h>
33 static inline size_t
34 xfs_filehandle_fid_len(void)
36 struct xfs_handle *handle = NULL;
38 return sizeof(struct xfs_fid) - sizeof(handle->ha_fid.fid_len);
41 static inline size_t
42 xfs_filehandle_init(
43 struct xfs_mount *mp,
44 xfs_ino_t ino,
45 uint32_t gen,
46 struct xfs_handle *handle)
48 memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
50 handle->ha_fid.fid_len = xfs_filehandle_fid_len();
51 handle->ha_fid.fid_pad = 0;
52 handle->ha_fid.fid_gen = gen;
53 handle->ha_fid.fid_ino = ino;
55 return sizeof(struct xfs_handle);
58 static inline size_t
59 xfs_fshandle_init(
60 struct xfs_mount *mp,
61 struct xfs_handle *handle)
63 memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
64 memset(&handle->ha_fid, 0, sizeof(handle->ha_fid));
66 return sizeof(struct xfs_fsid);
70 * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
71 * a file or fs handle.
73 * XFS_IOC_PATH_TO_FSHANDLE
74 * returns fs handle for a mount point or path within that mount point
75 * XFS_IOC_FD_TO_HANDLE
76 * returns full handle for a FD opened in user space
77 * XFS_IOC_PATH_TO_HANDLE
78 * returns full handle for a path
80 int
81 xfs_find_handle(
82 unsigned int cmd,
83 xfs_fsop_handlereq_t *hreq)
85 int hsize;
86 xfs_handle_t handle;
87 struct inode *inode;
88 struct path path;
89 int error;
90 struct xfs_inode *ip;
92 if (cmd == XFS_IOC_FD_TO_HANDLE) {
93 CLASS(fd, f)(hreq->fd);
95 if (fd_empty(f))
96 return -EBADF;
97 path = fd_file(f)->f_path;
98 path_get(&path);
99 } else {
100 error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
101 if (error)
102 return error;
104 inode = d_inode(path.dentry);
105 ip = XFS_I(inode);
108 * We can only generate handles for inodes residing on a XFS filesystem,
109 * and only for regular files, directories or symbolic links.
111 error = -EINVAL;
112 if (inode->i_sb->s_magic != XFS_SB_MAGIC)
113 goto out_put;
115 error = -EBADF;
116 if (!S_ISREG(inode->i_mode) &&
117 !S_ISDIR(inode->i_mode) &&
118 !S_ISLNK(inode->i_mode))
119 goto out_put;
122 memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
124 if (cmd == XFS_IOC_PATH_TO_FSHANDLE)
125 hsize = xfs_fshandle_init(ip->i_mount, &handle);
126 else
127 hsize = xfs_filehandle_init(ip->i_mount, ip->i_ino,
128 inode->i_generation, &handle);
130 error = -EFAULT;
131 if (copy_to_user(hreq->ohandle, &handle, hsize) ||
132 copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
133 goto out_put;
135 error = 0;
137 out_put:
138 path_put(&path);
139 return error;
143 * No need to do permission checks on the various pathname components
144 * as the handle operations are privileged.
146 STATIC int
147 xfs_handle_acceptable(
148 void *context,
149 struct dentry *dentry)
151 return 1;
154 /* Convert handle already copied to kernel space into a dentry. */
155 static struct dentry *
156 xfs_khandle_to_dentry(
157 struct file *file,
158 struct xfs_handle *handle)
160 struct xfs_fid64 fid = {
161 .ino = handle->ha_fid.fid_ino,
162 .gen = handle->ha_fid.fid_gen,
166 * Only allow handle opens under a directory.
168 if (!S_ISDIR(file_inode(file)->i_mode))
169 return ERR_PTR(-ENOTDIR);
171 if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
172 return ERR_PTR(-EINVAL);
174 return exportfs_decode_fh(file->f_path.mnt, (struct fid *)&fid, 3,
175 FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
176 xfs_handle_acceptable, NULL);
179 /* Convert handle already copied to kernel space into an xfs_inode. */
180 static struct xfs_inode *
181 xfs_khandle_to_inode(
182 struct file *file,
183 struct xfs_handle *handle)
185 struct xfs_inode *ip = XFS_I(file_inode(file));
186 struct xfs_mount *mp = ip->i_mount;
187 struct inode *inode;
189 if (!S_ISDIR(VFS_I(ip)->i_mode))
190 return ERR_PTR(-ENOTDIR);
192 if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
193 return ERR_PTR(-EINVAL);
195 inode = xfs_nfs_get_inode(mp->m_super, handle->ha_fid.fid_ino,
196 handle->ha_fid.fid_gen);
197 if (IS_ERR(inode))
198 return ERR_CAST(inode);
200 return XFS_I(inode);
204 * Convert userspace handle data into a dentry.
206 struct dentry *
207 xfs_handle_to_dentry(
208 struct file *parfilp,
209 void __user *uhandle,
210 u32 hlen)
212 xfs_handle_t handle;
214 if (hlen != sizeof(xfs_handle_t))
215 return ERR_PTR(-EINVAL);
216 if (copy_from_user(&handle, uhandle, hlen))
217 return ERR_PTR(-EFAULT);
219 return xfs_khandle_to_dentry(parfilp, &handle);
222 STATIC struct dentry *
223 xfs_handlereq_to_dentry(
224 struct file *parfilp,
225 xfs_fsop_handlereq_t *hreq)
227 return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
231 xfs_open_by_handle(
232 struct file *parfilp,
233 xfs_fsop_handlereq_t *hreq)
235 const struct cred *cred = current_cred();
236 int error;
237 int fd;
238 int permflag;
239 struct file *filp;
240 struct inode *inode;
241 struct dentry *dentry;
242 fmode_t fmode;
243 struct path path;
245 if (!capable(CAP_SYS_ADMIN))
246 return -EPERM;
248 dentry = xfs_handlereq_to_dentry(parfilp, hreq);
249 if (IS_ERR(dentry))
250 return PTR_ERR(dentry);
251 inode = d_inode(dentry);
253 /* Restrict xfs_open_by_handle to directories & regular files. */
254 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
255 error = -EPERM;
256 goto out_dput;
259 #if BITS_PER_LONG != 32
260 hreq->oflags |= O_LARGEFILE;
261 #endif
263 permflag = hreq->oflags;
264 fmode = OPEN_FMODE(permflag);
265 if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
266 (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
267 error = -EPERM;
268 goto out_dput;
271 if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
272 error = -EPERM;
273 goto out_dput;
276 /* Can't write directories. */
277 if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
278 error = -EISDIR;
279 goto out_dput;
282 fd = get_unused_fd_flags(0);
283 if (fd < 0) {
284 error = fd;
285 goto out_dput;
288 path.mnt = parfilp->f_path.mnt;
289 path.dentry = dentry;
290 filp = dentry_open(&path, hreq->oflags, cred);
291 dput(dentry);
292 if (IS_ERR(filp)) {
293 put_unused_fd(fd);
294 return PTR_ERR(filp);
297 if (S_ISREG(inode->i_mode)) {
298 filp->f_flags |= O_NOATIME;
299 filp->f_mode |= FMODE_NOCMTIME;
302 fd_install(fd, filp);
303 return fd;
305 out_dput:
306 dput(dentry);
307 return error;
311 xfs_readlink_by_handle(
312 struct file *parfilp,
313 xfs_fsop_handlereq_t *hreq)
315 struct dentry *dentry;
316 __u32 olen;
317 int error;
319 if (!capable(CAP_SYS_ADMIN))
320 return -EPERM;
322 dentry = xfs_handlereq_to_dentry(parfilp, hreq);
323 if (IS_ERR(dentry))
324 return PTR_ERR(dentry);
326 /* Restrict this handle operation to symlinks only. */
327 if (!d_is_symlink(dentry)) {
328 error = -EINVAL;
329 goto out_dput;
332 if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
333 error = -EFAULT;
334 goto out_dput;
337 error = vfs_readlink(dentry, hreq->ohandle, olen);
339 out_dput:
340 dput(dentry);
341 return error;
345 * Format an attribute and copy it out to the user's buffer.
346 * Take care to check values and protect against them changing later,
347 * we may be reading them directly out of a user buffer.
349 static void
350 xfs_ioc_attr_put_listent(
351 struct xfs_attr_list_context *context,
352 int flags,
353 unsigned char *name,
354 int namelen,
355 void *value,
356 int valuelen)
358 struct xfs_attrlist *alist = context->buffer;
359 struct xfs_attrlist_ent *aep;
360 int arraytop;
362 ASSERT(!context->seen_enough);
363 ASSERT(context->count >= 0);
364 ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
365 ASSERT(context->firstu >= sizeof(*alist));
366 ASSERT(context->firstu <= context->bufsize);
369 * Only list entries in the right namespace.
371 if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
372 return;
374 arraytop = sizeof(*alist) +
375 context->count * sizeof(alist->al_offset[0]);
377 /* decrement by the actual bytes used by the attr */
378 context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
379 namelen + 1, sizeof(uint32_t));
380 if (context->firstu < arraytop) {
381 trace_xfs_attr_list_full(context);
382 alist->al_more = 1;
383 context->seen_enough = 1;
384 return;
387 aep = context->buffer + context->firstu;
388 aep->a_valuelen = valuelen;
389 memcpy(aep->a_name, name, namelen);
390 aep->a_name[namelen] = 0;
391 alist->al_offset[context->count++] = context->firstu;
392 alist->al_count = context->count;
393 trace_xfs_attr_list_add(context);
396 static unsigned int
397 xfs_attr_filter(
398 u32 ioc_flags)
400 if (ioc_flags & XFS_IOC_ATTR_ROOT)
401 return XFS_ATTR_ROOT;
402 if (ioc_flags & XFS_IOC_ATTR_SECURE)
403 return XFS_ATTR_SECURE;
404 return 0;
407 static inline enum xfs_attr_update
408 xfs_xattr_flags(
409 u32 ioc_flags,
410 void *value)
412 if (!value)
413 return XFS_ATTRUPDATE_REMOVE;
414 if (ioc_flags & XFS_IOC_ATTR_CREATE)
415 return XFS_ATTRUPDATE_CREATE;
416 if (ioc_flags & XFS_IOC_ATTR_REPLACE)
417 return XFS_ATTRUPDATE_REPLACE;
418 return XFS_ATTRUPDATE_UPSERT;
422 xfs_ioc_attr_list(
423 struct xfs_inode *dp,
424 void __user *ubuf,
425 size_t bufsize,
426 int flags,
427 struct xfs_attrlist_cursor __user *ucursor)
429 struct xfs_attr_list_context context = { };
430 struct xfs_attrlist *alist;
431 void *buffer;
432 int error;
434 if (bufsize < sizeof(struct xfs_attrlist) ||
435 bufsize > XFS_XATTR_LIST_MAX)
436 return -EINVAL;
439 * Reject flags, only allow namespaces.
441 if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
442 return -EINVAL;
443 if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
444 return -EINVAL;
447 * Validate the cursor.
449 if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
450 return -EFAULT;
451 if (context.cursor.pad1 || context.cursor.pad2)
452 return -EINVAL;
453 if (!context.cursor.initted &&
454 (context.cursor.hashval || context.cursor.blkno ||
455 context.cursor.offset))
456 return -EINVAL;
458 buffer = kvzalloc(bufsize, GFP_KERNEL);
459 if (!buffer)
460 return -ENOMEM;
463 * Initialize the output buffer.
465 context.dp = dp;
466 context.resynch = 1;
467 context.attr_filter = xfs_attr_filter(flags);
468 context.buffer = buffer;
469 context.bufsize = round_down(bufsize, sizeof(uint32_t));
470 context.firstu = context.bufsize;
471 context.put_listent = xfs_ioc_attr_put_listent;
473 alist = context.buffer;
474 alist->al_count = 0;
475 alist->al_more = 0;
476 alist->al_offset[0] = context.bufsize;
478 error = xfs_attr_list(&context);
479 if (error)
480 goto out_free;
482 if (copy_to_user(ubuf, buffer, bufsize) ||
483 copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
484 error = -EFAULT;
485 out_free:
486 kvfree(buffer);
487 return error;
491 xfs_attrlist_by_handle(
492 struct file *parfilp,
493 struct xfs_fsop_attrlist_handlereq __user *p)
495 struct xfs_fsop_attrlist_handlereq al_hreq;
496 struct dentry *dentry;
497 int error = -ENOMEM;
499 if (!capable(CAP_SYS_ADMIN))
500 return -EPERM;
501 if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
502 return -EFAULT;
504 dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
505 if (IS_ERR(dentry))
506 return PTR_ERR(dentry);
508 error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
509 al_hreq.buflen, al_hreq.flags, &p->pos);
510 dput(dentry);
511 return error;
514 static int
515 xfs_attrmulti_attr_get(
516 struct inode *inode,
517 unsigned char *name,
518 unsigned char __user *ubuf,
519 uint32_t *len,
520 uint32_t flags)
522 struct xfs_da_args args = {
523 .dp = XFS_I(inode),
524 .attr_filter = xfs_attr_filter(flags),
525 .name = name,
526 .namelen = strlen(name),
527 .valuelen = *len,
529 int error;
531 if (*len > XFS_XATTR_SIZE_MAX)
532 return -EINVAL;
534 error = xfs_attr_get(&args);
535 if (error)
536 goto out_kfree;
538 *len = args.valuelen;
539 if (copy_to_user(ubuf, args.value, args.valuelen))
540 error = -EFAULT;
542 out_kfree:
543 kvfree(args.value);
544 return error;
547 static int
548 xfs_attrmulti_attr_set(
549 struct inode *inode,
550 unsigned char *name,
551 const unsigned char __user *ubuf,
552 uint32_t len,
553 uint32_t flags)
555 struct xfs_da_args args = {
556 .dp = XFS_I(inode),
557 .attr_filter = xfs_attr_filter(flags),
558 .name = name,
559 .namelen = strlen(name),
561 int error;
563 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
564 return -EPERM;
566 if (ubuf) {
567 if (len > XFS_XATTR_SIZE_MAX)
568 return -EINVAL;
569 args.value = memdup_user(ubuf, len);
570 if (IS_ERR(args.value))
571 return PTR_ERR(args.value);
572 args.valuelen = len;
575 error = xfs_attr_change(&args, xfs_xattr_flags(flags, args.value));
576 if (!error && (flags & XFS_IOC_ATTR_ROOT))
577 xfs_forget_acl(inode, name);
578 kfree(args.value);
579 return error;
583 xfs_ioc_attrmulti_one(
584 struct file *parfilp,
585 struct inode *inode,
586 uint32_t opcode,
587 void __user *uname,
588 void __user *value,
589 uint32_t *len,
590 uint32_t flags)
592 unsigned char *name;
593 int error;
595 if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
596 return -EINVAL;
598 name = strndup_user(uname, MAXNAMELEN);
599 if (IS_ERR(name))
600 return PTR_ERR(name);
602 switch (opcode) {
603 case ATTR_OP_GET:
604 error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
605 break;
606 case ATTR_OP_REMOVE:
607 value = NULL;
608 *len = 0;
609 fallthrough;
610 case ATTR_OP_SET:
611 error = mnt_want_write_file(parfilp);
612 if (error)
613 break;
614 error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
615 mnt_drop_write_file(parfilp);
616 break;
617 default:
618 error = -EINVAL;
619 break;
622 kfree(name);
623 return error;
627 xfs_attrmulti_by_handle(
628 struct file *parfilp,
629 void __user *arg)
631 int error;
632 xfs_attr_multiop_t *ops;
633 xfs_fsop_attrmulti_handlereq_t am_hreq;
634 struct dentry *dentry;
635 unsigned int i, size;
637 if (!capable(CAP_SYS_ADMIN))
638 return -EPERM;
639 if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
640 return -EFAULT;
642 /* overflow check */
643 if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
644 return -E2BIG;
646 dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
647 if (IS_ERR(dentry))
648 return PTR_ERR(dentry);
650 error = -E2BIG;
651 size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
652 if (!size || size > 16 * PAGE_SIZE)
653 goto out_dput;
655 ops = memdup_user(am_hreq.ops, size);
656 if (IS_ERR(ops)) {
657 error = PTR_ERR(ops);
658 goto out_dput;
661 error = 0;
662 for (i = 0; i < am_hreq.opcount; i++) {
663 ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
664 d_inode(dentry), ops[i].am_opcode,
665 ops[i].am_attrname, ops[i].am_attrvalue,
666 &ops[i].am_length, ops[i].am_flags);
669 if (copy_to_user(am_hreq.ops, ops, size))
670 error = -EFAULT;
672 kfree(ops);
673 out_dput:
674 dput(dentry);
675 return error;
678 struct xfs_getparents_ctx {
679 struct xfs_attr_list_context context;
680 struct xfs_getparents_by_handle gph;
682 /* File to target */
683 struct xfs_inode *ip;
685 /* Internal buffer where we format records */
686 void *krecords;
688 /* Last record filled out */
689 struct xfs_getparents_rec *lastrec;
691 unsigned int count;
694 static inline unsigned int
695 xfs_getparents_rec_sizeof(
696 unsigned int namelen)
698 return round_up(sizeof(struct xfs_getparents_rec) + namelen + 1,
699 sizeof(uint64_t));
702 static void
703 xfs_getparents_put_listent(
704 struct xfs_attr_list_context *context,
705 int flags,
706 unsigned char *name,
707 int namelen,
708 void *value,
709 int valuelen)
711 struct xfs_getparents_ctx *gpx =
712 container_of(context, struct xfs_getparents_ctx, context);
713 struct xfs_inode *ip = context->dp;
714 struct xfs_mount *mp = ip->i_mount;
715 struct xfs_getparents *gp = &gpx->gph.gph_request;
716 struct xfs_getparents_rec *gpr = gpx->krecords + context->firstu;
717 unsigned short reclen =
718 xfs_getparents_rec_sizeof(namelen);
719 xfs_ino_t ino;
720 uint32_t gen;
721 int error;
723 if (!(flags & XFS_ATTR_PARENT))
724 return;
726 error = xfs_parent_from_attr(mp, flags, name, namelen, value, valuelen,
727 &ino, &gen);
728 if (error) {
729 xfs_inode_mark_sick(ip, XFS_SICK_INO_PARENT);
730 context->seen_enough = -EFSCORRUPTED;
731 return;
735 * We found a parent pointer, but we've filled up the buffer. Signal
736 * to the caller that we did /not/ reach the end of the parent pointer
737 * recordset.
739 if (context->firstu > context->bufsize - reclen) {
740 context->seen_enough = 1;
741 return;
744 /* Format the parent pointer directly into the caller buffer. */
745 gpr->gpr_reclen = reclen;
746 xfs_filehandle_init(mp, ino, gen, &gpr->gpr_parent);
747 memcpy(gpr->gpr_name, name, namelen);
748 gpr->gpr_name[namelen] = 0;
750 trace_xfs_getparents_put_listent(ip, gp, context, gpr);
752 context->firstu += reclen;
753 gpx->count++;
754 gpx->lastrec = gpr;
757 /* Expand the last record to fill the rest of the caller's buffer. */
758 static inline void
759 xfs_getparents_expand_lastrec(
760 struct xfs_getparents_ctx *gpx)
762 struct xfs_getparents *gp = &gpx->gph.gph_request;
763 struct xfs_getparents_rec *gpr = gpx->lastrec;
765 if (!gpx->lastrec)
766 gpr = gpx->krecords;
768 gpr->gpr_reclen = gp->gp_bufsize - ((void *)gpr - gpx->krecords);
770 trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr);
773 /* Retrieve the parent pointers for a given inode. */
774 STATIC int
775 xfs_getparents(
776 struct xfs_getparents_ctx *gpx)
778 struct xfs_getparents *gp = &gpx->gph.gph_request;
779 struct xfs_inode *ip = gpx->ip;
780 struct xfs_mount *mp = ip->i_mount;
781 size_t bufsize;
782 int error;
784 /* Check size of buffer requested by user */
785 if (gp->gp_bufsize > XFS_XATTR_LIST_MAX)
786 return -ENOMEM;
787 if (gp->gp_bufsize < xfs_getparents_rec_sizeof(1))
788 return -EINVAL;
790 if (gp->gp_iflags & ~XFS_GETPARENTS_IFLAGS_ALL)
791 return -EINVAL;
792 if (gp->gp_reserved)
793 return -EINVAL;
795 bufsize = round_down(gp->gp_bufsize, sizeof(uint64_t));
796 gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
797 if (!gpx->krecords) {
798 bufsize = min(bufsize, PAGE_SIZE);
799 gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
800 if (!gpx->krecords)
801 return -ENOMEM;
804 gpx->context.dp = ip;
805 gpx->context.resynch = 1;
806 gpx->context.put_listent = xfs_getparents_put_listent;
807 gpx->context.bufsize = bufsize;
808 /* firstu is used to track the bytes filled in the buffer */
809 gpx->context.firstu = 0;
811 /* Copy the cursor provided by caller */
812 memcpy(&gpx->context.cursor, &gp->gp_cursor,
813 sizeof(struct xfs_attrlist_cursor));
814 gpx->count = 0;
815 gp->gp_oflags = 0;
817 trace_xfs_getparents_begin(ip, gp, &gpx->context.cursor);
819 error = xfs_attr_list(&gpx->context);
820 if (error)
821 goto out_free_buf;
822 if (gpx->context.seen_enough < 0) {
823 error = gpx->context.seen_enough;
824 goto out_free_buf;
826 xfs_getparents_expand_lastrec(gpx);
828 /* Update the caller with the current cursor position */
829 memcpy(&gp->gp_cursor, &gpx->context.cursor,
830 sizeof(struct xfs_attrlist_cursor));
832 /* Is this the root directory? */
833 if (ip->i_ino == mp->m_sb.sb_rootino)
834 gp->gp_oflags |= XFS_GETPARENTS_OFLAG_ROOT;
836 if (gpx->context.seen_enough == 0) {
838 * If we did not run out of buffer space, then we reached the
839 * end of the pptr recordset, so set the DONE flag.
841 gp->gp_oflags |= XFS_GETPARENTS_OFLAG_DONE;
842 } else if (gpx->count == 0) {
844 * If we ran out of buffer space before copying any parent
845 * pointers at all, the caller's buffer was too short. Tell
846 * userspace that, erm, the message is too long.
848 error = -EMSGSIZE;
849 goto out_free_buf;
852 trace_xfs_getparents_end(ip, gp, &gpx->context.cursor);
854 ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize);
856 /* Copy the records to userspace. */
857 if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer),
858 gpx->krecords, gpx->context.firstu))
859 error = -EFAULT;
861 out_free_buf:
862 kvfree(gpx->krecords);
863 gpx->krecords = NULL;
864 return error;
867 /* Retrieve the parents of this file and pass them back to userspace. */
869 xfs_ioc_getparents(
870 struct file *file,
871 struct xfs_getparents __user *ureq)
873 struct xfs_getparents_ctx gpx = {
874 .ip = XFS_I(file_inode(file)),
876 struct xfs_getparents *kreq = &gpx.gph.gph_request;
877 struct xfs_mount *mp = gpx.ip->i_mount;
878 int error;
880 if (!capable(CAP_SYS_ADMIN))
881 return -EPERM;
882 if (!xfs_has_parent(mp))
883 return -EOPNOTSUPP;
884 if (copy_from_user(kreq, ureq, sizeof(*kreq)))
885 return -EFAULT;
887 error = xfs_getparents(&gpx);
888 if (error)
889 return error;
891 if (copy_to_user(ureq, kreq, sizeof(*kreq)))
892 return -EFAULT;
894 return 0;
897 /* Retrieve the parents of this file handle and pass them back to userspace. */
899 xfs_ioc_getparents_by_handle(
900 struct file *file,
901 struct xfs_getparents_by_handle __user *ureq)
903 struct xfs_getparents_ctx gpx = { };
904 struct xfs_inode *ip = XFS_I(file_inode(file));
905 struct xfs_mount *mp = ip->i_mount;
906 struct xfs_getparents_by_handle *kreq = &gpx.gph;
907 struct xfs_handle *handle = &kreq->gph_handle;
908 int error;
910 if (!capable(CAP_SYS_ADMIN))
911 return -EPERM;
912 if (!xfs_has_parent(mp))
913 return -EOPNOTSUPP;
914 if (copy_from_user(kreq, ureq, sizeof(*kreq)))
915 return -EFAULT;
918 * We don't use exportfs_decode_fh because it does too much work here.
919 * If the handle refers to a directory, the exportfs code will walk
920 * upwards through the directory tree to connect the dentries to the
921 * root directory dentry. For GETPARENTS we don't care about that
922 * because we're not actually going to open a file descriptor; we only
923 * want to open an inode and read its parent pointers.
925 * Note that xfs_scrub uses GETPARENTS to log that it will try to fix a
926 * corrupted file's metadata. For this usecase we would really rather
927 * userspace single-step the path reconstruction to avoid loops or
928 * other strange things if the directory tree is corrupt.
930 gpx.ip = xfs_khandle_to_inode(file, handle);
931 if (IS_ERR(gpx.ip))
932 return PTR_ERR(gpx.ip);
934 error = xfs_getparents(&gpx);
935 if (error)
936 goto out_rele;
938 if (copy_to_user(ureq, kreq, sizeof(*kreq)))
939 error = -EFAULT;
941 out_rele:
942 xfs_irele(gpx.ip);
943 return error;