diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/staging/pohmelfs/lock.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/staging/pohmelfs/lock.c')
-rw-r--r-- | drivers/staging/pohmelfs/lock.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c new file mode 100644 index 00000000000..6710114cd42 --- /dev/null +++ b/drivers/staging/pohmelfs/lock.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/backing-dev.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/fsnotify.h> | ||
20 | #include <linux/mempool.h> | ||
21 | |||
22 | #include "netfs.h" | ||
23 | |||
24 | static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi, | ||
25 | u64 id, u64 start, u32 size, int type) | ||
26 | { | ||
27 | struct inode *inode = &pi->vfs_inode; | ||
28 | struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); | ||
29 | struct netfs_trans *t; | ||
30 | struct netfs_cmd *cmd; | ||
31 | int path_len, err; | ||
32 | void *data; | ||
33 | struct netfs_lock *l; | ||
34 | int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info); | ||
35 | |||
36 | err = pohmelfs_path_length(pi); | ||
37 | if (err < 0) | ||
38 | goto err_out_exit; | ||
39 | |||
40 | path_len = err; | ||
41 | |||
42 | err = -ENOMEM; | ||
43 | t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize, | ||
44 | NETFS_TRANS_SINGLE_DST, 0); | ||
45 | if (!t) | ||
46 | goto err_out_exit; | ||
47 | |||
48 | cmd = netfs_trans_current(t); | ||
49 | data = cmd + 1; | ||
50 | |||
51 | err = pohmelfs_construct_path_string(pi, data, path_len); | ||
52 | if (err < 0) | ||
53 | goto err_out_free; | ||
54 | path_len = err; | ||
55 | |||
56 | l = data + path_len; | ||
57 | |||
58 | l->start = start; | ||
59 | l->size = size; | ||
60 | l->type = type; | ||
61 | l->ino = pi->ino; | ||
62 | |||
63 | cmd->cmd = NETFS_LOCK; | ||
64 | cmd->start = 0; | ||
65 | cmd->id = id; | ||
66 | cmd->size = sizeof(struct netfs_lock) + path_len + isize; | ||
67 | cmd->ext = path_len; | ||
68 | cmd->csize = 0; | ||
69 | |||
70 | netfs_convert_cmd(cmd); | ||
71 | netfs_convert_lock(l); | ||
72 | |||
73 | if (isize) { | ||
74 | struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1); | ||
75 | |||
76 | info->mode = inode->i_mode; | ||
77 | info->nlink = inode->i_nlink; | ||
78 | info->uid = inode->i_uid; | ||
79 | info->gid = inode->i_gid; | ||
80 | info->blocks = inode->i_blocks; | ||
81 | info->rdev = inode->i_rdev; | ||
82 | info->size = inode->i_size; | ||
83 | info->version = inode->i_version; | ||
84 | |||
85 | netfs_convert_inode_info(info); | ||
86 | } | ||
87 | |||
88 | netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize); | ||
89 | |||
90 | return netfs_trans_finish(t, psb); | ||
91 | |||
92 | err_out_free: | ||
93 | netfs_trans_free(t); | ||
94 | err_out_exit: | ||
95 | printk("%s: err: %d.\n", __func__, err); | ||
96 | return err; | ||
97 | } | ||
98 | |||
99 | int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) | ||
100 | { | ||
101 | struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); | ||
102 | struct pohmelfs_mcache *m; | ||
103 | int err = -ENOMEM; | ||
104 | struct iattr iattr; | ||
105 | struct inode *inode = &pi->vfs_inode; | ||
106 | |||
107 | dprintk("%s: %p: ino: %llu, start: %llu, size: %u, " | ||
108 | "type: %d, locked as: %d, owned: %d.\n", | ||
109 | __func__, &pi->vfs_inode, pi->ino, | ||
110 | start, size, type, pi->lock_type, | ||
111 | !!test_bit(NETFS_INODE_OWNED, &pi->state)); | ||
112 | |||
113 | if (!pohmelfs_need_lock(pi, type)) | ||
114 | return 0; | ||
115 | |||
116 | m = pohmelfs_mcache_alloc(psb, start, size, NULL); | ||
117 | if (IS_ERR(m)) | ||
118 | return PTR_ERR(m); | ||
119 | |||
120 | err = pohmelfs_send_lock_trans(pi, m->gen, start, size, | ||
121 | type | POHMELFS_LOCK_GRAB); | ||
122 | if (err) | ||
123 | goto err_out_put; | ||
124 | |||
125 | err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout); | ||
126 | if (err) | ||
127 | err = m->err; | ||
128 | else | ||
129 | err = -ETIMEDOUT; | ||
130 | |||
131 | if (err) { | ||
132 | printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n", | ||
133 | __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err); | ||
134 | } | ||
135 | |||
136 | if (err && (err != -ENOENT)) | ||
137 | goto err_out_put; | ||
138 | |||
139 | if (!err) { | ||
140 | netfs_convert_inode_info(&m->info); | ||
141 | |||
142 | iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME; | ||
143 | iattr.ia_mode = m->info.mode; | ||
144 | iattr.ia_uid = m->info.uid; | ||
145 | iattr.ia_gid = m->info.gid; | ||
146 | iattr.ia_size = m->info.size; | ||
147 | iattr.ia_atime = CURRENT_TIME; | ||
148 | |||
149 | dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n", | ||
150 | __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size); | ||
151 | |||
152 | err = pohmelfs_setattr_raw(inode, &iattr); | ||
153 | if (!err) { | ||
154 | struct dentry *dentry = d_find_alias(inode); | ||
155 | if (dentry) { | ||
156 | fsnotify_change(dentry, iattr.ia_valid); | ||
157 | dput(dentry); | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | pi->lock_type = type; | ||
163 | set_bit(NETFS_INODE_OWNED, &pi->state); | ||
164 | |||
165 | pohmelfs_mcache_put(psb, m); | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | err_out_put: | ||
170 | pohmelfs_mcache_put(psb, m); | ||
171 | return err; | ||
172 | } | ||
173 | |||
174 | int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) | ||
175 | { | ||
176 | dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n", | ||
177 | __func__, &pi->vfs_inode, pi->ino, start, size, type); | ||
178 | pi->lock_type = 0; | ||
179 | clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state); | ||
180 | clear_bit(NETFS_INODE_OWNED, &pi->state); | ||
181 | return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type); | ||
182 | } | ||