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 ...
This commit is contained in:
@@ -13,6 +13,38 @@
|
||||
#include "mds_client.h"
|
||||
#include "cache.h"
|
||||
|
||||
static __le32 ceph_flags_sys2wire(u32 flags)
|
||||
{
|
||||
u32 wire_flags = 0;
|
||||
|
||||
switch (flags & O_ACCMODE) {
|
||||
case O_RDONLY:
|
||||
wire_flags |= CEPH_O_RDONLY;
|
||||
break;
|
||||
case O_WRONLY:
|
||||
wire_flags |= CEPH_O_WRONLY;
|
||||
break;
|
||||
case O_RDWR:
|
||||
wire_flags |= CEPH_O_RDWR;
|
||||
break;
|
||||
}
|
||||
|
||||
#define ceph_sys2wire(a) if (flags & a) { wire_flags |= CEPH_##a; flags &= ~a; }
|
||||
|
||||
ceph_sys2wire(O_CREAT);
|
||||
ceph_sys2wire(O_EXCL);
|
||||
ceph_sys2wire(O_TRUNC);
|
||||
ceph_sys2wire(O_DIRECTORY);
|
||||
ceph_sys2wire(O_NOFOLLOW);
|
||||
|
||||
#undef ceph_sys2wire
|
||||
|
||||
if (flags)
|
||||
dout("unused open flags: %x", flags);
|
||||
|
||||
return cpu_to_le32(wire_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ceph file operations
|
||||
*
|
||||
@@ -120,7 +152,7 @@ prepare_open_request(struct super_block *sb, int flags, int create_mode)
|
||||
if (IS_ERR(req))
|
||||
goto out;
|
||||
req->r_fmode = ceph_flags_to_mode(flags);
|
||||
req->r_args.open.flags = cpu_to_le32(flags);
|
||||
req->r_args.open.flags = ceph_flags_sys2wire(flags);
|
||||
req->r_args.open.mode = cpu_to_le32(create_mode);
|
||||
out:
|
||||
return req;
|
||||
@@ -189,7 +221,7 @@ int ceph_renew_caps(struct inode *inode)
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
wanted = __ceph_caps_file_wanted(ci);
|
||||
if (__ceph_is_any_real_caps(ci) &&
|
||||
(!(wanted & CEPH_CAP_ANY_WR) == 0 || ci->i_auth_cap)) {
|
||||
(!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
|
||||
int issued = __ceph_caps_issued(ci, NULL);
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
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)
|
||||
req->r_callback = ceph_aio_complete_req;
|
||||
req->r_inode = inode;
|
||||
req->r_priv = aio_req;
|
||||
req->r_abort_on_full = true;
|
||||
|
||||
ret = ceph_osdc_start_request(req->r_osdc, req, false);
|
||||
out:
|
||||
@@ -1085,19 +1118,22 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
|
||||
|
||||
out:
|
||||
ceph_osdc_put_request(req);
|
||||
if (ret == 0) {
|
||||
pos += len;
|
||||
written += len;
|
||||
|
||||
if (pos > i_size_read(inode)) {
|
||||
check_caps = ceph_inode_set_size(inode, pos);
|
||||
if (check_caps)
|
||||
ceph_check_caps(ceph_inode(inode),
|
||||
CHECK_CAPS_AUTHONLY,
|
||||
NULL);
|
||||
}
|
||||
} else
|
||||
if (ret != 0) {
|
||||
ceph_set_error_write(ci);
|
||||
break;
|
||||
}
|
||||
|
||||
ceph_clear_error_write(ci);
|
||||
pos += len;
|
||||
written += len;
|
||||
if (pos > i_size_read(inode)) {
|
||||
check_caps = ceph_inode_set_size(inode, pos);
|
||||
if (check_caps)
|
||||
ceph_check_caps(ceph_inode(inode),
|
||||
CHECK_CAPS_AUTHONLY,
|
||||
NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ret != -EOLDSNAPC && written > 0) {
|
||||
@@ -1303,6 +1339,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
}
|
||||
|
||||
retry_snap:
|
||||
/* FIXME: not complete since it doesn't account for being at quota */
|
||||
if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
|
||||
err = -ENOSPC;
|
||||
goto out;
|
||||
@@ -1324,7 +1361,8 @@ retry_snap:
|
||||
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
|
||||
|
||||
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
|
||||
(iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
|
||||
(iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
|
||||
(ci->i_ceph_flags & CEPH_I_ERROR_WRITE)) {
|
||||
struct ceph_snap_context *snapc;
|
||||
struct iov_iter data;
|
||||
inode_unlock(inode);
|
||||
|
Reference in New Issue
Block a user