summaryrefslogtreecommitdiffstats
path: root/fs/ceph/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-10 11:42:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-10 11:42:33 -0400
commit26c5eaa1326e9703effd01e7cc3cc0d4ad4b3c19 (patch)
tree070c518340ae308dce62695a06a118a1df78be15 /fs/ceph/file.c
parent1176032cb12bb89ad558a3e57e82f2f25b817eff (diff)
parenteeca958dce0a9231d1969f86196653eb50fcc9b3 (diff)
Merge tag 'ceph-for-4.12-rc1' of git://github.com/ceph/ceph-client
Pull ceph updates from Ilya Dryomov: "The two main items are support for disabling automatic rbd exclusive lock transfers from myself and the long awaited -ENOSPC handling series from Jeff. The former will allow rbd users to take advantage of exclusive lock's built-in blacklist/break-lock functionality while staying in control of who owns the lock. With the latter in place, we will abort filesystem writes on -ENOSPC instead of having them block indefinitely. Beyond that we've got the usual pile of filesystem fixes from Zheng, some refcount_t conversion patches from Elena and a patch for an ancient open() flags handling bug from Alexander" * tag 'ceph-for-4.12-rc1' of git://github.com/ceph/ceph-client: (31 commits) ceph: fix memory leak in __ceph_setxattr() ceph: fix file open flags on ppc64 ceph: choose readdir frag based on previous readdir reply rbd: exclusive map option rbd: return ResponseMessage result from rbd_handle_request_lock() rbd: kill rbd_is_lock_supported() rbd: support updating the lock cookie without releasing the lock rbd: store lock cookie rbd: ignore unlock errors rbd: fix error handling around rbd_init_disk() rbd: move rbd_unregister_watch() call into rbd_dev_image_release() rbd: move rbd_dev_destroy() call out of rbd_dev_image_release() ceph: when seeing write errors on an inode, switch to sync writes Revert "ceph: SetPageError() for writeback pages if writepages fails" ceph: handle epoch barriers in cap messages libceph: add an epoch_barrier field to struct ceph_osd_client libceph: abort already submitted but abortable requests when map or pool goes full libceph: allow requests to return immediately on full conditions if caller wishes libceph: remove req->r_replay_version ceph: make seeky readdir more efficient ...
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r--fs/ceph/file.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 18c045e2ead6..3fdde0b283c9 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -13,6 +13,38 @@
13#include "mds_client.h" 13#include "mds_client.h"
14#include "cache.h" 14#include "cache.h"
15 15
16static __le32 ceph_flags_sys2wire(u32 flags)
17{
18 u32 wire_flags = 0;
19
20 switch (flags & O_ACCMODE) {
21 case O_RDONLY:
22 wire_flags |= CEPH_O_RDONLY;
23 break;
24 case O_WRONLY:
25 wire_flags |= CEPH_O_WRONLY;
26 break;
27 case O_RDWR:
28 wire_flags |= CEPH_O_RDWR;
29 break;
30 }
31
32#define ceph_sys2wire(a) if (flags & a) { wire_flags |= CEPH_##a; flags &= ~a; }
33
34 ceph_sys2wire(O_CREAT);
35 ceph_sys2wire(O_EXCL);
36 ceph_sys2wire(O_TRUNC);
37 ceph_sys2wire(O_DIRECTORY);
38 ceph_sys2wire(O_NOFOLLOW);
39
40#undef ceph_sys2wire
41
42 if (flags)
43 dout("unused open flags: %x", flags);
44
45 return cpu_to_le32(wire_flags);
46}
47
16/* 48/*
17 * Ceph file operations 49 * Ceph file operations
18 * 50 *
@@ -120,7 +152,7 @@ prepare_open_request(struct super_block *sb, int flags, int create_mode)
120 if (IS_ERR(req)) 152 if (IS_ERR(req))
121 goto out; 153 goto out;
122 req->r_fmode = ceph_flags_to_mode(flags); 154 req->r_fmode = ceph_flags_to_mode(flags);
123 req->r_args.open.flags = cpu_to_le32(flags); 155 req->r_args.open.flags = ceph_flags_sys2wire(flags);
124 req->r_args.open.mode = cpu_to_le32(create_mode); 156 req->r_args.open.mode = cpu_to_le32(create_mode);
125out: 157out:
126 return req; 158 return req;
@@ -189,7 +221,7 @@ int ceph_renew_caps(struct inode *inode)
189 spin_lock(&ci->i_ceph_lock); 221 spin_lock(&ci->i_ceph_lock);
190 wanted = __ceph_caps_file_wanted(ci); 222 wanted = __ceph_caps_file_wanted(ci);
191 if (__ceph_is_any_real_caps(ci) && 223 if (__ceph_is_any_real_caps(ci) &&
192 (!(wanted & CEPH_CAP_ANY_WR) == 0 || ci->i_auth_cap)) { 224 (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
193 int issued = __ceph_caps_issued(ci, NULL); 225 int issued = __ceph_caps_issued(ci, NULL);
194 spin_unlock(&ci->i_ceph_lock); 226 spin_unlock(&ci->i_ceph_lock);
195 dout("renew caps %p want %s issued %s updating mds_wanted\n", 227 dout("renew caps %p want %s issued %s updating mds_wanted\n",
@@ -778,6 +810,7 @@ static void ceph_aio_retry_work(struct work_struct *work)
778 req->r_callback = ceph_aio_complete_req; 810 req->r_callback = ceph_aio_complete_req;
779 req->r_inode = inode; 811 req->r_inode = inode;
780 req->r_priv = aio_req; 812 req->r_priv = aio_req;
813 req->r_abort_on_full = true;
781 814
782 ret = ceph_osdc_start_request(req->r_osdc, req, false); 815 ret = ceph_osdc_start_request(req->r_osdc, req, false);
783out: 816out:
@@ -1085,19 +1118,22 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
1085 1118
1086out: 1119out:
1087 ceph_osdc_put_request(req); 1120 ceph_osdc_put_request(req);
1088 if (ret == 0) { 1121 if (ret != 0) {
1089 pos += len; 1122 ceph_set_error_write(ci);
1090 written += len;
1091
1092 if (pos > i_size_read(inode)) {
1093 check_caps = ceph_inode_set_size(inode, pos);
1094 if (check_caps)
1095 ceph_check_caps(ceph_inode(inode),
1096 CHECK_CAPS_AUTHONLY,
1097 NULL);
1098 }
1099 } else
1100 break; 1123 break;
1124 }
1125
1126 ceph_clear_error_write(ci);
1127 pos += len;
1128 written += len;
1129 if (pos > i_size_read(inode)) {
1130 check_caps = ceph_inode_set_size(inode, pos);
1131 if (check_caps)
1132 ceph_check_caps(ceph_inode(inode),
1133 CHECK_CAPS_AUTHONLY,
1134 NULL);
1135 }
1136
1101 } 1137 }
1102 1138
1103 if (ret != -EOLDSNAPC && written > 0) { 1139 if (ret != -EOLDSNAPC && written > 0) {
@@ -1303,6 +1339,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
1303 } 1339 }
1304 1340
1305retry_snap: 1341retry_snap:
1342 /* FIXME: not complete since it doesn't account for being at quota */
1306 if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) { 1343 if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
1307 err = -ENOSPC; 1344 err = -ENOSPC;
1308 goto out; 1345 goto out;
@@ -1324,7 +1361,8 @@ retry_snap:
1324 inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); 1361 inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
1325 1362
1326 if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || 1363 if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
1327 (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) { 1364 (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
1365 (ci->i_ceph_flags & CEPH_I_ERROR_WRITE)) {
1328 struct ceph_snap_context *snapc; 1366 struct ceph_snap_context *snapc;
1329 struct iov_iter data; 1367 struct iov_iter data;
1330 inode_unlock(inode); 1368 inode_unlock(inode);