/** * fiemap_fill_next_extent - Fiemap helper function * @fieinfo: Fiemap context passed into ->fiemap * @logical: Extent logical start offset, in bytes * @phys: Extent physical start offset, in bytes * @len: Extent length, in bytes * @flags: FIEMAP_EXTENT flags that describe this extent * * Called from file system ->fiemap callback. Will populate extent * info as passed in via arguments and copy to user memory. On * success, extent count on fieinfo is incremented. * * Returns 0 on success, -errno on error, 1 if this was the last * extent that will fit in user array.
*/ int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical,
u64 phys, u64 len, u32 flags)
{ struct fiemap_extent extent; struct fiemap_extent __user *dest = fieinfo->fi_extents_start;
/* only count the extents */ if (fieinfo->fi_extents_max == 0) {
fieinfo->fi_extents_mapped++; return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
}
if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max) return 1;
/** * fiemap_prep - check validity of requested flags for fiemap * @inode: Inode to operate on * @fieinfo: Fiemap context passed into ->fiemap * @start: Start of the mapped range * @len: Length of the mapped range, can be truncated by this function. * @supported_flags: Set of fiemap flags that the file system understands * * This function must be called from each ->fiemap instance to validate the * fiemap request against the file system parameters. * * Returns 0 on success, or a negative error on failure.
*/ int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 *len, u32 supported_flags)
{
u64 maxbytes = inode->i_sb->s_maxbytes;
u32 incompat_flags; int ret = 0;
if (*len == 0) return -EINVAL; if (start >= maxbytes) return -EFBIG;
/* * Shrink request scope to what the fs can actually handle.
*/ if (*len > maxbytes || (maxbytes - *len) < start)
*len = maxbytes - start;
/* * This provides compatibility with legacy XFS pre-allocation ioctls * which predate the fallocate syscall. * * Only the l_start, l_len and l_whence fields of the 'struct space_resv' * are used here, rest are ignored.
*/ staticint ioctl_preallocate(struct file *filp, int mode, void __user *argp)
{ struct inode *inode = file_inode(filp); struct space_resv sr;
if (copy_from_user(&sr, argp, sizeof(sr))) return -EFAULT;
switch (sr.l_whence) { case SEEK_SET: break; case SEEK_CUR:
sr.l_start += filp->f_pos; break; case SEEK_END:
sr.l_start += i_size_read(inode); break; default: return -EINVAL;
}
/* on ia32 l_start is on a 32-bit boundary */ #ifdefined CONFIG_COMPAT && defined(CONFIG_X86_64) /* just account for different alignment */ staticint compat_ioctl_preallocate(struct file *file, int mode, struct space_resv_32 __user *argp)
{ struct inode *inode = file_inode(file); struct space_resv_32 sr;
if (copy_from_user(&sr, argp, sizeof(sr))) return -EFAULT;
switch (sr.l_whence) { case SEEK_SET: break; case SEEK_CUR:
sr.l_start += file->f_pos; break; case SEEK_END:
sr.l_start += i_size_read(inode); break; default: return -EINVAL;
}
/* * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. * * When you add any new common ioctls to the switches above and below, * please ensure they have compatible arguments in compat mode. * * The LSM mailing list should also be notified of any command additions or * changes, as specific LSMs may be affected.
*/ staticint do_vfs_ioctl(struct file *filp, unsignedint fd, unsignedint cmd, unsignedlong arg)
{ void __user *argp = (void __user *)arg; struct inode *inode = file_inode(filp);
switch (cmd) { case FIOCLEX:
set_close_on_exec(fd, 1); return 0;
case FIONCLEX:
set_close_on_exec(fd, 0); return 0;
case FIONBIO: return ioctl_fionbio(filp, argp);
case FIOASYNC: return ioctl_fioasync(fd, filp, argp);
case FIOQSIZE: if (S_ISDIR(inode->i_mode) ||
(S_ISREG(inode->i_mode) && !IS_ANON_FILE(inode)) ||
S_ISLNK(inode->i_mode)) {
loff_t res = inode_get_bytes(inode); return copy_to_user(argp, &res, sizeof(res)) ?
-EFAULT : 0;
}
return -ENOTTY;
case FIFREEZE: return ioctl_fsfreeze(filp);
case FITHAW: return ioctl_fsthaw(filp);
case FS_IOC_FIEMAP: return ioctl_fiemap(filp, argp);
case FIGETBSZ: /* anon_bdev filesystems may not have a block size */ if (!inode->i_sb->s_blocksize) return -EINVAL;
#ifdef CONFIG_COMPAT /** * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation * @file: The file to operate on. * @cmd: The ioctl command number. * @arg: The argument to the ioctl. * * This is not normally called as a function, but instead set in struct * file_operations as * * .compat_ioctl = compat_ptr_ioctl, * * On most architectures, the compat_ptr_ioctl() just passes all arguments * to the corresponding ->ioctl handler. The exception is arch/s390, where * compat_ptr() clears the top bit of a 32-bit pointer value, so user space * pointers to the second 2GB alias the first 2GB, as is the case for * native 32-bit s390 user space. * * The compat_ptr_ioctl() function must therefore be used only with ioctl * functions that either ignore the argument or pass a pointer to a * compatible data type. * * If any ioctl command handled by fops->unlocked_ioctl passes a plain * integer instead of a pointer, or any of the passed data types * is incompatible between 32-bit and 64-bit architectures, a proper * handler is required instead of compat_ptr_ioctl.
*/ long compat_ptr_ioctl(struct file *file, unsignedint cmd, unsignedlong arg)
{ if (!file->f_op->unlocked_ioctl) return -ENOIOCTLCMD;
error = security_file_ioctl_compat(fd_file(f), cmd, arg); if (error) return error;
switch (cmd) { /* FICLONE takes an int argument, so don't use compat_ptr() */ case FICLONE:
error = ioctl_file_clone(fd_file(f), arg, 0, 0, 0); break;
#ifdefined(CONFIG_X86_64) /* these get messy on amd64 due to alignment differences */ case FS_IOC_RESVSP_32: case FS_IOC_RESVSP64_32:
error = compat_ioctl_preallocate(fd_file(f), 0, compat_ptr(arg)); break; case FS_IOC_UNRESVSP_32: case FS_IOC_UNRESVSP64_32:
error = compat_ioctl_preallocate(fd_file(f), FALLOC_FL_PUNCH_HOLE,
compat_ptr(arg)); break; case FS_IOC_ZERO_RANGE_32:
error = compat_ioctl_preallocate(fd_file(f), FALLOC_FL_ZERO_RANGE,
compat_ptr(arg)); break; #endif
/* * These access 32-bit values anyway so no further handling is * necessary.
*/ case FS_IOC32_GETFLAGS: case FS_IOC32_SETFLAGS:
cmd = (cmd == FS_IOC32_GETFLAGS) ?
FS_IOC_GETFLAGS : FS_IOC_SETFLAGS;
fallthrough; /* * everything else in do_vfs_ioctl() takes either a compatible * pointer argument or no argument -- call it with a modified * argument.
*/ default:
error = do_vfs_ioctl(fd_file(f), fd, cmd,
(unsignedlong)compat_ptr(arg)); if (error != -ENOIOCTLCMD) break;
if (fd_file(f)->f_op->compat_ioctl)
error = fd_file(f)->f_op->compat_ioctl(fd_file(f), cmd, arg); if (error == -ENOIOCTLCMD)
error = -ENOTTY; break;
} return error;
} #endif
Messung V0.5
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.