^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/ceph/ceph_debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "super.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "mds_client.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/ceph/pagelist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static u64 lock_secret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct ceph_mds_request *req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static inline u64 secure_addr(void *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u64 v = lock_secret ^ (u64)(unsigned long)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Set the most significant bit, so that MDS knows the 'owner'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * is sufficient to identify the owner of lock. (old code uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * both 'owner' and 'pid')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) v |= (1ULL << 63);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void __init ceph_flock_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) get_random_bytes(&lock_secret, sizeof(lock_secret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct ceph_file_info *fi = dst->fl_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct inode *inode = file_inode(dst->fl_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) atomic_inc(&ceph_inode(inode)->i_filelock_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) atomic_inc(&fi->num_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void ceph_fl_release_lock(struct file_lock *fl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ceph_file_info *fi = fl->fl_file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct inode *inode = file_inode(fl->fl_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct ceph_inode_info *ci = ceph_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) atomic_dec(&fi->num_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (atomic_dec_and_test(&ci->i_filelock_ref)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* clear error when all locks are released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ci->i_ceph_flags &= ~CEPH_I_ERROR_FILELOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static const struct file_lock_operations ceph_fl_lock_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .fl_copy_lock = ceph_fl_copy_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .fl_release_private = ceph_fl_release_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Implement fcntl and flock locking functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int cmd, u8 wait, struct file_lock *fl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct ceph_mds_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u64 length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u64 owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (operation == CEPH_MDS_OP_SETFILELOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * increasing i_filelock_ref closes race window between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * handling request reply and adding file_lock struct to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * inode. Otherwise, auth caps may get trimmed in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * window. Caller function will decrease the counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fl->fl_ops = &ceph_fl_lock_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) fl->fl_ops->fl_copy_lock(fl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (operation != CEPH_MDS_OP_SETFILELOCK || cmd == CEPH_LOCK_UNLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) wait = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) req->r_inode = inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ihold(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) req->r_num_caps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* mds requires start and length rather than start and end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (LLONG_MAX == fl->fl_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) length = fl->fl_end - fl->fl_start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) owner = secure_addr(fl->fl_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "start: %llu, length: %llu, wait: %d, type: %d\n", (int)lock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (int)operation, owner, (u64)fl->fl_pid, fl->fl_start, length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) wait, fl->fl_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) req->r_args.filelock_change.rule = lock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) req->r_args.filelock_change.type = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) req->r_args.filelock_change.owner = cpu_to_le64(owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) req->r_args.filelock_change.length = cpu_to_le64(length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) req->r_args.filelock_change.wait = wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) req->r_wait_for_completion = ceph_lock_wait_for_completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) err = ceph_mdsc_do_request(mdsc, inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!err && operation == CEPH_MDS_OP_GETFILELOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) fl->fl_type = F_RDLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fl->fl_type = F_WRLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) fl->fl_type = F_UNLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) le64_to_cpu(req->r_reply_info.filelock_reply->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (length >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fl->fl_end = length -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) fl->fl_end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ceph_mdsc_put_request(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "length: %llu, wait: %d, type: %d, err code %d\n", (int)lock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) (int)operation, (u64)fl->fl_pid, fl->fl_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) length, wait, fl->fl_type, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct ceph_mds_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct ceph_mds_request *intr_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct inode *inode = req->r_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int err, lock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) BUG_ON(req->r_op != CEPH_MDS_OP_SETFILELOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (req->r_args.filelock_change.rule == CEPH_LOCK_FCNTL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) lock_type = CEPH_LOCK_FCNTL_INTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) else if (req->r_args.filelock_change.rule == CEPH_LOCK_FLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) lock_type = CEPH_LOCK_FLOCK_INTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) BUG_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) BUG_ON(req->r_args.filelock_change.type == CEPH_LOCK_UNLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) err = wait_for_completion_interruptible(&req->r_completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dout("ceph_lock_wait_for_completion: request %llu was interrupted\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) req->r_tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mutex_lock(&mdsc->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * ensure we aren't running concurrently with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * ceph_fill_trace or ceph_readdir_prepopulate, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * rely on locks (dir mutex) held by our caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) mutex_lock(&req->r_fill_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) req->r_err = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) mutex_unlock(&req->r_fill_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!req->r_session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) // haven't sent the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mutex_unlock(&mdsc->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) intr_req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETFILELOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) USE_AUTH_MDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (IS_ERR(intr_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return PTR_ERR(intr_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) intr_req->r_inode = inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ihold(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) intr_req->r_num_caps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) intr_req->r_args.filelock_change = req->r_args.filelock_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) intr_req->r_args.filelock_change.rule = lock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) intr_req->r_args.filelock_change.type = CEPH_LOCK_UNLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) err = ceph_mdsc_do_request(mdsc, inode, intr_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ceph_mdsc_put_request(intr_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (err && err != -ERESTARTSYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) wait_for_completion_killable(&req->r_safe_completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int try_unlock_file(struct file *file, struct file_lock *fl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned int orig_flags = fl->fl_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fl->fl_flags |= FL_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) err = locks_lock_file_wait(file, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) fl->fl_flags = orig_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!(orig_flags & FL_EXISTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Attempt to set an fcntl lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * For now, this just goes away to the server. Later it may be more awesome.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct ceph_inode_info *ci = ceph_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u16 op = CEPH_MDS_OP_SETFILELOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u8 wait = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u8 lock_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!(fl->fl_flags & FL_POSIX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -ENOLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* No mandatory locks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -ENOLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dout("ceph_lock, fl_owner: %p\n", fl->fl_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* set wait bit as appropriate, then make command as Ceph expects it*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (IS_GETLK(cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) op = CEPH_MDS_OP_GETFILELOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) else if (IS_SETLKW(cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) wait = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) posix_lock_file(file, fl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (F_RDLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) lock_cmd = CEPH_LOCK_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) else if (F_WRLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) lock_cmd = CEPH_LOCK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) lock_cmd = CEPH_LOCK_UNLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK == fl->fl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) err = try_unlock_file(file, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (err <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dout("mds locked, locking locally\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) err = posix_lock_file(file, fl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* undo! This should only happen if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * the kernel detects local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * deadlock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ceph_lock_message(CEPH_LOCK_FCNTL, op, inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) CEPH_LOCK_UNLOCK, 0, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dout("got %d on posix_lock_file, undid lock\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct ceph_inode_info *ci = ceph_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u8 wait = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u8 lock_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!(fl->fl_flags & FL_FLOCK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -ENOLCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* No mandatory locks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (fl->fl_type & LOCK_MAND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dout("ceph_flock, fl_file: %p\n", fl->fl_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) spin_lock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) spin_unlock(&ci->i_ceph_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (F_UNLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) locks_lock_file_wait(file, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (IS_SETLKW(cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) wait = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (F_RDLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) lock_cmd = CEPH_LOCK_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) else if (F_WRLCK == fl->fl_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) lock_cmd = CEPH_LOCK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) lock_cmd = CEPH_LOCK_UNLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (F_UNLCK == fl->fl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) err = try_unlock_file(file, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) inode, lock_cmd, wait, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (!err && F_UNLCK != fl->fl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err = locks_lock_file_wait(file, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ceph_lock_message(CEPH_LOCK_FLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) CEPH_MDS_OP_SETFILELOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) inode, CEPH_LOCK_UNLOCK, 0, fl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dout("got %d on locks_lock_file_wait, undid lock\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Fills in the passed counter variables, so you can prepare pagelist metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * before calling ceph_encode_locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct file_lock *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct file_lock_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *fcntl_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *flock_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ctx = inode->i_flctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (ctx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) spin_lock(&ctx->flc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) list_for_each_entry(lock, &ctx->flc_posix, fl_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ++(*fcntl_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) list_for_each_entry(lock, &ctx->flc_flock, fl_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ++(*flock_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) spin_unlock(&ctx->flc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dout("counted %d flock locks and %d fcntl locks\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) *flock_count, *fcntl_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Given a pointer to a lock, convert it to a ceph filelock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int lock_to_ceph_filelock(struct file_lock *lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct ceph_filelock *cephlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) cephlock->start = cpu_to_le64(lock->fl_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) cephlock->client = cpu_to_le64(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) cephlock->pid = cpu_to_le64((u64)lock->fl_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) switch (lock->fl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case F_RDLCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) cephlock->type = CEPH_LOCK_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case F_WRLCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) cephlock->type = CEPH_LOCK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) case F_UNLCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) cephlock->type = CEPH_LOCK_UNLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) dout("Have unknown lock type %d\n", lock->fl_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * Encode the flock and fcntl locks for the given inode into the ceph_filelock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * array. Must be called with inode->i_lock already held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * If we encounter more of a specific lock type than expected, return -ENOSPC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int ceph_encode_locks_to_buffer(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct ceph_filelock *flocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int num_fcntl_locks, int num_flock_locks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct file_lock *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct file_lock_context *ctx = inode->i_flctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) int seen_fcntl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int seen_flock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) dout("encoding %d flock and %d fcntl locks\n", num_flock_locks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) num_fcntl_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) spin_lock(&ctx->flc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) list_for_each_entry(lock, &ctx->flc_posix, fl_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ++seen_fcntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (seen_fcntl > num_fcntl_locks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) err = lock_to_ceph_filelock(lock, &flocks[l]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ++l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ++seen_flock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (seen_flock > num_flock_locks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) err = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) err = lock_to_ceph_filelock(lock, &flocks[l]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ++l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) spin_unlock(&ctx->flc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * Copy the encoded flock and fcntl locks into the pagelist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * sequential flock locks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * Returns zero on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct ceph_pagelist *pagelist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int num_fcntl_locks, int num_flock_locks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) __le32 nlocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) nlocks = cpu_to_le32(num_fcntl_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto out_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (num_fcntl_locks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) err = ceph_pagelist_append(pagelist, flocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) num_fcntl_locks * sizeof(*flocks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) goto out_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) nlocks = cpu_to_le32(num_flock_locks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) goto out_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (num_flock_locks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) err = ceph_pagelist_append(pagelist, &flocks[num_fcntl_locks],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) num_flock_locks * sizeof(*flocks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) out_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }