ioctl.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  3. */
  4. #include <linux/capability.h>
  5. #include <linux/fs.h>
  6. #include <linux/mount.h>
  7. #include "reiserfs.h"
  8. #include <linux/time.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/pagemap.h>
  11. #include <linux/compat.h>
  12. #include <linux/fileattr.h>
  13. int reiserfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
  14. {
  15. struct inode *inode = d_inode(dentry);
  16. if (!reiserfs_attrs(inode->i_sb))
  17. return -ENOTTY;
  18. fileattr_fill_flags(fa, REISERFS_I(inode)->i_attrs);
  19. return 0;
  20. }
  21. int reiserfs_fileattr_set(struct user_namespace *mnt_userns,
  22. struct dentry *dentry, struct fileattr *fa)
  23. {
  24. struct inode *inode = d_inode(dentry);
  25. unsigned int flags = fa->flags;
  26. int err;
  27. reiserfs_write_lock(inode->i_sb);
  28. err = -ENOTTY;
  29. if (!reiserfs_attrs(inode->i_sb))
  30. goto unlock;
  31. err = -EOPNOTSUPP;
  32. if (fileattr_has_fsx(fa))
  33. goto unlock;
  34. /*
  35. * Is it quota file? Do not allow user to mess with it
  36. */
  37. err = -EPERM;
  38. if (IS_NOQUOTA(inode))
  39. goto unlock;
  40. if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) {
  41. err = reiserfs_unpack(inode);
  42. if (err)
  43. goto unlock;
  44. }
  45. sd_attrs_to_i_attrs(flags, inode);
  46. REISERFS_I(inode)->i_attrs = flags;
  47. inode->i_ctime = current_time(inode);
  48. mark_inode_dirty(inode);
  49. err = 0;
  50. unlock:
  51. reiserfs_write_unlock(inode->i_sb);
  52. return err;
  53. }
  54. /*
  55. * reiserfs_ioctl - handler for ioctl for inode
  56. * supported commands:
  57. * 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
  58. * and prevent packing file (argument arg has t
  59. * be non-zero)
  60. * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
  61. * 3) That's all for a while ...
  62. */
  63. long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  64. {
  65. struct inode *inode = file_inode(filp);
  66. int err = 0;
  67. reiserfs_write_lock(inode->i_sb);
  68. switch (cmd) {
  69. case REISERFS_IOC_UNPACK:
  70. if (S_ISREG(inode->i_mode)) {
  71. if (arg)
  72. err = reiserfs_unpack(inode);
  73. } else
  74. err = -ENOTTY;
  75. break;
  76. /*
  77. * following two cases are taken from fs/ext2/ioctl.c by Remy
  78. * Card ([email protected])
  79. */
  80. case REISERFS_IOC_GETVERSION:
  81. err = put_user(inode->i_generation, (int __user *)arg);
  82. break;
  83. case REISERFS_IOC_SETVERSION:
  84. if (!inode_owner_or_capable(&init_user_ns, inode)) {
  85. err = -EPERM;
  86. break;
  87. }
  88. err = mnt_want_write_file(filp);
  89. if (err)
  90. break;
  91. if (get_user(inode->i_generation, (int __user *)arg)) {
  92. err = -EFAULT;
  93. goto setversion_out;
  94. }
  95. inode->i_ctime = current_time(inode);
  96. mark_inode_dirty(inode);
  97. setversion_out:
  98. mnt_drop_write_file(filp);
  99. break;
  100. default:
  101. err = -ENOTTY;
  102. }
  103. reiserfs_write_unlock(inode->i_sb);
  104. return err;
  105. }
  106. #ifdef CONFIG_COMPAT
  107. long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
  108. unsigned long arg)
  109. {
  110. /*
  111. * These are just misnamed, they actually
  112. * get/put from/to user an int
  113. */
  114. switch (cmd) {
  115. case REISERFS_IOC32_UNPACK:
  116. cmd = REISERFS_IOC_UNPACK;
  117. break;
  118. case REISERFS_IOC32_GETVERSION:
  119. cmd = REISERFS_IOC_GETVERSION;
  120. break;
  121. case REISERFS_IOC32_SETVERSION:
  122. cmd = REISERFS_IOC_SETVERSION;
  123. break;
  124. default:
  125. return -ENOIOCTLCMD;
  126. }
  127. return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
  128. }
  129. #endif
  130. int reiserfs_commit_write(struct file *f, struct page *page,
  131. unsigned from, unsigned to);
  132. /*
  133. * reiserfs_unpack
  134. * Function try to convert tail from direct item into indirect.
  135. * It set up nopack attribute in the REISERFS_I(inode)->nopack
  136. */
  137. int reiserfs_unpack(struct inode *inode)
  138. {
  139. int retval = 0;
  140. int index;
  141. struct page *page;
  142. struct address_space *mapping;
  143. unsigned long write_from;
  144. unsigned long blocksize = inode->i_sb->s_blocksize;
  145. if (inode->i_size == 0) {
  146. REISERFS_I(inode)->i_flags |= i_nopack_mask;
  147. return 0;
  148. }
  149. /* ioctl already done */
  150. if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
  151. return 0;
  152. }
  153. /* we need to make sure nobody is changing the file size beneath us */
  154. {
  155. int depth = reiserfs_write_unlock_nested(inode->i_sb);
  156. inode_lock(inode);
  157. reiserfs_write_lock_nested(inode->i_sb, depth);
  158. }
  159. reiserfs_write_lock(inode->i_sb);
  160. write_from = inode->i_size & (blocksize - 1);
  161. /* if we are on a block boundary, we are already unpacked. */
  162. if (write_from == 0) {
  163. REISERFS_I(inode)->i_flags |= i_nopack_mask;
  164. goto out;
  165. }
  166. /*
  167. * we unpack by finding the page with the tail, and calling
  168. * __reiserfs_write_begin on that page. This will force a
  169. * reiserfs_get_block to unpack the tail for us.
  170. */
  171. index = inode->i_size >> PAGE_SHIFT;
  172. mapping = inode->i_mapping;
  173. page = grab_cache_page(mapping, index);
  174. retval = -ENOMEM;
  175. if (!page) {
  176. goto out;
  177. }
  178. retval = __reiserfs_write_begin(page, write_from, 0);
  179. if (retval)
  180. goto out_unlock;
  181. /* conversion can change page contents, must flush */
  182. flush_dcache_page(page);
  183. retval = reiserfs_commit_write(NULL, page, write_from, write_from);
  184. REISERFS_I(inode)->i_flags |= i_nopack_mask;
  185. out_unlock:
  186. unlock_page(page);
  187. put_page(page);
  188. out:
  189. inode_unlock(inode);
  190. reiserfs_write_unlock(inode->i_sb);
  191. return retval;
  192. }