ioctl.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * linux/fs/ext3/ioctl.c
  3. *
  4. * Copyright (C) 1993, 1994, 1995
  5. * Remy Card (card@masi.ibp.fr)
  6. * Laboratoire MASI - Institut Blaise Pascal
  7. * Universite Pierre et Marie Curie (Paris VI)
  8. */
  9. #include <linux/fs.h>
  10. #include <linux/jbd.h>
  11. #include <linux/capability.h>
  12. #include <linux/ext3_fs.h>
  13. #include <linux/ext3_jbd.h>
  14. #include <linux/time.h>
  15. #include <asm/uaccess.h>
  16. int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
  17. unsigned long arg)
  18. {
  19. struct ext3_inode_info *ei = EXT3_I(inode);
  20. unsigned int flags;
  21. unsigned short rsv_window_size;
  22. ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
  23. switch (cmd) {
  24. case EXT3_IOC_GETFLAGS:
  25. flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
  26. return put_user(flags, (int __user *) arg);
  27. case EXT3_IOC_SETFLAGS: {
  28. handle_t *handle = NULL;
  29. int err;
  30. struct ext3_iloc iloc;
  31. unsigned int oldflags;
  32. unsigned int jflag;
  33. if (IS_RDONLY(inode))
  34. return -EROFS;
  35. if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
  36. return -EACCES;
  37. if (get_user(flags, (int __user *) arg))
  38. return -EFAULT;
  39. if (!S_ISDIR(inode->i_mode))
  40. flags &= ~EXT3_DIRSYNC_FL;
  41. mutex_lock(&inode->i_mutex);
  42. oldflags = ei->i_flags;
  43. /* The JOURNAL_DATA flag is modifiable only by root */
  44. jflag = flags & EXT3_JOURNAL_DATA_FL;
  45. /*
  46. * The IMMUTABLE and APPEND_ONLY flags can only be changed by
  47. * the relevant capability.
  48. *
  49. * This test looks nicer. Thanks to Pauline Middelink
  50. */
  51. if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
  52. if (!capable(CAP_LINUX_IMMUTABLE)) {
  53. mutex_unlock(&inode->i_mutex);
  54. return -EPERM;
  55. }
  56. }
  57. /*
  58. * The JOURNAL_DATA flag can only be changed by
  59. * the relevant capability.
  60. */
  61. if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
  62. if (!capable(CAP_SYS_RESOURCE)) {
  63. mutex_unlock(&inode->i_mutex);
  64. return -EPERM;
  65. }
  66. }
  67. handle = ext3_journal_start(inode, 1);
  68. if (IS_ERR(handle)) {
  69. mutex_unlock(&inode->i_mutex);
  70. return PTR_ERR(handle);
  71. }
  72. if (IS_SYNC(inode))
  73. handle->h_sync = 1;
  74. err = ext3_reserve_inode_write(handle, inode, &iloc);
  75. if (err)
  76. goto flags_err;
  77. flags = flags & EXT3_FL_USER_MODIFIABLE;
  78. flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
  79. ei->i_flags = flags;
  80. ext3_set_inode_flags(inode);
  81. inode->i_ctime = CURRENT_TIME_SEC;
  82. err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  83. flags_err:
  84. ext3_journal_stop(handle);
  85. if (err) {
  86. mutex_unlock(&inode->i_mutex);
  87. return err;
  88. }
  89. if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
  90. err = ext3_change_inode_journal_flag(inode, jflag);
  91. mutex_unlock(&inode->i_mutex);
  92. return err;
  93. }
  94. case EXT3_IOC_GETVERSION:
  95. case EXT3_IOC_GETVERSION_OLD:
  96. return put_user(inode->i_generation, (int __user *) arg);
  97. case EXT3_IOC_SETVERSION:
  98. case EXT3_IOC_SETVERSION_OLD: {
  99. handle_t *handle;
  100. struct ext3_iloc iloc;
  101. __u32 generation;
  102. int err;
  103. if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
  104. return -EPERM;
  105. if (IS_RDONLY(inode))
  106. return -EROFS;
  107. if (get_user(generation, (int __user *) arg))
  108. return -EFAULT;
  109. handle = ext3_journal_start(inode, 1);
  110. if (IS_ERR(handle))
  111. return PTR_ERR(handle);
  112. err = ext3_reserve_inode_write(handle, inode, &iloc);
  113. if (err == 0) {
  114. inode->i_ctime = CURRENT_TIME_SEC;
  115. inode->i_generation = generation;
  116. err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  117. }
  118. ext3_journal_stop(handle);
  119. return err;
  120. }
  121. #ifdef CONFIG_JBD_DEBUG
  122. case EXT3_IOC_WAIT_FOR_READONLY:
  123. /*
  124. * This is racy - by the time we're woken up and running,
  125. * the superblock could be released. And the module could
  126. * have been unloaded. So sue me.
  127. *
  128. * Returns 1 if it slept, else zero.
  129. */
  130. {
  131. struct super_block *sb = inode->i_sb;
  132. DECLARE_WAITQUEUE(wait, current);
  133. int ret = 0;
  134. set_current_state(TASK_INTERRUPTIBLE);
  135. add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
  136. if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
  137. schedule();
  138. ret = 1;
  139. }
  140. remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
  141. return ret;
  142. }
  143. #endif
  144. case EXT3_IOC_GETRSVSZ:
  145. if (test_opt(inode->i_sb, RESERVATION)
  146. && S_ISREG(inode->i_mode)
  147. && ei->i_block_alloc_info) {
  148. rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
  149. return put_user(rsv_window_size, (int __user *)arg);
  150. }
  151. return -ENOTTY;
  152. case EXT3_IOC_SETRSVSZ: {
  153. if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
  154. return -ENOTTY;
  155. if (IS_RDONLY(inode))
  156. return -EROFS;
  157. if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
  158. return -EACCES;
  159. if (get_user(rsv_window_size, (int __user *)arg))
  160. return -EFAULT;
  161. if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
  162. rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
  163. /*
  164. * need to allocate reservation structure for this inode
  165. * before set the window size
  166. */
  167. mutex_lock(&ei->truncate_mutex);
  168. if (!ei->i_block_alloc_info)
  169. ext3_init_block_alloc_info(inode);
  170. if (ei->i_block_alloc_info){
  171. struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
  172. rsv->rsv_goal_size = rsv_window_size;
  173. }
  174. mutex_unlock(&ei->truncate_mutex);
  175. return 0;
  176. }
  177. case EXT3_IOC_GROUP_EXTEND: {
  178. ext3_fsblk_t n_blocks_count;
  179. struct super_block *sb = inode->i_sb;
  180. int err;
  181. if (!capable(CAP_SYS_RESOURCE))
  182. return -EPERM;
  183. if (IS_RDONLY(inode))
  184. return -EROFS;
  185. if (get_user(n_blocks_count, (__u32 __user *)arg))
  186. return -EFAULT;
  187. err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
  188. journal_lock_updates(EXT3_SB(sb)->s_journal);
  189. journal_flush(EXT3_SB(sb)->s_journal);
  190. journal_unlock_updates(EXT3_SB(sb)->s_journal);
  191. return err;
  192. }
  193. case EXT3_IOC_GROUP_ADD: {
  194. struct ext3_new_group_data input;
  195. struct super_block *sb = inode->i_sb;
  196. int err;
  197. if (!capable(CAP_SYS_RESOURCE))
  198. return -EPERM;
  199. if (IS_RDONLY(inode))
  200. return -EROFS;
  201. if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
  202. sizeof(input)))
  203. return -EFAULT;
  204. err = ext3_group_add(sb, &input);
  205. journal_lock_updates(EXT3_SB(sb)->s_journal);
  206. journal_flush(EXT3_SB(sb)->s_journal);
  207. journal_unlock_updates(EXT3_SB(sb)->s_journal);
  208. return err;
  209. }
  210. default:
  211. return -ENOTTY;
  212. }
  213. }