ioctl.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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/mount.h>
  15. #include <linux/time.h>
  16. #include <linux/compat.h>
  17. #include <linux/smp_lock.h>
  18. #include <asm/uaccess.h>
  19. int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
  20. unsigned long arg)
  21. {
  22. struct ext3_inode_info *ei = EXT3_I(inode);
  23. unsigned int flags;
  24. unsigned short rsv_window_size;
  25. ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
  26. switch (cmd) {
  27. case EXT3_IOC_GETFLAGS:
  28. ext3_get_inode_flags(ei);
  29. flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
  30. return put_user(flags, (int __user *) arg);
  31. case EXT3_IOC_SETFLAGS: {
  32. handle_t *handle = NULL;
  33. int err;
  34. struct ext3_iloc iloc;
  35. unsigned int oldflags;
  36. unsigned int jflag;
  37. err = mnt_want_write(filp->f_path.mnt);
  38. if (err)
  39. return err;
  40. if (!is_owner_or_cap(inode)) {
  41. err = -EACCES;
  42. goto flags_out;
  43. }
  44. if (get_user(flags, (int __user *) arg)) {
  45. err = -EFAULT;
  46. goto flags_out;
  47. }
  48. flags = ext3_mask_flags(inode->i_mode, flags);
  49. mutex_lock(&inode->i_mutex);
  50. /* Is it quota file? Do not allow user to mess with it */
  51. if (IS_NOQUOTA(inode)) {
  52. mutex_unlock(&inode->i_mutex);
  53. err = -EPERM;
  54. goto flags_out;
  55. }
  56. oldflags = ei->i_flags;
  57. /* The JOURNAL_DATA flag is modifiable only by root */
  58. jflag = flags & EXT3_JOURNAL_DATA_FL;
  59. /*
  60. * The IMMUTABLE and APPEND_ONLY flags can only be changed by
  61. * the relevant capability.
  62. *
  63. * This test looks nicer. Thanks to Pauline Middelink
  64. */
  65. if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
  66. if (!capable(CAP_LINUX_IMMUTABLE)) {
  67. mutex_unlock(&inode->i_mutex);
  68. err = -EPERM;
  69. goto flags_out;
  70. }
  71. }
  72. /*
  73. * The JOURNAL_DATA flag can only be changed by
  74. * the relevant capability.
  75. */
  76. if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
  77. if (!capable(CAP_SYS_RESOURCE)) {
  78. mutex_unlock(&inode->i_mutex);
  79. err = -EPERM;
  80. goto flags_out;
  81. }
  82. }
  83. handle = ext3_journal_start(inode, 1);
  84. if (IS_ERR(handle)) {
  85. mutex_unlock(&inode->i_mutex);
  86. err = PTR_ERR(handle);
  87. goto flags_out;
  88. }
  89. if (IS_SYNC(inode))
  90. handle->h_sync = 1;
  91. err = ext3_reserve_inode_write(handle, inode, &iloc);
  92. if (err)
  93. goto flags_err;
  94. flags = flags & EXT3_FL_USER_MODIFIABLE;
  95. flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
  96. ei->i_flags = flags;
  97. ext3_set_inode_flags(inode);
  98. inode->i_ctime = CURRENT_TIME_SEC;
  99. err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  100. flags_err:
  101. ext3_journal_stop(handle);
  102. if (err) {
  103. mutex_unlock(&inode->i_mutex);
  104. return err;
  105. }
  106. if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
  107. err = ext3_change_inode_journal_flag(inode, jflag);
  108. mutex_unlock(&inode->i_mutex);
  109. flags_out:
  110. mnt_drop_write(filp->f_path.mnt);
  111. return err;
  112. }
  113. case EXT3_IOC_GETVERSION:
  114. case EXT3_IOC_GETVERSION_OLD:
  115. return put_user(inode->i_generation, (int __user *) arg);
  116. case EXT3_IOC_SETVERSION:
  117. case EXT3_IOC_SETVERSION_OLD: {
  118. handle_t *handle;
  119. struct ext3_iloc iloc;
  120. __u32 generation;
  121. int err;
  122. if (!is_owner_or_cap(inode))
  123. return -EPERM;
  124. err = mnt_want_write(filp->f_path.mnt);
  125. if (err)
  126. return err;
  127. if (get_user(generation, (int __user *) arg)) {
  128. err = -EFAULT;
  129. goto setversion_out;
  130. }
  131. handle = ext3_journal_start(inode, 1);
  132. if (IS_ERR(handle)) {
  133. err = PTR_ERR(handle);
  134. goto setversion_out;
  135. }
  136. err = ext3_reserve_inode_write(handle, inode, &iloc);
  137. if (err == 0) {
  138. inode->i_ctime = CURRENT_TIME_SEC;
  139. inode->i_generation = generation;
  140. err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  141. }
  142. ext3_journal_stop(handle);
  143. setversion_out:
  144. mnt_drop_write(filp->f_path.mnt);
  145. return err;
  146. }
  147. #ifdef CONFIG_JBD_DEBUG
  148. case EXT3_IOC_WAIT_FOR_READONLY:
  149. /*
  150. * This is racy - by the time we're woken up and running,
  151. * the superblock could be released. And the module could
  152. * have been unloaded. So sue me.
  153. *
  154. * Returns 1 if it slept, else zero.
  155. */
  156. {
  157. struct super_block *sb = inode->i_sb;
  158. DECLARE_WAITQUEUE(wait, current);
  159. int ret = 0;
  160. set_current_state(TASK_INTERRUPTIBLE);
  161. add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
  162. if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
  163. schedule();
  164. ret = 1;
  165. }
  166. remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
  167. return ret;
  168. }
  169. #endif
  170. case EXT3_IOC_GETRSVSZ:
  171. if (test_opt(inode->i_sb, RESERVATION)
  172. && S_ISREG(inode->i_mode)
  173. && ei->i_block_alloc_info) {
  174. rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
  175. return put_user(rsv_window_size, (int __user *)arg);
  176. }
  177. return -ENOTTY;
  178. case EXT3_IOC_SETRSVSZ: {
  179. int err;
  180. if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
  181. return -ENOTTY;
  182. err = mnt_want_write(filp->f_path.mnt);
  183. if (err)
  184. return err;
  185. if (!is_owner_or_cap(inode)) {
  186. err = -EACCES;
  187. goto setrsvsz_out;
  188. }
  189. if (get_user(rsv_window_size, (int __user *)arg)) {
  190. err = -EFAULT;
  191. goto setrsvsz_out;
  192. }
  193. if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
  194. rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
  195. /*
  196. * need to allocate reservation structure for this inode
  197. * before set the window size
  198. */
  199. mutex_lock(&ei->truncate_mutex);
  200. if (!ei->i_block_alloc_info)
  201. ext3_init_block_alloc_info(inode);
  202. if (ei->i_block_alloc_info){
  203. struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
  204. rsv->rsv_goal_size = rsv_window_size;
  205. }
  206. mutex_unlock(&ei->truncate_mutex);
  207. setrsvsz_out:
  208. mnt_drop_write(filp->f_path.mnt);
  209. return err;
  210. }
  211. case EXT3_IOC_GROUP_EXTEND: {
  212. ext3_fsblk_t n_blocks_count;
  213. struct super_block *sb = inode->i_sb;
  214. int err, err2;
  215. if (!capable(CAP_SYS_RESOURCE))
  216. return -EPERM;
  217. err = mnt_want_write(filp->f_path.mnt);
  218. if (err)
  219. return err;
  220. if (get_user(n_blocks_count, (__u32 __user *)arg)) {
  221. err = -EFAULT;
  222. goto group_extend_out;
  223. }
  224. err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
  225. journal_lock_updates(EXT3_SB(sb)->s_journal);
  226. err2 = journal_flush(EXT3_SB(sb)->s_journal);
  227. journal_unlock_updates(EXT3_SB(sb)->s_journal);
  228. if (err == 0)
  229. err = err2;
  230. group_extend_out:
  231. mnt_drop_write(filp->f_path.mnt);
  232. return err;
  233. }
  234. case EXT3_IOC_GROUP_ADD: {
  235. struct ext3_new_group_data input;
  236. struct super_block *sb = inode->i_sb;
  237. int err, err2;
  238. if (!capable(CAP_SYS_RESOURCE))
  239. return -EPERM;
  240. err = mnt_want_write(filp->f_path.mnt);
  241. if (err)
  242. return err;
  243. if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
  244. sizeof(input))) {
  245. err = -EFAULT;
  246. goto group_add_out;
  247. }
  248. err = ext3_group_add(sb, &input);
  249. journal_lock_updates(EXT3_SB(sb)->s_journal);
  250. err2 = journal_flush(EXT3_SB(sb)->s_journal);
  251. journal_unlock_updates(EXT3_SB(sb)->s_journal);
  252. if (err == 0)
  253. err = err2;
  254. group_add_out:
  255. mnt_drop_write(filp->f_path.mnt);
  256. return err;
  257. }
  258. default:
  259. return -ENOTTY;
  260. }
  261. }
  262. #ifdef CONFIG_COMPAT
  263. long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  264. {
  265. struct inode *inode = file->f_path.dentry->d_inode;
  266. int ret;
  267. /* These are just misnamed, they actually get/put from/to user an int */
  268. switch (cmd) {
  269. case EXT3_IOC32_GETFLAGS:
  270. cmd = EXT3_IOC_GETFLAGS;
  271. break;
  272. case EXT3_IOC32_SETFLAGS:
  273. cmd = EXT3_IOC_SETFLAGS;
  274. break;
  275. case EXT3_IOC32_GETVERSION:
  276. cmd = EXT3_IOC_GETVERSION;
  277. break;
  278. case EXT3_IOC32_SETVERSION:
  279. cmd = EXT3_IOC_SETVERSION;
  280. break;
  281. case EXT3_IOC32_GROUP_EXTEND:
  282. cmd = EXT3_IOC_GROUP_EXTEND;
  283. break;
  284. case EXT3_IOC32_GETVERSION_OLD:
  285. cmd = EXT3_IOC_GETVERSION_OLD;
  286. break;
  287. case EXT3_IOC32_SETVERSION_OLD:
  288. cmd = EXT3_IOC_SETVERSION_OLD;
  289. break;
  290. #ifdef CONFIG_JBD_DEBUG
  291. case EXT3_IOC32_WAIT_FOR_READONLY:
  292. cmd = EXT3_IOC_WAIT_FOR_READONLY;
  293. break;
  294. #endif
  295. case EXT3_IOC32_GETRSVSZ:
  296. cmd = EXT3_IOC_GETRSVSZ;
  297. break;
  298. case EXT3_IOC32_SETRSVSZ:
  299. cmd = EXT3_IOC_SETRSVSZ;
  300. break;
  301. case EXT3_IOC_GROUP_ADD:
  302. break;
  303. default:
  304. return -ENOIOCTLCMD;
  305. }
  306. lock_kernel();
  307. ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
  308. unlock_kernel();
  309. return ret;
  310. }
  311. #endif