ioctl.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/fs/jfs/ioctl.c
  4. *
  5. * Copyright (C) 2006 Herbert Poetzl
  6. * adapted from Remy Card's ext2/ioctl.c
  7. */
  8. #include <linux/fs.h>
  9. #include <linux/ctype.h>
  10. #include <linux/capability.h>
  11. #include <linux/mount.h>
  12. #include <linux/time.h>
  13. #include <linux/sched.h>
  14. #include <linux/blkdev.h>
  15. #include <asm/current.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/fileattr.h>
  18. #include "jfs_filsys.h"
  19. #include "jfs_debug.h"
  20. #include "jfs_incore.h"
  21. #include "jfs_dinode.h"
  22. #include "jfs_inode.h"
  23. #include "jfs_dmap.h"
  24. #include "jfs_discard.h"
  25. static struct {
  26. long jfs_flag;
  27. long ext2_flag;
  28. } jfs_map[] = {
  29. {JFS_NOATIME_FL, FS_NOATIME_FL},
  30. {JFS_DIRSYNC_FL, FS_DIRSYNC_FL},
  31. {JFS_SYNC_FL, FS_SYNC_FL},
  32. {JFS_SECRM_FL, FS_SECRM_FL},
  33. {JFS_UNRM_FL, FS_UNRM_FL},
  34. {JFS_APPEND_FL, FS_APPEND_FL},
  35. {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL},
  36. {0, 0},
  37. };
  38. static long jfs_map_ext2(unsigned long flags, int from)
  39. {
  40. int index=0;
  41. long mapped=0;
  42. while (jfs_map[index].jfs_flag) {
  43. if (from) {
  44. if (jfs_map[index].ext2_flag & flags)
  45. mapped |= jfs_map[index].jfs_flag;
  46. } else {
  47. if (jfs_map[index].jfs_flag & flags)
  48. mapped |= jfs_map[index].ext2_flag;
  49. }
  50. index++;
  51. }
  52. return mapped;
  53. }
  54. int jfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
  55. {
  56. struct jfs_inode_info *jfs_inode = JFS_IP(d_inode(dentry));
  57. unsigned int flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
  58. if (d_is_special(dentry))
  59. return -ENOTTY;
  60. fileattr_fill_flags(fa, jfs_map_ext2(flags, 0));
  61. return 0;
  62. }
  63. int jfs_fileattr_set(struct mnt_idmap *idmap,
  64. struct dentry *dentry, struct file_kattr *fa)
  65. {
  66. struct inode *inode = d_inode(dentry);
  67. struct jfs_inode_info *jfs_inode = JFS_IP(inode);
  68. unsigned int flags;
  69. if (d_is_special(dentry))
  70. return -ENOTTY;
  71. if (fileattr_has_fsx(fa))
  72. return -EOPNOTSUPP;
  73. flags = jfs_map_ext2(fa->flags, 1);
  74. if (!S_ISDIR(inode->i_mode))
  75. flags &= ~JFS_DIRSYNC_FL;
  76. /* Is it quota file? Do not allow user to mess with it */
  77. if (IS_NOQUOTA(inode))
  78. return -EPERM;
  79. flags = flags & JFS_FL_USER_MODIFIABLE;
  80. flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
  81. jfs_inode->mode2 = flags;
  82. jfs_set_inode_flags(inode);
  83. inode_set_ctime_current(inode);
  84. mark_inode_dirty(inode);
  85. return 0;
  86. }
  87. long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  88. {
  89. struct inode *inode = file_inode(filp);
  90. switch (cmd) {
  91. case FITRIM:
  92. {
  93. struct super_block *sb = inode->i_sb;
  94. struct fstrim_range range;
  95. s64 ret = 0;
  96. if (!capable(CAP_SYS_ADMIN))
  97. return -EPERM;
  98. if (!bdev_max_discard_sectors(sb->s_bdev)) {
  99. jfs_warn("FITRIM not supported on device");
  100. return -EOPNOTSUPP;
  101. }
  102. if (copy_from_user(&range, (struct fstrim_range __user *)arg,
  103. sizeof(range)))
  104. return -EFAULT;
  105. range.minlen = max_t(unsigned int, range.minlen,
  106. bdev_discard_granularity(sb->s_bdev));
  107. ret = jfs_ioc_trim(inode, &range);
  108. if (ret < 0)
  109. return ret;
  110. if (copy_to_user((struct fstrim_range __user *)arg, &range,
  111. sizeof(range)))
  112. return -EFAULT;
  113. return 0;
  114. }
  115. default:
  116. return -ENOTTY;
  117. }
  118. }