xfs_file.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of version 2 of the GNU General Public License as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it would be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. *
  12. * Further, this software is distributed without any warranty that it is
  13. * free of the rightful claim of any third person regarding infringement
  14. * or the like. Any license provided herein, whether implied or
  15. * otherwise, applies only to this software file. Patent licenses, if
  16. * any, provided herein do not apply to combinations of this program with
  17. * other software, or any other product whatsoever.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write the Free Software Foundation, Inc., 59
  21. * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22. *
  23. * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
  24. * Mountain View, CA 94043, or:
  25. *
  26. * http://www.sgi.com
  27. *
  28. * For further information regarding this notice, see:
  29. *
  30. * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  31. */
  32. #include "xfs.h"
  33. #include "xfs_inum.h"
  34. #include "xfs_log.h"
  35. #include "xfs_sb.h"
  36. #include "xfs_dir.h"
  37. #include "xfs_dir2.h"
  38. #include "xfs_trans.h"
  39. #include "xfs_dmapi.h"
  40. #include "xfs_mount.h"
  41. #include "xfs_bmap_btree.h"
  42. #include "xfs_alloc_btree.h"
  43. #include "xfs_ialloc_btree.h"
  44. #include "xfs_alloc.h"
  45. #include "xfs_btree.h"
  46. #include "xfs_attr_sf.h"
  47. #include "xfs_dir_sf.h"
  48. #include "xfs_dir2_sf.h"
  49. #include "xfs_dinode.h"
  50. #include "xfs_inode.h"
  51. #include "xfs_error.h"
  52. #include "xfs_rw.h"
  53. #include "xfs_ioctl32.h"
  54. #include <linux/dcache.h>
  55. #include <linux/smp_lock.h>
  56. static struct vm_operations_struct linvfs_file_vm_ops;
  57. #ifdef CONFIG_XFS_DMAPI
  58. static struct vm_operations_struct linvfs_dmapi_file_vm_ops;
  59. #endif
  60. STATIC inline ssize_t
  61. __linvfs_read(
  62. struct kiocb *iocb,
  63. char __user *buf,
  64. int ioflags,
  65. size_t count,
  66. loff_t pos)
  67. {
  68. struct iovec iov = {buf, count};
  69. struct file *file = iocb->ki_filp;
  70. vnode_t *vp = LINVFS_GET_VP(file->f_dentry->d_inode);
  71. ssize_t rval;
  72. BUG_ON(iocb->ki_pos != pos);
  73. if (unlikely(file->f_flags & O_DIRECT))
  74. ioflags |= IO_ISDIRECT;
  75. VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
  76. return rval;
  77. }
  78. STATIC ssize_t
  79. linvfs_aio_read(
  80. struct kiocb *iocb,
  81. char __user *buf,
  82. size_t count,
  83. loff_t pos)
  84. {
  85. return __linvfs_read(iocb, buf, IO_ISAIO, count, pos);
  86. }
  87. STATIC ssize_t
  88. linvfs_aio_read_invis(
  89. struct kiocb *iocb,
  90. char __user *buf,
  91. size_t count,
  92. loff_t pos)
  93. {
  94. return __linvfs_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
  95. }
  96. STATIC inline ssize_t
  97. __linvfs_write(
  98. struct kiocb *iocb,
  99. const char __user *buf,
  100. int ioflags,
  101. size_t count,
  102. loff_t pos)
  103. {
  104. struct iovec iov = {(void __user *)buf, count};
  105. struct file *file = iocb->ki_filp;
  106. struct inode *inode = file->f_mapping->host;
  107. vnode_t *vp = LINVFS_GET_VP(inode);
  108. ssize_t rval;
  109. BUG_ON(iocb->ki_pos != pos);
  110. if (unlikely(file->f_flags & O_DIRECT))
  111. ioflags |= IO_ISDIRECT;
  112. VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
  113. return rval;
  114. }
  115. STATIC ssize_t
  116. linvfs_aio_write(
  117. struct kiocb *iocb,
  118. const char __user *buf,
  119. size_t count,
  120. loff_t pos)
  121. {
  122. return __linvfs_write(iocb, buf, IO_ISAIO, count, pos);
  123. }
  124. STATIC ssize_t
  125. linvfs_aio_write_invis(
  126. struct kiocb *iocb,
  127. const char __user *buf,
  128. size_t count,
  129. loff_t pos)
  130. {
  131. return __linvfs_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
  132. }
  133. STATIC inline ssize_t
  134. __linvfs_readv(
  135. struct file *file,
  136. const struct iovec *iov,
  137. int ioflags,
  138. unsigned long nr_segs,
  139. loff_t *ppos)
  140. {
  141. struct inode *inode = file->f_mapping->host;
  142. vnode_t *vp = LINVFS_GET_VP(inode);
  143. struct kiocb kiocb;
  144. ssize_t rval;
  145. init_sync_kiocb(&kiocb, file);
  146. kiocb.ki_pos = *ppos;
  147. if (unlikely(file->f_flags & O_DIRECT))
  148. ioflags |= IO_ISDIRECT;
  149. VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
  150. *ppos = kiocb.ki_pos;
  151. return rval;
  152. }
  153. STATIC ssize_t
  154. linvfs_readv(
  155. struct file *file,
  156. const struct iovec *iov,
  157. unsigned long nr_segs,
  158. loff_t *ppos)
  159. {
  160. return __linvfs_readv(file, iov, 0, nr_segs, ppos);
  161. }
  162. STATIC ssize_t
  163. linvfs_readv_invis(
  164. struct file *file,
  165. const struct iovec *iov,
  166. unsigned long nr_segs,
  167. loff_t *ppos)
  168. {
  169. return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos);
  170. }
  171. STATIC inline ssize_t
  172. __linvfs_writev(
  173. struct file *file,
  174. const struct iovec *iov,
  175. int ioflags,
  176. unsigned long nr_segs,
  177. loff_t *ppos)
  178. {
  179. struct inode *inode = file->f_mapping->host;
  180. vnode_t *vp = LINVFS_GET_VP(inode);
  181. struct kiocb kiocb;
  182. ssize_t rval;
  183. init_sync_kiocb(&kiocb, file);
  184. kiocb.ki_pos = *ppos;
  185. if (unlikely(file->f_flags & O_DIRECT))
  186. ioflags |= IO_ISDIRECT;
  187. VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
  188. *ppos = kiocb.ki_pos;
  189. return rval;
  190. }
  191. STATIC ssize_t
  192. linvfs_writev(
  193. struct file *file,
  194. const struct iovec *iov,
  195. unsigned long nr_segs,
  196. loff_t *ppos)
  197. {
  198. return __linvfs_writev(file, iov, 0, nr_segs, ppos);
  199. }
  200. STATIC ssize_t
  201. linvfs_writev_invis(
  202. struct file *file,
  203. const struct iovec *iov,
  204. unsigned long nr_segs,
  205. loff_t *ppos)
  206. {
  207. return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos);
  208. }
  209. STATIC ssize_t
  210. linvfs_sendfile(
  211. struct file *filp,
  212. loff_t *ppos,
  213. size_t count,
  214. read_actor_t actor,
  215. void *target)
  216. {
  217. vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
  218. ssize_t rval;
  219. VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
  220. return rval;
  221. }
  222. STATIC int
  223. linvfs_open(
  224. struct inode *inode,
  225. struct file *filp)
  226. {
  227. vnode_t *vp = LINVFS_GET_VP(inode);
  228. int error;
  229. if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
  230. return -EFBIG;
  231. ASSERT(vp);
  232. VOP_OPEN(vp, NULL, error);
  233. return -error;
  234. }
  235. STATIC int
  236. linvfs_release(
  237. struct inode *inode,
  238. struct file *filp)
  239. {
  240. vnode_t *vp = LINVFS_GET_VP(inode);
  241. int error = 0;
  242. if (vp)
  243. VOP_RELEASE(vp, error);
  244. return -error;
  245. }
  246. STATIC int
  247. linvfs_fsync(
  248. struct file *filp,
  249. struct dentry *dentry,
  250. int datasync)
  251. {
  252. struct inode *inode = dentry->d_inode;
  253. vnode_t *vp = LINVFS_GET_VP(inode);
  254. int error;
  255. int flags = FSYNC_WAIT;
  256. if (datasync)
  257. flags |= FSYNC_DATA;
  258. ASSERT(vp);
  259. VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
  260. return -error;
  261. }
  262. /*
  263. * linvfs_readdir maps to VOP_READDIR().
  264. * We need to build a uio, cred, ...
  265. */
  266. #define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
  267. STATIC int
  268. linvfs_readdir(
  269. struct file *filp,
  270. void *dirent,
  271. filldir_t filldir)
  272. {
  273. int error = 0;
  274. vnode_t *vp;
  275. uio_t uio;
  276. iovec_t iov;
  277. int eof = 0;
  278. caddr_t read_buf;
  279. int namelen, size = 0;
  280. size_t rlen = PAGE_CACHE_SIZE;
  281. xfs_off_t start_offset, curr_offset;
  282. xfs_dirent_t *dbp = NULL;
  283. vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
  284. ASSERT(vp);
  285. /* Try fairly hard to get memory */
  286. do {
  287. if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
  288. break;
  289. rlen >>= 1;
  290. } while (rlen >= 1024);
  291. if (read_buf == NULL)
  292. return -ENOMEM;
  293. uio.uio_iov = &iov;
  294. uio.uio_segflg = UIO_SYSSPACE;
  295. curr_offset = filp->f_pos;
  296. if (filp->f_pos != 0x7fffffff)
  297. uio.uio_offset = filp->f_pos;
  298. else
  299. uio.uio_offset = 0xffffffff;
  300. while (!eof) {
  301. uio.uio_resid = iov.iov_len = rlen;
  302. iov.iov_base = read_buf;
  303. uio.uio_iovcnt = 1;
  304. start_offset = uio.uio_offset;
  305. VOP_READDIR(vp, &uio, NULL, &eof, error);
  306. if ((uio.uio_offset == start_offset) || error) {
  307. size = 0;
  308. break;
  309. }
  310. size = rlen - uio.uio_resid;
  311. dbp = (xfs_dirent_t *)read_buf;
  312. while (size > 0) {
  313. namelen = strlen(dbp->d_name);
  314. if (filldir(dirent, dbp->d_name, namelen,
  315. (loff_t) curr_offset & 0x7fffffff,
  316. (ino_t) dbp->d_ino,
  317. DT_UNKNOWN)) {
  318. goto done;
  319. }
  320. size -= dbp->d_reclen;
  321. curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
  322. dbp = nextdp(dbp);
  323. }
  324. }
  325. done:
  326. if (!error) {
  327. if (size == 0)
  328. filp->f_pos = uio.uio_offset & 0x7fffffff;
  329. else if (dbp)
  330. filp->f_pos = curr_offset;
  331. }
  332. kfree(read_buf);
  333. return -error;
  334. }
  335. #ifdef CONFIG_XFS_DMAPI
  336. STATIC void
  337. linvfs_mmap_close(
  338. struct vm_area_struct *vma)
  339. {
  340. xfs_dm_mm_put(vma);
  341. }
  342. #endif /* CONFIG_XFS_DMAPI */
  343. STATIC int
  344. linvfs_file_mmap(
  345. struct file *filp,
  346. struct vm_area_struct *vma)
  347. {
  348. struct inode *ip = filp->f_dentry->d_inode;
  349. vnode_t *vp = LINVFS_GET_VP(ip);
  350. vattr_t va = { .va_mask = XFS_AT_UPDATIME };
  351. int error;
  352. vma->vm_ops = &linvfs_file_vm_ops;
  353. if (vp->v_vfsp->vfs_flag & VFS_DMI) {
  354. xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
  355. error = -XFS_SEND_MMAP(mp, vma, 0);
  356. if (error)
  357. return error;
  358. #ifdef CONFIG_XFS_DMAPI
  359. vma->vm_ops = &linvfs_dmapi_file_vm_ops;
  360. #endif
  361. }
  362. VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
  363. if (!error)
  364. vn_revalidate(vp); /* update Linux inode flags */
  365. return 0;
  366. }
  367. STATIC long
  368. linvfs_ioctl(
  369. struct file *filp,
  370. unsigned int cmd,
  371. unsigned long arg)
  372. {
  373. int error;
  374. struct inode *inode = filp->f_dentry->d_inode;
  375. vnode_t *vp = LINVFS_GET_VP(inode);
  376. VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
  377. VMODIFY(vp);
  378. /* NOTE: some of the ioctl's return positive #'s as a
  379. * byte count indicating success, such as
  380. * readlink_by_handle. So we don't "sign flip"
  381. * like most other routines. This means true
  382. * errors need to be returned as a negative value.
  383. */
  384. return error;
  385. }
  386. STATIC long
  387. linvfs_ioctl_invis(
  388. struct file *filp,
  389. unsigned int cmd,
  390. unsigned long arg)
  391. {
  392. int error;
  393. struct inode *inode = filp->f_dentry->d_inode;
  394. vnode_t *vp = LINVFS_GET_VP(inode);
  395. ASSERT(vp);
  396. VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
  397. VMODIFY(vp);
  398. /* NOTE: some of the ioctl's return positive #'s as a
  399. * byte count indicating success, such as
  400. * readlink_by_handle. So we don't "sign flip"
  401. * like most other routines. This means true
  402. * errors need to be returned as a negative value.
  403. */
  404. return error;
  405. }
  406. #ifdef HAVE_VMOP_MPROTECT
  407. STATIC int
  408. linvfs_mprotect(
  409. struct vm_area_struct *vma,
  410. unsigned int newflags)
  411. {
  412. vnode_t *vp = LINVFS_GET_VP(vma->vm_file->f_dentry->d_inode);
  413. int error = 0;
  414. if (vp->v_vfsp->vfs_flag & VFS_DMI) {
  415. if ((vma->vm_flags & VM_MAYSHARE) &&
  416. (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
  417. xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
  418. error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
  419. }
  420. }
  421. return error;
  422. }
  423. #endif /* HAVE_VMOP_MPROTECT */
  424. #ifdef HAVE_FOP_OPEN_EXEC
  425. /* If the user is attempting to execute a file that is offline then
  426. * we have to trigger a DMAPI READ event before the file is marked as busy
  427. * otherwise the invisible I/O will not be able to write to the file to bring
  428. * it back online.
  429. */
  430. STATIC int
  431. linvfs_open_exec(
  432. struct inode *inode)
  433. {
  434. vnode_t *vp = LINVFS_GET_VP(inode);
  435. xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
  436. int error = 0;
  437. bhv_desc_t *bdp;
  438. xfs_inode_t *ip;
  439. if (vp->v_vfsp->vfs_flag & VFS_DMI) {
  440. bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
  441. if (!bdp) {
  442. error = -EINVAL;
  443. goto open_exec_out;
  444. }
  445. ip = XFS_BHVTOI(bdp);
  446. if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) {
  447. error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
  448. 0, 0, 0, NULL);
  449. }
  450. }
  451. open_exec_out:
  452. return error;
  453. }
  454. #endif /* HAVE_FOP_OPEN_EXEC */
  455. /*
  456. * Temporary workaround to the AIO direct IO write problem.
  457. * This code can go and we can revert to do_sync_write once
  458. * the writepage(s) rework is merged.
  459. */
  460. STATIC ssize_t
  461. linvfs_write(
  462. struct file *filp,
  463. const char __user *buf,
  464. size_t len,
  465. loff_t *ppos)
  466. {
  467. struct kiocb kiocb;
  468. ssize_t ret;
  469. init_sync_kiocb(&kiocb, filp);
  470. kiocb.ki_pos = *ppos;
  471. ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
  472. *ppos = kiocb.ki_pos;
  473. return ret;
  474. }
  475. STATIC ssize_t
  476. linvfs_write_invis(
  477. struct file *filp,
  478. const char __user *buf,
  479. size_t len,
  480. loff_t *ppos)
  481. {
  482. struct kiocb kiocb;
  483. ssize_t ret;
  484. init_sync_kiocb(&kiocb, filp);
  485. kiocb.ki_pos = *ppos;
  486. ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
  487. *ppos = kiocb.ki_pos;
  488. return ret;
  489. }
  490. struct file_operations linvfs_file_operations = {
  491. .llseek = generic_file_llseek,
  492. .read = do_sync_read,
  493. .write = linvfs_write,
  494. .readv = linvfs_readv,
  495. .writev = linvfs_writev,
  496. .aio_read = linvfs_aio_read,
  497. .aio_write = linvfs_aio_write,
  498. .sendfile = linvfs_sendfile,
  499. .unlocked_ioctl = linvfs_ioctl,
  500. #ifdef CONFIG_COMPAT
  501. .compat_ioctl = linvfs_compat_ioctl,
  502. #endif
  503. .mmap = linvfs_file_mmap,
  504. .open = linvfs_open,
  505. .release = linvfs_release,
  506. .fsync = linvfs_fsync,
  507. #ifdef HAVE_FOP_OPEN_EXEC
  508. .open_exec = linvfs_open_exec,
  509. #endif
  510. };
  511. struct file_operations linvfs_invis_file_operations = {
  512. .llseek = generic_file_llseek,
  513. .read = do_sync_read,
  514. .write = linvfs_write_invis,
  515. .readv = linvfs_readv_invis,
  516. .writev = linvfs_writev_invis,
  517. .aio_read = linvfs_aio_read_invis,
  518. .aio_write = linvfs_aio_write_invis,
  519. .sendfile = linvfs_sendfile,
  520. .unlocked_ioctl = linvfs_ioctl_invis,
  521. #ifdef CONFIG_COMPAT
  522. .compat_ioctl = linvfs_compat_invis_ioctl,
  523. #endif
  524. .mmap = linvfs_file_mmap,
  525. .open = linvfs_open,
  526. .release = linvfs_release,
  527. .fsync = linvfs_fsync,
  528. };
  529. struct file_operations linvfs_dir_operations = {
  530. .read = generic_read_dir,
  531. .readdir = linvfs_readdir,
  532. .unlocked_ioctl = linvfs_ioctl,
  533. #ifdef CONFIG_COMPAT
  534. .compat_ioctl = linvfs_compat_ioctl,
  535. #endif
  536. .fsync = linvfs_fsync,
  537. };
  538. static struct vm_operations_struct linvfs_file_vm_ops = {
  539. .nopage = filemap_nopage,
  540. .populate = filemap_populate,
  541. };
  542. #ifdef CONFIG_XFS_DMAPI
  543. static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
  544. .close = linvfs_mmap_close,
  545. .nopage = filemap_nopage,
  546. .populate = filemap_populate,
  547. #ifdef HAVE_VMOP_MPROTECT
  548. .mprotect = linvfs_mprotect,
  549. #endif
  550. };
  551. #endif /* CONFIG_XFS_DMAPI */