diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-03-09 11:16:40 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2014-04-05 00:07:11 -0400 |
commit | eb13e832f823f6c110ea53e3067bafe22b87de63 (patch) | |
tree | e7e06eaf5ded86bb0d64b363b1c98c5909cf4847 | |
parent | eb70c0ce4e877c6854c682c0fc009d7875994942 (diff) |
ceph: use fl->fl_file as owner identifier of flock and posix lock
flock and posix lock should use fl->fl_file instead of process ID
as owner identifier. (posix lock uses fl->fl_owner. fl->fl_owner
is usually equal to fl->fl_file, but it also can be a customized
value). The process ID of who holds the lock is just for F_GETLK
fcntl(2).
The fix is rename the 'pid' fields of struct ceph_mds_request_args
and struct ceph_filelock to 'owner', rename 'pid_namespace' fields
to 'pid'. Assign fl->fl_file to the 'owner' field of lock messages.
We also set the most significant bit of the 'owner' field. MDS can
use that bit to distinguish between old and new clients.
The MDS counterpart of this patch modifies the flock code to not
take the 'pid_namespace' into consideration when checking conflict
locks.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r-- | fs/ceph/locks.c | 61 | ||||
-rw-r--r-- | fs/ceph/super.c | 1 | ||||
-rw-r--r-- | fs/ceph/super.h | 1 | ||||
-rw-r--r-- | include/linux/ceph/ceph_fs.h | 4 |
4 files changed, 45 insertions, 22 deletions
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index f91a569a20fb..d94ba0df9f4d 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c | |||
@@ -2,11 +2,31 @@ | |||
2 | 2 | ||
3 | #include <linux/file.h> | 3 | #include <linux/file.h> |
4 | #include <linux/namei.h> | 4 | #include <linux/namei.h> |
5 | #include <linux/random.h> | ||
5 | 6 | ||
6 | #include "super.h" | 7 | #include "super.h" |
7 | #include "mds_client.h" | 8 | #include "mds_client.h" |
8 | #include <linux/ceph/pagelist.h> | 9 | #include <linux/ceph/pagelist.h> |
9 | 10 | ||
11 | static u64 lock_secret; | ||
12 | |||
13 | static inline u64 secure_addr(void *addr) | ||
14 | { | ||
15 | u64 v = lock_secret ^ (u64)(unsigned long)addr; | ||
16 | /* | ||
17 | * Set the most significant bit, so that MDS knows the 'owner' | ||
18 | * is sufficient to identify the owner of lock. (old code uses | ||
19 | * both 'owner' and 'pid') | ||
20 | */ | ||
21 | v |= (1ULL << 63); | ||
22 | return v; | ||
23 | } | ||
24 | |||
25 | void __init ceph_flock_init(void) | ||
26 | { | ||
27 | get_random_bytes(&lock_secret, sizeof(lock_secret)); | ||
28 | } | ||
29 | |||
10 | /** | 30 | /** |
11 | * Implement fcntl and flock locking functions. | 31 | * Implement fcntl and flock locking functions. |
12 | */ | 32 | */ |
@@ -14,11 +34,11 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, | |||
14 | int cmd, u8 wait, struct file_lock *fl) | 34 | int cmd, u8 wait, struct file_lock *fl) |
15 | { | 35 | { |
16 | struct inode *inode = file_inode(file); | 36 | struct inode *inode = file_inode(file); |
17 | struct ceph_mds_client *mdsc = | 37 | struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
18 | ceph_sb_to_client(inode->i_sb)->mdsc; | ||
19 | struct ceph_mds_request *req; | 38 | struct ceph_mds_request *req; |
20 | int err; | 39 | int err; |
21 | u64 length = 0; | 40 | u64 length = 0; |
41 | u64 owner; | ||
22 | 42 | ||
23 | req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); | 43 | req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); |
24 | if (IS_ERR(req)) | 44 | if (IS_ERR(req)) |
@@ -32,25 +52,27 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, | |||
32 | else | 52 | else |
33 | length = fl->fl_end - fl->fl_start + 1; | 53 | length = fl->fl_end - fl->fl_start + 1; |
34 | 54 | ||
35 | dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " | 55 | if (lock_type == CEPH_LOCK_FCNTL) |
36 | "length: %llu, wait: %d, type: %d", (int)lock_type, | 56 | owner = secure_addr(fl->fl_owner); |
37 | (int)operation, (u64)fl->fl_pid, fl->fl_start, | 57 | else |
38 | length, wait, fl->fl_type); | 58 | owner = secure_addr(fl->fl_file); |
59 | |||
60 | dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, " | ||
61 | "start: %llu, length: %llu, wait: %d, type: %d", (int)lock_type, | ||
62 | (int)operation, owner, (u64)fl->fl_pid, fl->fl_start, length, | ||
63 | wait, fl->fl_type); | ||
39 | 64 | ||
40 | req->r_args.filelock_change.rule = lock_type; | 65 | req->r_args.filelock_change.rule = lock_type; |
41 | req->r_args.filelock_change.type = cmd; | 66 | req->r_args.filelock_change.type = cmd; |
67 | req->r_args.filelock_change.owner = cpu_to_le64(owner); | ||
42 | req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid); | 68 | req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid); |
43 | /* This should be adjusted, but I'm not sure if | ||
44 | namespaces actually get id numbers*/ | ||
45 | req->r_args.filelock_change.pid_namespace = | ||
46 | cpu_to_le64((u64)(unsigned long)fl->fl_nspid); | ||
47 | req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start); | 69 | req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start); |
48 | req->r_args.filelock_change.length = cpu_to_le64(length); | 70 | req->r_args.filelock_change.length = cpu_to_le64(length); |
49 | req->r_args.filelock_change.wait = wait; | 71 | req->r_args.filelock_change.wait = wait; |
50 | 72 | ||
51 | err = ceph_mdsc_do_request(mdsc, inode, req); | 73 | err = ceph_mdsc_do_request(mdsc, inode, req); |
52 | 74 | ||
53 | if ( operation == CEPH_MDS_OP_GETFILELOCK){ | 75 | if (operation == CEPH_MDS_OP_GETFILELOCK) { |
54 | fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid); | 76 | 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) | 77 | if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type) |
56 | fl->fl_type = F_RDLCK; | 78 | fl->fl_type = F_RDLCK; |
@@ -93,8 +115,7 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) | |||
93 | if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK) | 115 | if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK) |
94 | return -ENOLCK; | 116 | return -ENOLCK; |
95 | 117 | ||
96 | fl->fl_nspid = get_pid(task_tgid(current)); | 118 | dout("ceph_lock, fl_owner: %p", fl->fl_owner); |
97 | dout("ceph_lock, fl_pid:%d", fl->fl_pid); | ||
98 | 119 | ||
99 | /* set wait bit as appropriate, then make command as Ceph expects it*/ | 120 | /* set wait bit as appropriate, then make command as Ceph expects it*/ |
100 | if (IS_GETLK(cmd)) | 121 | if (IS_GETLK(cmd)) |
@@ -111,7 +132,7 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) | |||
111 | 132 | ||
112 | err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl); | 133 | err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl); |
113 | if (!err) { | 134 | if (!err) { |
114 | if ( op != CEPH_MDS_OP_GETFILELOCK ){ | 135 | if (op != CEPH_MDS_OP_GETFILELOCK) { |
115 | dout("mds locked, locking locally"); | 136 | dout("mds locked, locking locally"); |
116 | err = posix_lock_file(file, fl, NULL); | 137 | err = posix_lock_file(file, fl, NULL); |
117 | if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { | 138 | if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { |
@@ -145,8 +166,7 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) | |||
145 | if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK) | 166 | if (__mandatory_lock(file->f_mapping->host) && fl->fl_type != F_UNLCK) |
146 | return -ENOLCK; | 167 | return -ENOLCK; |
147 | 168 | ||
148 | fl->fl_nspid = get_pid(task_tgid(current)); | 169 | dout("ceph_flock, fl_file: %p", fl->fl_file); |
149 | dout("ceph_flock, fl_pid:%d", fl->fl_pid); | ||
150 | 170 | ||
151 | if (IS_SETLKW(cmd)) | 171 | if (IS_SETLKW(cmd)) |
152 | wait = 1; | 172 | wait = 1; |
@@ -289,13 +309,14 @@ int lock_to_ceph_filelock(struct file_lock *lock, | |||
289 | struct ceph_filelock *cephlock) | 309 | struct ceph_filelock *cephlock) |
290 | { | 310 | { |
291 | int err = 0; | 311 | int err = 0; |
292 | |||
293 | cephlock->start = cpu_to_le64(lock->fl_start); | 312 | cephlock->start = cpu_to_le64(lock->fl_start); |
294 | cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1); | 313 | cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1); |
295 | cephlock->client = cpu_to_le64(0); | 314 | cephlock->client = cpu_to_le64(0); |
296 | cephlock->pid = cpu_to_le64(lock->fl_pid); | 315 | cephlock->pid = cpu_to_le64((u64)lock->fl_pid); |
297 | cephlock->pid_namespace = | 316 | if (lock->fl_flags & FL_POSIX) |
298 | cpu_to_le64((u64)(unsigned long)lock->fl_nspid); | 317 | cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner)); |
318 | else | ||
319 | cephlock->owner = cpu_to_le64(secure_addr(lock->fl_file)); | ||
299 | 320 | ||
300 | switch (lock->fl_type) { | 321 | switch (lock->fl_type) { |
301 | case F_RDLCK: | 322 | case F_RDLCK: |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 10a4ccbf38da..06150fd745ac 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -1026,6 +1026,7 @@ static int __init init_ceph(void) | |||
1026 | if (ret) | 1026 | if (ret) |
1027 | goto out; | 1027 | goto out; |
1028 | 1028 | ||
1029 | ceph_flock_init(); | ||
1029 | ceph_xattr_init(); | 1030 | ceph_xattr_init(); |
1030 | ret = register_filesystem(&ceph_fs_type); | 1031 | ret = register_filesystem(&ceph_fs_type); |
1031 | if (ret) | 1032 | if (ret) |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 70bb183385b7..7866cd05a6bb 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -871,6 +871,7 @@ extern long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | |||
871 | extern const struct export_operations ceph_export_ops; | 871 | extern const struct export_operations ceph_export_ops; |
872 | 872 | ||
873 | /* locks.c */ | 873 | /* locks.c */ |
874 | extern __init void ceph_flock_init(void); | ||
874 | extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl); | 875 | extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl); |
875 | extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl); | 876 | extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl); |
876 | extern void ceph_count_locks(struct inode *inode, int *p_num, int *f_num); | 877 | extern void ceph_count_locks(struct inode *inode, int *p_num, int *f_num); |
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index 35f345f7b3a3..5f6db18d72e8 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h | |||
@@ -421,8 +421,8 @@ union ceph_mds_request_args { | |||
421 | struct { | 421 | struct { |
422 | __u8 rule; /* currently fcntl or flock */ | 422 | __u8 rule; /* currently fcntl or flock */ |
423 | __u8 type; /* shared, exclusive, remove*/ | 423 | __u8 type; /* shared, exclusive, remove*/ |
424 | __le64 owner; /* owner of the lock */ | ||
424 | __le64 pid; /* process id requesting the lock */ | 425 | __le64 pid; /* process id requesting the lock */ |
425 | __le64 pid_namespace; | ||
426 | __le64 start; /* initial location to lock */ | 426 | __le64 start; /* initial location to lock */ |
427 | __le64 length; /* num bytes to lock from start */ | 427 | __le64 length; /* num bytes to lock from start */ |
428 | __u8 wait; /* will caller wait for lock to become available? */ | 428 | __u8 wait; /* will caller wait for lock to become available? */ |
@@ -533,8 +533,8 @@ struct ceph_filelock { | |||
533 | __le64 start;/* file offset to start lock at */ | 533 | __le64 start;/* file offset to start lock at */ |
534 | __le64 length; /* num bytes to lock; 0 for all following start */ | 534 | __le64 length; /* num bytes to lock; 0 for all following start */ |
535 | __le64 client; /* which client holds the lock */ | 535 | __le64 client; /* which client holds the lock */ |
536 | __le64 owner; /* owner the lock */ | ||
536 | __le64 pid; /* process id holding the lock on the client */ | 537 | __le64 pid; /* process id holding the lock on the client */ |
537 | __le64 pid_namespace; | ||
538 | __u8 type; /* shared lock, exclusive lock, or unlock */ | 538 | __u8 type; /* shared lock, exclusive lock, or unlock */ |
539 | } __attribute__ ((packed)); | 539 | } __attribute__ ((packed)); |
540 | 540 | ||