Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }