aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/locks.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/ceph/locks.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/ceph/locks.c')
-rw-r--r--fs/ceph/locks.c136
1 files changed, 81 insertions, 55 deletions
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index ff4e753aae92..80576d05d687 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -1,50 +1,78 @@
1#include "ceph_debug.h" 1#include <linux/ceph/ceph_debug.h>
2 2
3#include <linux/file.h> 3#include <linux/file.h>
4#include <linux/namei.h> 4#include <linux/namei.h>
5 5
6#include "super.h" 6#include "super.h"
7#include "mds_client.h" 7#include "mds_client.h"
8#include "pagelist.h" 8#include <linux/ceph/pagelist.h>
9 9
10/** 10/**
11 * Implement fcntl and flock locking functions. 11 * Implement fcntl and flock locking functions.
12 */ 12 */
13static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, 13static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
14 u64 pid, u64 pid_ns, 14 int cmd, u8 wait, struct file_lock *fl)
15 int cmd, u64 start, u64 length, u8 wait)
16{ 15{
17 struct inode *inode = file->f_dentry->d_inode; 16 struct inode *inode = file->f_dentry->d_inode;
18 struct ceph_mds_client *mdsc = 17 struct ceph_mds_client *mdsc =
19 &ceph_sb_to_client(inode->i_sb)->mdsc; 18 ceph_sb_to_client(inode->i_sb)->mdsc;
20 struct ceph_mds_request *req; 19 struct ceph_mds_request *req;
21 int err; 20 int err;
21 u64 length = 0;
22 22
23 req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); 23 req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
24 if (IS_ERR(req)) 24 if (IS_ERR(req))
25 return PTR_ERR(req); 25 return PTR_ERR(req);
26 req->r_inode = igrab(inode); 26 req->r_inode = inode;
27 ihold(inode);
28
29 /* mds requires start and length rather than start and end */
30 if (LLONG_MAX == fl->fl_end)
31 length = 0;
32 else
33 length = fl->fl_end - fl->fl_start + 1;
27 34
28 dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " 35 dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
29 "length: %llu, wait: %d, type`: %d", (int)lock_type, 36 "length: %llu, wait: %d, type: %d", (int)lock_type,
30 (int)operation, pid, start, length, wait, cmd); 37 (int)operation, (u64)fl->fl_pid, fl->fl_start,
38 length, wait, fl->fl_type);
31 39
32 req->r_args.filelock_change.rule = lock_type; 40 req->r_args.filelock_change.rule = lock_type;
33 req->r_args.filelock_change.type = cmd; 41 req->r_args.filelock_change.type = cmd;
34 req->r_args.filelock_change.pid = cpu_to_le64(pid); 42 req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
35 /* This should be adjusted, but I'm not sure if 43 /* This should be adjusted, but I'm not sure if
36 namespaces actually get id numbers*/ 44 namespaces actually get id numbers*/
37 req->r_args.filelock_change.pid_namespace = 45 req->r_args.filelock_change.pid_namespace =
38 cpu_to_le64((u64)pid_ns); 46 cpu_to_le64((u64)(unsigned long)fl->fl_nspid);
39 req->r_args.filelock_change.start = cpu_to_le64(start); 47 req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
40 req->r_args.filelock_change.length = cpu_to_le64(length); 48 req->r_args.filelock_change.length = cpu_to_le64(length);
41 req->r_args.filelock_change.wait = wait; 49 req->r_args.filelock_change.wait = wait;
42 50
43 err = ceph_mdsc_do_request(mdsc, inode, req); 51 err = ceph_mdsc_do_request(mdsc, inode, req);
52
53 if ( operation == CEPH_MDS_OP_GETFILELOCK){
54 fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
55 if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
56 fl->fl_type = F_RDLCK;
57 else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
58 fl->fl_type = F_WRLCK;
59 else
60 fl->fl_type = F_UNLCK;
61
62 fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
63 length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
64 le64_to_cpu(req->r_reply_info.filelock_reply->length);
65 if (length >= 1)
66 fl->fl_end = length -1;
67 else
68 fl->fl_end = 0;
69
70 }
44 ceph_mdsc_put_request(req); 71 ceph_mdsc_put_request(req);
45 dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " 72 dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
46 "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type, 73 "length: %llu, wait: %d, type: %d, err code %d", (int)lock_type,
47 (int)operation, pid, start, length, wait, cmd, err); 74 (int)operation, (u64)fl->fl_pid, fl->fl_start,
75 length, wait, fl->fl_type, err);
48 return err; 76 return err;
49} 77}
50 78
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
54 */ 82 */
55int ceph_lock(struct file *file, int cmd, struct file_lock *fl) 83int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
56{ 84{
57 u64 length;
58 u8 lock_cmd; 85 u8 lock_cmd;
59 int err; 86 int err;
60 u8 wait = 0; 87 u8 wait = 0;
@@ -76,38 +103,32 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
76 else 103 else
77 lock_cmd = CEPH_LOCK_UNLOCK; 104 lock_cmd = CEPH_LOCK_UNLOCK;
78 105
79 if (LLONG_MAX == fl->fl_end) 106 err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl);
80 length = 0;
81 else
82 length = fl->fl_end - fl->fl_start + 1;
83
84 err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
85 (u64)fl->fl_pid,
86 (u64)(unsigned long)fl->fl_nspid,
87 lock_cmd, fl->fl_start,
88 length, wait);
89 if (!err) { 107 if (!err) {
90 dout("mds locked, locking locally"); 108 if ( op != CEPH_MDS_OP_GETFILELOCK ){
91 err = posix_lock_file(file, fl, NULL); 109 dout("mds locked, locking locally");
92 if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { 110 err = posix_lock_file(file, fl, NULL);
93 /* undo! This should only happen if the kernel detects 111 if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
94 * local deadlock. */ 112 /* undo! This should only happen if
95 ceph_lock_message(CEPH_LOCK_FCNTL, op, file, 113 * the kernel detects local
96 (u64)fl->fl_pid, 114 * deadlock. */
97 (u64)(unsigned long)fl->fl_nspid, 115 ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
98 CEPH_LOCK_UNLOCK, fl->fl_start, 116 CEPH_LOCK_UNLOCK, 0, fl);
99 length, 0); 117 dout("got %d on posix_lock_file, undid lock",
100 dout("got %d on posix_lock_file, undid lock", err); 118 err);
119 }
101 } 120 }
102 } else { 121
103 dout("mds returned error code %d", err); 122 } else if (err == -ERESTARTSYS) {
123 dout("undoing lock\n");
124 ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
125 CEPH_LOCK_UNLOCK, 0, fl);
104 } 126 }
105 return err; 127 return err;
106} 128}
107 129
108int ceph_flock(struct file *file, int cmd, struct file_lock *fl) 130int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
109{ 131{
110 u64 length;
111 u8 lock_cmd; 132 u8 lock_cmd;
112 int err; 133 int err;
113 u8 wait = 1; 134 u8 wait = 1;
@@ -127,30 +148,22 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
127 lock_cmd = CEPH_LOCK_EXCL; 148 lock_cmd = CEPH_LOCK_EXCL;
128 else 149 else
129 lock_cmd = CEPH_LOCK_UNLOCK; 150 lock_cmd = CEPH_LOCK_UNLOCK;
130 /* mds requires start and length rather than start and end */
131 if (LLONG_MAX == fl->fl_end)
132 length = 0;
133 else
134 length = fl->fl_end - fl->fl_start + 1;
135 151
136 err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, 152 err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
137 file, (u64)fl->fl_pid, 153 file, lock_cmd, wait, fl);
138 (u64)(unsigned long)fl->fl_nspid,
139 lock_cmd, fl->fl_start,
140 length, wait);
141 if (!err) { 154 if (!err) {
142 err = flock_lock_file_wait(file, fl); 155 err = flock_lock_file_wait(file, fl);
143 if (err) { 156 if (err) {
144 ceph_lock_message(CEPH_LOCK_FLOCK, 157 ceph_lock_message(CEPH_LOCK_FLOCK,
145 CEPH_MDS_OP_SETFILELOCK, 158 CEPH_MDS_OP_SETFILELOCK,
146 file, (u64)fl->fl_pid, 159 file, CEPH_LOCK_UNLOCK, 0, fl);
147 (u64)(unsigned long)fl->fl_nspid,
148 CEPH_LOCK_UNLOCK, fl->fl_start,
149 length, 0);
150 dout("got %d on flock_lock_file_wait, undid lock", err); 160 dout("got %d on flock_lock_file_wait, undid lock", err);
151 } 161 }
152 } else { 162 } else if (err == -ERESTARTSYS) {
153 dout("mds error code %d", err); 163 dout("undoing lock\n");
164 ceph_lock_message(CEPH_LOCK_FLOCK,
165 CEPH_MDS_OP_SETFILELOCK,
166 file, CEPH_LOCK_UNLOCK, 0, fl);
154 } 167 }
155 return err; 168 return err;
156} 169}
@@ -181,8 +194,9 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
181 * Encode the flock and fcntl locks for the given inode into the pagelist. 194 * Encode the flock and fcntl locks for the given inode into the pagelist.
182 * Format is: #fcntl locks, sequential fcntl locks, #flock locks, 195 * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
183 * sequential flock locks. 196 * sequential flock locks.
184 * Must be called with BLK already held, and the lock numbers should have 197 * Must be called with lock_flocks() already held.
185 * been gathered under the same lock holding window. 198 * If we encounter more of a specific lock type than expected,
199 * we return the value 1.
186 */ 200 */
187int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, 201int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
188 int num_fcntl_locks, int num_flock_locks) 202 int num_fcntl_locks, int num_flock_locks)
@@ -190,6 +204,8 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
190 struct file_lock *lock; 204 struct file_lock *lock;
191 struct ceph_filelock cephlock; 205 struct ceph_filelock cephlock;
192 int err = 0; 206 int err = 0;
207 int seen_fcntl = 0;
208 int seen_flock = 0;
193 209
194 dout("encoding %d flock and %d fcntl locks", num_flock_locks, 210 dout("encoding %d flock and %d fcntl locks", num_flock_locks,
195 num_fcntl_locks); 211 num_fcntl_locks);
@@ -198,6 +214,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
198 goto fail; 214 goto fail;
199 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { 215 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
200 if (lock->fl_flags & FL_POSIX) { 216 if (lock->fl_flags & FL_POSIX) {
217 ++seen_fcntl;
218 if (seen_fcntl > num_fcntl_locks) {
219 err = -ENOSPC;
220 goto fail;
221 }
201 err = lock_to_ceph_filelock(lock, &cephlock); 222 err = lock_to_ceph_filelock(lock, &cephlock);
202 if (err) 223 if (err)
203 goto fail; 224 goto fail;
@@ -213,6 +234,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
213 goto fail; 234 goto fail;
214 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { 235 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
215 if (lock->fl_flags & FL_FLOCK) { 236 if (lock->fl_flags & FL_FLOCK) {
237 ++seen_flock;
238 if (seen_flock > num_flock_locks) {
239 err = -ENOSPC;
240 goto fail;
241 }
216 err = lock_to_ceph_filelock(lock, &cephlock); 242 err = lock_to_ceph_filelock(lock, &cephlock);
217 if (err) 243 if (err)
218 goto fail; 244 goto fail;