diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 16:56:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 16:56:13 -0400 |
commit | 1b21f458ddbc8fb6fceeb68158e9e04b2571dabd (patch) | |
tree | 6ad7a02eba52a17e7a5d2e5de07b2918705c97bb | |
parent | 01370f0603f8435d415a19f7e62d1bab826c3589 (diff) | |
parent | 3ebf44902f77537b5784eb5059c2b78d8b5a920a (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (57 commits)
[GFS2] Accept old format NFS filehandles
[GFS2] Small fixes to logging code
[DLM] dump more lock values
[GFS2] Remove i_mode passing from NFS File Handle
[GFS2] Obtaining no_formal_ino from directory entry
[GFS2] git-gfs2-nmw-build-fix
[GFS2] System won't suspend with GFS2 file system mounted
[GFS2] remounting w/o acl option leaves acls enabled
[GFS2] inode size inconsistency
[DLM] Telnet to port 21064 can stop all lockspaces
[GFS2] Fix gfs2_block_truncate_page err return
[GFS2] Addendum to the journaled file/unmount patch
[GFS2] Simplify multiple glock aquisition
[GFS2] assertion failure after writing to journaled file, umount
[GFS2] Use zero_user_page() in stuffed_readpage()
[GFS2] Remove bogus '\0' in rgrp.c
[GFS2] Journaled file write/unstuff bug
[DLM] don't require FS flag on all nodes
[GFS2] Fix deallocation issues
[GFS2] return conflicts for GETLK
...
62 files changed, 2249 insertions, 1107 deletions
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile index 604cf7dc5f39..d248e60951ba 100644 --- a/fs/dlm/Makefile +++ b/fs/dlm/Makefile | |||
@@ -8,6 +8,7 @@ dlm-y := ast.o \ | |||
8 | member.o \ | 8 | member.o \ |
9 | memory.o \ | 9 | memory.o \ |
10 | midcomms.o \ | 10 | midcomms.o \ |
11 | netlink.o \ | ||
11 | lowcomms.o \ | 12 | lowcomms.o \ |
12 | rcom.o \ | 13 | rcom.o \ |
13 | recover.o \ | 14 | recover.o \ |
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 822abdcd1434..5069b2cb5a1f 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c | |||
@@ -90,6 +90,7 @@ struct cluster { | |||
90 | unsigned int cl_scan_secs; | 90 | unsigned int cl_scan_secs; |
91 | unsigned int cl_log_debug; | 91 | unsigned int cl_log_debug; |
92 | unsigned int cl_protocol; | 92 | unsigned int cl_protocol; |
93 | unsigned int cl_timewarn_cs; | ||
93 | }; | 94 | }; |
94 | 95 | ||
95 | enum { | 96 | enum { |
@@ -103,6 +104,7 @@ enum { | |||
103 | CLUSTER_ATTR_SCAN_SECS, | 104 | CLUSTER_ATTR_SCAN_SECS, |
104 | CLUSTER_ATTR_LOG_DEBUG, | 105 | CLUSTER_ATTR_LOG_DEBUG, |
105 | CLUSTER_ATTR_PROTOCOL, | 106 | CLUSTER_ATTR_PROTOCOL, |
107 | CLUSTER_ATTR_TIMEWARN_CS, | ||
106 | }; | 108 | }; |
107 | 109 | ||
108 | struct cluster_attribute { | 110 | struct cluster_attribute { |
@@ -162,6 +164,7 @@ CLUSTER_ATTR(toss_secs, 1); | |||
162 | CLUSTER_ATTR(scan_secs, 1); | 164 | CLUSTER_ATTR(scan_secs, 1); |
163 | CLUSTER_ATTR(log_debug, 0); | 165 | CLUSTER_ATTR(log_debug, 0); |
164 | CLUSTER_ATTR(protocol, 0); | 166 | CLUSTER_ATTR(protocol, 0); |
167 | CLUSTER_ATTR(timewarn_cs, 1); | ||
165 | 168 | ||
166 | static struct configfs_attribute *cluster_attrs[] = { | 169 | static struct configfs_attribute *cluster_attrs[] = { |
167 | [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, | 170 | [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, |
@@ -174,6 +177,7 @@ static struct configfs_attribute *cluster_attrs[] = { | |||
174 | [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr, | 177 | [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr, |
175 | [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr, | 178 | [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr, |
176 | [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr, | 179 | [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr, |
180 | [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, | ||
177 | NULL, | 181 | NULL, |
178 | }; | 182 | }; |
179 | 183 | ||
@@ -429,6 +433,8 @@ static struct config_group *make_cluster(struct config_group *g, | |||
429 | cl->cl_toss_secs = dlm_config.ci_toss_secs; | 433 | cl->cl_toss_secs = dlm_config.ci_toss_secs; |
430 | cl->cl_scan_secs = dlm_config.ci_scan_secs; | 434 | cl->cl_scan_secs = dlm_config.ci_scan_secs; |
431 | cl->cl_log_debug = dlm_config.ci_log_debug; | 435 | cl->cl_log_debug = dlm_config.ci_log_debug; |
436 | cl->cl_protocol = dlm_config.ci_protocol; | ||
437 | cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; | ||
432 | 438 | ||
433 | space_list = &sps->ss_group; | 439 | space_list = &sps->ss_group; |
434 | comm_list = &cms->cs_group; | 440 | comm_list = &cms->cs_group; |
@@ -748,9 +754,16 @@ static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) | |||
748 | 754 | ||
749 | static struct space *get_space(char *name) | 755 | static struct space *get_space(char *name) |
750 | { | 756 | { |
757 | struct config_item *i; | ||
758 | |||
751 | if (!space_list) | 759 | if (!space_list) |
752 | return NULL; | 760 | return NULL; |
753 | return to_space(config_group_find_obj(space_list, name)); | 761 | |
762 | down(&space_list->cg_subsys->su_sem); | ||
763 | i = config_group_find_obj(space_list, name); | ||
764 | up(&space_list->cg_subsys->su_sem); | ||
765 | |||
766 | return to_space(i); | ||
754 | } | 767 | } |
755 | 768 | ||
756 | static void put_space(struct space *sp) | 769 | static void put_space(struct space *sp) |
@@ -776,20 +789,20 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) | |||
776 | if (cm->nodeid != nodeid) | 789 | if (cm->nodeid != nodeid) |
777 | continue; | 790 | continue; |
778 | found = 1; | 791 | found = 1; |
792 | config_item_get(i); | ||
779 | break; | 793 | break; |
780 | } else { | 794 | } else { |
781 | if (!cm->addr_count || | 795 | if (!cm->addr_count || |
782 | memcmp(cm->addr[0], addr, sizeof(*addr))) | 796 | memcmp(cm->addr[0], addr, sizeof(*addr))) |
783 | continue; | 797 | continue; |
784 | found = 1; | 798 | found = 1; |
799 | config_item_get(i); | ||
785 | break; | 800 | break; |
786 | } | 801 | } |
787 | } | 802 | } |
788 | up(&clusters_root.subsys.su_sem); | 803 | up(&clusters_root.subsys.su_sem); |
789 | 804 | ||
790 | if (found) | 805 | if (!found) |
791 | config_item_get(i); | ||
792 | else | ||
793 | cm = NULL; | 806 | cm = NULL; |
794 | return cm; | 807 | return cm; |
795 | } | 808 | } |
@@ -909,6 +922,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num) | |||
909 | #define DEFAULT_SCAN_SECS 5 | 922 | #define DEFAULT_SCAN_SECS 5 |
910 | #define DEFAULT_LOG_DEBUG 0 | 923 | #define DEFAULT_LOG_DEBUG 0 |
911 | #define DEFAULT_PROTOCOL 0 | 924 | #define DEFAULT_PROTOCOL 0 |
925 | #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ | ||
912 | 926 | ||
913 | struct dlm_config_info dlm_config = { | 927 | struct dlm_config_info dlm_config = { |
914 | .ci_tcp_port = DEFAULT_TCP_PORT, | 928 | .ci_tcp_port = DEFAULT_TCP_PORT, |
@@ -920,6 +934,7 @@ struct dlm_config_info dlm_config = { | |||
920 | .ci_toss_secs = DEFAULT_TOSS_SECS, | 934 | .ci_toss_secs = DEFAULT_TOSS_SECS, |
921 | .ci_scan_secs = DEFAULT_SCAN_SECS, | 935 | .ci_scan_secs = DEFAULT_SCAN_SECS, |
922 | .ci_log_debug = DEFAULT_LOG_DEBUG, | 936 | .ci_log_debug = DEFAULT_LOG_DEBUG, |
923 | .ci_protocol = DEFAULT_PROTOCOL | 937 | .ci_protocol = DEFAULT_PROTOCOL, |
938 | .ci_timewarn_cs = DEFAULT_TIMEWARN_CS | ||
924 | }; | 939 | }; |
925 | 940 | ||
diff --git a/fs/dlm/config.h b/fs/dlm/config.h index 967cc3d72e5e..a3170fe22090 100644 --- a/fs/dlm/config.h +++ b/fs/dlm/config.h | |||
@@ -27,6 +27,7 @@ struct dlm_config_info { | |||
27 | int ci_scan_secs; | 27 | int ci_scan_secs; |
28 | int ci_log_debug; | 28 | int ci_log_debug; |
29 | int ci_protocol; | 29 | int ci_protocol; |
30 | int ci_timewarn_cs; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | extern struct dlm_config_info dlm_config; | 33 | extern struct dlm_config_info dlm_config; |
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 61ba670b9e02..12c3bfd5e660 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/debugfs.h> | 17 | #include <linux/debugfs.h> |
18 | 18 | ||
19 | #include "dlm_internal.h" | 19 | #include "dlm_internal.h" |
20 | #include "lock.h" | ||
20 | 21 | ||
21 | #define DLM_DEBUG_BUF_LEN 4096 | 22 | #define DLM_DEBUG_BUF_LEN 4096 |
22 | static char debug_buf[DLM_DEBUG_BUF_LEN]; | 23 | static char debug_buf[DLM_DEBUG_BUF_LEN]; |
@@ -26,6 +27,8 @@ static struct dentry *dlm_root; | |||
26 | 27 | ||
27 | struct rsb_iter { | 28 | struct rsb_iter { |
28 | int entry; | 29 | int entry; |
30 | int locks; | ||
31 | int header; | ||
29 | struct dlm_ls *ls; | 32 | struct dlm_ls *ls; |
30 | struct list_head *next; | 33 | struct list_head *next; |
31 | struct dlm_rsb *rsb; | 34 | struct dlm_rsb *rsb; |
@@ -57,8 +60,8 @@ static char *print_lockmode(int mode) | |||
57 | } | 60 | } |
58 | } | 61 | } |
59 | 62 | ||
60 | static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, | 63 | static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb, |
61 | struct dlm_rsb *res) | 64 | struct dlm_rsb *res) |
62 | { | 65 | { |
63 | seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); | 66 | seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); |
64 | 67 | ||
@@ -85,6 +88,8 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
85 | struct dlm_lkb *lkb; | 88 | struct dlm_lkb *lkb; |
86 | int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; | 89 | int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; |
87 | 90 | ||
91 | lock_rsb(res); | ||
92 | |||
88 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); | 93 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); |
89 | for (i = 0; i < res->res_length; i++) { | 94 | for (i = 0; i < res->res_length; i++) { |
90 | if (isprint(res->res_name[i])) | 95 | if (isprint(res->res_name[i])) |
@@ -129,15 +134,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
129 | /* Print the locks attached to this resource */ | 134 | /* Print the locks attached to this resource */ |
130 | seq_printf(s, "Granted Queue\n"); | 135 | seq_printf(s, "Granted Queue\n"); |
131 | list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) | 136 | list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) |
132 | print_lock(s, lkb, res); | 137 | print_resource_lock(s, lkb, res); |
133 | 138 | ||
134 | seq_printf(s, "Conversion Queue\n"); | 139 | seq_printf(s, "Conversion Queue\n"); |
135 | list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) | 140 | list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) |
136 | print_lock(s, lkb, res); | 141 | print_resource_lock(s, lkb, res); |
137 | 142 | ||
138 | seq_printf(s, "Waiting Queue\n"); | 143 | seq_printf(s, "Waiting Queue\n"); |
139 | list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) | 144 | list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) |
140 | print_lock(s, lkb, res); | 145 | print_resource_lock(s, lkb, res); |
141 | 146 | ||
142 | if (list_empty(&res->res_lookup)) | 147 | if (list_empty(&res->res_lookup)) |
143 | goto out; | 148 | goto out; |
@@ -151,6 +156,61 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
151 | seq_printf(s, "\n"); | 156 | seq_printf(s, "\n"); |
152 | } | 157 | } |
153 | out: | 158 | out: |
159 | unlock_rsb(res); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r) | ||
164 | { | ||
165 | struct dlm_user_args *ua; | ||
166 | unsigned int waiting = 0; | ||
167 | uint64_t xid = 0; | ||
168 | |||
169 | if (lkb->lkb_flags & DLM_IFL_USER) { | ||
170 | ua = (struct dlm_user_args *) lkb->lkb_astparam; | ||
171 | if (ua) | ||
172 | xid = ua->xid; | ||
173 | } | ||
174 | |||
175 | if (lkb->lkb_timestamp) | ||
176 | waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp); | ||
177 | |||
178 | /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms | ||
179 | r_nodeid r_len r_name */ | ||
180 | |||
181 | seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n", | ||
182 | lkb->lkb_id, | ||
183 | lkb->lkb_nodeid, | ||
184 | lkb->lkb_remid, | ||
185 | lkb->lkb_ownpid, | ||
186 | (unsigned long long)xid, | ||
187 | lkb->lkb_exflags, | ||
188 | lkb->lkb_flags, | ||
189 | lkb->lkb_status, | ||
190 | lkb->lkb_grmode, | ||
191 | lkb->lkb_rqmode, | ||
192 | waiting, | ||
193 | r->res_nodeid, | ||
194 | r->res_length, | ||
195 | r->res_name); | ||
196 | } | ||
197 | |||
198 | static int print_locks(struct dlm_rsb *r, struct seq_file *s) | ||
199 | { | ||
200 | struct dlm_lkb *lkb; | ||
201 | |||
202 | lock_rsb(r); | ||
203 | |||
204 | list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) | ||
205 | print_lock(s, lkb, r); | ||
206 | |||
207 | list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) | ||
208 | print_lock(s, lkb, r); | ||
209 | |||
210 | list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) | ||
211 | print_lock(s, lkb, r); | ||
212 | |||
213 | unlock_rsb(r); | ||
154 | return 0; | 214 | return 0; |
155 | } | 215 | } |
156 | 216 | ||
@@ -166,6 +226,9 @@ static int rsb_iter_next(struct rsb_iter *ri) | |||
166 | read_lock(&ls->ls_rsbtbl[i].lock); | 226 | read_lock(&ls->ls_rsbtbl[i].lock); |
167 | if (!list_empty(&ls->ls_rsbtbl[i].list)) { | 227 | if (!list_empty(&ls->ls_rsbtbl[i].list)) { |
168 | ri->next = ls->ls_rsbtbl[i].list.next; | 228 | ri->next = ls->ls_rsbtbl[i].list.next; |
229 | ri->rsb = list_entry(ri->next, struct dlm_rsb, | ||
230 | res_hashchain); | ||
231 | dlm_hold_rsb(ri->rsb); | ||
169 | read_unlock(&ls->ls_rsbtbl[i].lock); | 232 | read_unlock(&ls->ls_rsbtbl[i].lock); |
170 | break; | 233 | break; |
171 | } | 234 | } |
@@ -176,6 +239,7 @@ static int rsb_iter_next(struct rsb_iter *ri) | |||
176 | if (ri->entry >= ls->ls_rsbtbl_size) | 239 | if (ri->entry >= ls->ls_rsbtbl_size) |
177 | return 1; | 240 | return 1; |
178 | } else { | 241 | } else { |
242 | struct dlm_rsb *old = ri->rsb; | ||
179 | i = ri->entry; | 243 | i = ri->entry; |
180 | read_lock(&ls->ls_rsbtbl[i].lock); | 244 | read_lock(&ls->ls_rsbtbl[i].lock); |
181 | ri->next = ri->next->next; | 245 | ri->next = ri->next->next; |
@@ -184,11 +248,14 @@ static int rsb_iter_next(struct rsb_iter *ri) | |||
184 | ri->next = NULL; | 248 | ri->next = NULL; |
185 | ri->entry++; | 249 | ri->entry++; |
186 | read_unlock(&ls->ls_rsbtbl[i].lock); | 250 | read_unlock(&ls->ls_rsbtbl[i].lock); |
251 | dlm_put_rsb(old); | ||
187 | goto top; | 252 | goto top; |
188 | } | 253 | } |
254 | ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain); | ||
255 | dlm_hold_rsb(ri->rsb); | ||
189 | read_unlock(&ls->ls_rsbtbl[i].lock); | 256 | read_unlock(&ls->ls_rsbtbl[i].lock); |
257 | dlm_put_rsb(old); | ||
190 | } | 258 | } |
191 | ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain); | ||
192 | 259 | ||
193 | return 0; | 260 | return 0; |
194 | } | 261 | } |
@@ -202,7 +269,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls) | |||
202 | { | 269 | { |
203 | struct rsb_iter *ri; | 270 | struct rsb_iter *ri; |
204 | 271 | ||
205 | ri = kmalloc(sizeof *ri, GFP_KERNEL); | 272 | ri = kzalloc(sizeof *ri, GFP_KERNEL); |
206 | if (!ri) | 273 | if (!ri) |
207 | return NULL; | 274 | return NULL; |
208 | 275 | ||
@@ -260,7 +327,17 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr) | |||
260 | { | 327 | { |
261 | struct rsb_iter *ri = iter_ptr; | 328 | struct rsb_iter *ri = iter_ptr; |
262 | 329 | ||
263 | print_resource(ri->rsb, file); | 330 | if (ri->locks) { |
331 | if (ri->header) { | ||
332 | seq_printf(file, "id nodeid remid pid xid exflags flags " | ||
333 | "sts grmode rqmode time_ms r_nodeid " | ||
334 | "r_len r_name\n"); | ||
335 | ri->header = 0; | ||
336 | } | ||
337 | print_locks(ri->rsb, file); | ||
338 | } else { | ||
339 | print_resource(ri->rsb, file); | ||
340 | } | ||
264 | 341 | ||
265 | return 0; | 342 | return 0; |
266 | } | 343 | } |
@@ -296,6 +373,83 @@ static const struct file_operations rsb_fops = { | |||
296 | }; | 373 | }; |
297 | 374 | ||
298 | /* | 375 | /* |
376 | * Dump state in compact per-lock listing | ||
377 | */ | ||
378 | |||
379 | static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos) | ||
380 | { | ||
381 | struct rsb_iter *ri; | ||
382 | |||
383 | ri = kzalloc(sizeof *ri, GFP_KERNEL); | ||
384 | if (!ri) | ||
385 | return NULL; | ||
386 | |||
387 | ri->ls = ls; | ||
388 | ri->entry = 0; | ||
389 | ri->next = NULL; | ||
390 | ri->locks = 1; | ||
391 | |||
392 | if (*pos == 0) | ||
393 | ri->header = 1; | ||
394 | |||
395 | if (rsb_iter_next(ri)) { | ||
396 | rsb_iter_free(ri); | ||
397 | return NULL; | ||
398 | } | ||
399 | |||
400 | return ri; | ||
401 | } | ||
402 | |||
403 | static void *locks_seq_start(struct seq_file *file, loff_t *pos) | ||
404 | { | ||
405 | struct rsb_iter *ri; | ||
406 | loff_t n = *pos; | ||
407 | |||
408 | ri = locks_iter_init(file->private, pos); | ||
409 | if (!ri) | ||
410 | return NULL; | ||
411 | |||
412 | while (n--) { | ||
413 | if (rsb_iter_next(ri)) { | ||
414 | rsb_iter_free(ri); | ||
415 | return NULL; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | return ri; | ||
420 | } | ||
421 | |||
422 | static struct seq_operations locks_seq_ops = { | ||
423 | .start = locks_seq_start, | ||
424 | .next = rsb_seq_next, | ||
425 | .stop = rsb_seq_stop, | ||
426 | .show = rsb_seq_show, | ||
427 | }; | ||
428 | |||
429 | static int locks_open(struct inode *inode, struct file *file) | ||
430 | { | ||
431 | struct seq_file *seq; | ||
432 | int ret; | ||
433 | |||
434 | ret = seq_open(file, &locks_seq_ops); | ||
435 | if (ret) | ||
436 | return ret; | ||
437 | |||
438 | seq = file->private_data; | ||
439 | seq->private = inode->i_private; | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static const struct file_operations locks_fops = { | ||
445 | .owner = THIS_MODULE, | ||
446 | .open = locks_open, | ||
447 | .read = seq_read, | ||
448 | .llseek = seq_lseek, | ||
449 | .release = seq_release | ||
450 | }; | ||
451 | |||
452 | /* | ||
299 | * dump lkb's on the ls_waiters list | 453 | * dump lkb's on the ls_waiters list |
300 | */ | 454 | */ |
301 | 455 | ||
@@ -362,6 +516,20 @@ int dlm_create_debug_file(struct dlm_ls *ls) | |||
362 | return -ENOMEM; | 516 | return -ENOMEM; |
363 | } | 517 | } |
364 | 518 | ||
519 | memset(name, 0, sizeof(name)); | ||
520 | snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name); | ||
521 | |||
522 | ls->ls_debug_locks_dentry = debugfs_create_file(name, | ||
523 | S_IFREG | S_IRUGO, | ||
524 | dlm_root, | ||
525 | ls, | ||
526 | &locks_fops); | ||
527 | if (!ls->ls_debug_locks_dentry) { | ||
528 | debugfs_remove(ls->ls_debug_waiters_dentry); | ||
529 | debugfs_remove(ls->ls_debug_rsb_dentry); | ||
530 | return -ENOMEM; | ||
531 | } | ||
532 | |||
365 | return 0; | 533 | return 0; |
366 | } | 534 | } |
367 | 535 | ||
@@ -371,6 +539,8 @@ void dlm_delete_debug_file(struct dlm_ls *ls) | |||
371 | debugfs_remove(ls->ls_debug_rsb_dentry); | 539 | debugfs_remove(ls->ls_debug_rsb_dentry); |
372 | if (ls->ls_debug_waiters_dentry) | 540 | if (ls->ls_debug_waiters_dentry) |
373 | debugfs_remove(ls->ls_debug_waiters_dentry); | 541 | debugfs_remove(ls->ls_debug_waiters_dentry); |
542 | if (ls->ls_debug_locks_dentry) | ||
543 | debugfs_remove(ls->ls_debug_locks_dentry); | ||
374 | } | 544 | } |
375 | 545 | ||
376 | int dlm_register_debugfs(void) | 546 | int dlm_register_debugfs(void) |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 30994d68f6a0..74901e981e10 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -151,6 +151,7 @@ struct dlm_args { | |||
151 | void *bastaddr; | 151 | void *bastaddr; |
152 | int mode; | 152 | int mode; |
153 | struct dlm_lksb *lksb; | 153 | struct dlm_lksb *lksb; |
154 | unsigned long timeout; | ||
154 | }; | 155 | }; |
155 | 156 | ||
156 | 157 | ||
@@ -213,6 +214,9 @@ struct dlm_args { | |||
213 | #define DLM_IFL_OVERLAP_UNLOCK 0x00080000 | 214 | #define DLM_IFL_OVERLAP_UNLOCK 0x00080000 |
214 | #define DLM_IFL_OVERLAP_CANCEL 0x00100000 | 215 | #define DLM_IFL_OVERLAP_CANCEL 0x00100000 |
215 | #define DLM_IFL_ENDOFLIFE 0x00200000 | 216 | #define DLM_IFL_ENDOFLIFE 0x00200000 |
217 | #define DLM_IFL_WATCH_TIMEWARN 0x00400000 | ||
218 | #define DLM_IFL_TIMEOUT_CANCEL 0x00800000 | ||
219 | #define DLM_IFL_DEADLOCK_CANCEL 0x01000000 | ||
216 | #define DLM_IFL_USER 0x00000001 | 220 | #define DLM_IFL_USER 0x00000001 |
217 | #define DLM_IFL_ORPHAN 0x00000002 | 221 | #define DLM_IFL_ORPHAN 0x00000002 |
218 | 222 | ||
@@ -243,6 +247,9 @@ struct dlm_lkb { | |||
243 | struct list_head lkb_wait_reply; /* waiting for remote reply */ | 247 | struct list_head lkb_wait_reply; /* waiting for remote reply */ |
244 | struct list_head lkb_astqueue; /* need ast to be sent */ | 248 | struct list_head lkb_astqueue; /* need ast to be sent */ |
245 | struct list_head lkb_ownqueue; /* list of locks for a process */ | 249 | struct list_head lkb_ownqueue; /* list of locks for a process */ |
250 | struct list_head lkb_time_list; | ||
251 | unsigned long lkb_timestamp; | ||
252 | unsigned long lkb_timeout_cs; | ||
246 | 253 | ||
247 | char *lkb_lvbptr; | 254 | char *lkb_lvbptr; |
248 | struct dlm_lksb *lkb_lksb; /* caller's status block */ | 255 | struct dlm_lksb *lkb_lksb; /* caller's status block */ |
@@ -447,12 +454,16 @@ struct dlm_ls { | |||
447 | struct mutex ls_orphans_mutex; | 454 | struct mutex ls_orphans_mutex; |
448 | struct list_head ls_orphans; | 455 | struct list_head ls_orphans; |
449 | 456 | ||
457 | struct mutex ls_timeout_mutex; | ||
458 | struct list_head ls_timeout; | ||
459 | |||
450 | struct list_head ls_nodes; /* current nodes in ls */ | 460 | struct list_head ls_nodes; /* current nodes in ls */ |
451 | struct list_head ls_nodes_gone; /* dead node list, recovery */ | 461 | struct list_head ls_nodes_gone; /* dead node list, recovery */ |
452 | int ls_num_nodes; /* number of nodes in ls */ | 462 | int ls_num_nodes; /* number of nodes in ls */ |
453 | int ls_low_nodeid; | 463 | int ls_low_nodeid; |
454 | int ls_total_weight; | 464 | int ls_total_weight; |
455 | int *ls_node_array; | 465 | int *ls_node_array; |
466 | gfp_t ls_allocation; | ||
456 | 467 | ||
457 | struct dlm_rsb ls_stub_rsb; /* for returning errors */ | 468 | struct dlm_rsb ls_stub_rsb; /* for returning errors */ |
458 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ | 469 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ |
@@ -460,9 +471,12 @@ struct dlm_ls { | |||
460 | 471 | ||
461 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ | 472 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ |
462 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ | 473 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ |
474 | struct dentry *ls_debug_locks_dentry; /* debugfs */ | ||
463 | 475 | ||
464 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ | 476 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ |
465 | int ls_uevent_result; | 477 | int ls_uevent_result; |
478 | struct completion ls_members_done; | ||
479 | int ls_members_result; | ||
466 | 480 | ||
467 | struct miscdevice ls_device; | 481 | struct miscdevice ls_device; |
468 | 482 | ||
@@ -472,6 +486,7 @@ struct dlm_ls { | |||
472 | struct task_struct *ls_recoverd_task; | 486 | struct task_struct *ls_recoverd_task; |
473 | struct mutex ls_recoverd_active; | 487 | struct mutex ls_recoverd_active; |
474 | spinlock_t ls_recover_lock; | 488 | spinlock_t ls_recover_lock; |
489 | unsigned long ls_recover_begin; /* jiffies timestamp */ | ||
475 | uint32_t ls_recover_status; /* DLM_RS_ */ | 490 | uint32_t ls_recover_status; /* DLM_RS_ */ |
476 | uint64_t ls_recover_seq; | 491 | uint64_t ls_recover_seq; |
477 | struct dlm_recover *ls_recover_args; | 492 | struct dlm_recover *ls_recover_args; |
@@ -501,6 +516,7 @@ struct dlm_ls { | |||
501 | #define LSFL_RCOM_READY 3 | 516 | #define LSFL_RCOM_READY 3 |
502 | #define LSFL_RCOM_WAIT 4 | 517 | #define LSFL_RCOM_WAIT 4 |
503 | #define LSFL_UEVENT_WAIT 5 | 518 | #define LSFL_UEVENT_WAIT 5 |
519 | #define LSFL_TIMEWARN 6 | ||
504 | 520 | ||
505 | /* much of this is just saving user space pointers associated with the | 521 | /* much of this is just saving user space pointers associated with the |
506 | lock that we pass back to the user lib with an ast */ | 522 | lock that we pass back to the user lib with an ast */ |
@@ -518,6 +534,7 @@ struct dlm_user_args { | |||
518 | void __user *castaddr; | 534 | void __user *castaddr; |
519 | void __user *bastparam; | 535 | void __user *bastparam; |
520 | void __user *bastaddr; | 536 | void __user *bastaddr; |
537 | uint64_t xid; | ||
521 | }; | 538 | }; |
522 | 539 | ||
523 | #define DLM_PROC_FLAGS_CLOSING 1 | 540 | #define DLM_PROC_FLAGS_CLOSING 1 |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index d8d6e729f96b..b455919c1998 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -82,10 +82,13 @@ static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode); | |||
82 | static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); | 82 | static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); |
83 | static int send_remove(struct dlm_rsb *r); | 83 | static int send_remove(struct dlm_rsb *r); |
84 | static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | 84 | static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); |
85 | static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | ||
85 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | 86 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, |
86 | struct dlm_message *ms); | 87 | struct dlm_message *ms); |
87 | static int receive_extralen(struct dlm_message *ms); | 88 | static int receive_extralen(struct dlm_message *ms); |
88 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); | 89 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); |
90 | static void del_timeout(struct dlm_lkb *lkb); | ||
91 | void dlm_timeout_warn(struct dlm_lkb *lkb); | ||
89 | 92 | ||
90 | /* | 93 | /* |
91 | * Lock compatibilty matrix - thanks Steve | 94 | * Lock compatibilty matrix - thanks Steve |
@@ -194,17 +197,17 @@ void dlm_dump_rsb(struct dlm_rsb *r) | |||
194 | 197 | ||
195 | /* Threads cannot use the lockspace while it's being recovered */ | 198 | /* Threads cannot use the lockspace while it's being recovered */ |
196 | 199 | ||
197 | static inline void lock_recovery(struct dlm_ls *ls) | 200 | static inline void dlm_lock_recovery(struct dlm_ls *ls) |
198 | { | 201 | { |
199 | down_read(&ls->ls_in_recovery); | 202 | down_read(&ls->ls_in_recovery); |
200 | } | 203 | } |
201 | 204 | ||
202 | static inline void unlock_recovery(struct dlm_ls *ls) | 205 | void dlm_unlock_recovery(struct dlm_ls *ls) |
203 | { | 206 | { |
204 | up_read(&ls->ls_in_recovery); | 207 | up_read(&ls->ls_in_recovery); |
205 | } | 208 | } |
206 | 209 | ||
207 | static inline int lock_recovery_try(struct dlm_ls *ls) | 210 | int dlm_lock_recovery_try(struct dlm_ls *ls) |
208 | { | 211 | { |
209 | return down_read_trylock(&ls->ls_in_recovery); | 212 | return down_read_trylock(&ls->ls_in_recovery); |
210 | } | 213 | } |
@@ -286,8 +289,22 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) | |||
286 | if (is_master_copy(lkb)) | 289 | if (is_master_copy(lkb)) |
287 | return; | 290 | return; |
288 | 291 | ||
292 | del_timeout(lkb); | ||
293 | |||
289 | DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb);); | 294 | DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb);); |
290 | 295 | ||
296 | /* if the operation was a cancel, then return -DLM_ECANCEL, if a | ||
297 | timeout caused the cancel then return -ETIMEDOUT */ | ||
298 | if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) { | ||
299 | lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL; | ||
300 | rv = -ETIMEDOUT; | ||
301 | } | ||
302 | |||
303 | if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) { | ||
304 | lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL; | ||
305 | rv = -EDEADLK; | ||
306 | } | ||
307 | |||
291 | lkb->lkb_lksb->sb_status = rv; | 308 | lkb->lkb_lksb->sb_status = rv; |
292 | lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags; | 309 | lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags; |
293 | 310 | ||
@@ -581,6 +598,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | |||
581 | kref_init(&lkb->lkb_ref); | 598 | kref_init(&lkb->lkb_ref); |
582 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); | 599 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); |
583 | INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); | 600 | INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); |
601 | INIT_LIST_HEAD(&lkb->lkb_time_list); | ||
584 | 602 | ||
585 | get_random_bytes(&bucket, sizeof(bucket)); | 603 | get_random_bytes(&bucket, sizeof(bucket)); |
586 | bucket &= (ls->ls_lkbtbl_size - 1); | 604 | bucket &= (ls->ls_lkbtbl_size - 1); |
@@ -985,15 +1003,136 @@ void dlm_scan_rsbs(struct dlm_ls *ls) | |||
985 | { | 1003 | { |
986 | int i; | 1004 | int i; |
987 | 1005 | ||
988 | if (dlm_locking_stopped(ls)) | ||
989 | return; | ||
990 | |||
991 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { | 1006 | for (i = 0; i < ls->ls_rsbtbl_size; i++) { |
992 | shrink_bucket(ls, i); | 1007 | shrink_bucket(ls, i); |
1008 | if (dlm_locking_stopped(ls)) | ||
1009 | break; | ||
993 | cond_resched(); | 1010 | cond_resched(); |
994 | } | 1011 | } |
995 | } | 1012 | } |
996 | 1013 | ||
1014 | static void add_timeout(struct dlm_lkb *lkb) | ||
1015 | { | ||
1016 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | ||
1017 | |||
1018 | if (is_master_copy(lkb)) { | ||
1019 | lkb->lkb_timestamp = jiffies; | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) && | ||
1024 | !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) { | ||
1025 | lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN; | ||
1026 | goto add_it; | ||
1027 | } | ||
1028 | if (lkb->lkb_exflags & DLM_LKF_TIMEOUT) | ||
1029 | goto add_it; | ||
1030 | return; | ||
1031 | |||
1032 | add_it: | ||
1033 | DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb);); | ||
1034 | mutex_lock(&ls->ls_timeout_mutex); | ||
1035 | hold_lkb(lkb); | ||
1036 | lkb->lkb_timestamp = jiffies; | ||
1037 | list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout); | ||
1038 | mutex_unlock(&ls->ls_timeout_mutex); | ||
1039 | } | ||
1040 | |||
1041 | static void del_timeout(struct dlm_lkb *lkb) | ||
1042 | { | ||
1043 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | ||
1044 | |||
1045 | mutex_lock(&ls->ls_timeout_mutex); | ||
1046 | if (!list_empty(&lkb->lkb_time_list)) { | ||
1047 | list_del_init(&lkb->lkb_time_list); | ||
1048 | unhold_lkb(lkb); | ||
1049 | } | ||
1050 | mutex_unlock(&ls->ls_timeout_mutex); | ||
1051 | } | ||
1052 | |||
1053 | /* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and | ||
1054 | lkb_lksb_timeout without lock_rsb? Note: we can't lock timeout_mutex | ||
1055 | and then lock rsb because of lock ordering in add_timeout. We may need | ||
1056 | to specify some special timeout-related bits in the lkb that are just to | ||
1057 | be accessed under the timeout_mutex. */ | ||
1058 | |||
1059 | void dlm_scan_timeout(struct dlm_ls *ls) | ||
1060 | { | ||
1061 | struct dlm_rsb *r; | ||
1062 | struct dlm_lkb *lkb; | ||
1063 | int do_cancel, do_warn; | ||
1064 | |||
1065 | for (;;) { | ||
1066 | if (dlm_locking_stopped(ls)) | ||
1067 | break; | ||
1068 | |||
1069 | do_cancel = 0; | ||
1070 | do_warn = 0; | ||
1071 | mutex_lock(&ls->ls_timeout_mutex); | ||
1072 | list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) { | ||
1073 | |||
1074 | if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) && | ||
1075 | time_after_eq(jiffies, lkb->lkb_timestamp + | ||
1076 | lkb->lkb_timeout_cs * HZ/100)) | ||
1077 | do_cancel = 1; | ||
1078 | |||
1079 | if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) && | ||
1080 | time_after_eq(jiffies, lkb->lkb_timestamp + | ||
1081 | dlm_config.ci_timewarn_cs * HZ/100)) | ||
1082 | do_warn = 1; | ||
1083 | |||
1084 | if (!do_cancel && !do_warn) | ||
1085 | continue; | ||
1086 | hold_lkb(lkb); | ||
1087 | break; | ||
1088 | } | ||
1089 | mutex_unlock(&ls->ls_timeout_mutex); | ||
1090 | |||
1091 | if (!do_cancel && !do_warn) | ||
1092 | break; | ||
1093 | |||
1094 | r = lkb->lkb_resource; | ||
1095 | hold_rsb(r); | ||
1096 | lock_rsb(r); | ||
1097 | |||
1098 | if (do_warn) { | ||
1099 | /* clear flag so we only warn once */ | ||
1100 | lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN; | ||
1101 | if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT)) | ||
1102 | del_timeout(lkb); | ||
1103 | dlm_timeout_warn(lkb); | ||
1104 | } | ||
1105 | |||
1106 | if (do_cancel) { | ||
1107 | log_debug(ls, "timeout cancel %x node %d %s", | ||
1108 | lkb->lkb_id, lkb->lkb_nodeid, r->res_name); | ||
1109 | lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN; | ||
1110 | lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL; | ||
1111 | del_timeout(lkb); | ||
1112 | _cancel_lock(r, lkb); | ||
1113 | } | ||
1114 | |||
1115 | unlock_rsb(r); | ||
1116 | unhold_rsb(r); | ||
1117 | dlm_put_lkb(lkb); | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | /* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping | ||
1122 | dlm_recoverd before checking/setting ls_recover_begin. */ | ||
1123 | |||
1124 | void dlm_adjust_timeouts(struct dlm_ls *ls) | ||
1125 | { | ||
1126 | struct dlm_lkb *lkb; | ||
1127 | long adj = jiffies - ls->ls_recover_begin; | ||
1128 | |||
1129 | ls->ls_recover_begin = 0; | ||
1130 | mutex_lock(&ls->ls_timeout_mutex); | ||
1131 | list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) | ||
1132 | lkb->lkb_timestamp += adj; | ||
1133 | mutex_unlock(&ls->ls_timeout_mutex); | ||
1134 | } | ||
1135 | |||
997 | /* lkb is master or local copy */ | 1136 | /* lkb is master or local copy */ |
998 | 1137 | ||
999 | static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1138 | static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) |
@@ -1275,10 +1414,8 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb) | |||
1275 | * queue for one resource. The granted mode of each lock blocks the requested | 1414 | * queue for one resource. The granted mode of each lock blocks the requested |
1276 | * mode of the other lock." | 1415 | * mode of the other lock." |
1277 | * | 1416 | * |
1278 | * Part 2: if the granted mode of lkb is preventing the first lkb in the | 1417 | * Part 2: if the granted mode of lkb is preventing an earlier lkb in the |
1279 | * convert queue from being granted, then demote lkb (set grmode to NL). | 1418 | * convert queue from being granted, then deadlk/demote lkb. |
1280 | * This second form requires that we check for conv-deadlk even when | ||
1281 | * now == 0 in _can_be_granted(). | ||
1282 | * | 1419 | * |
1283 | * Example: | 1420 | * Example: |
1284 | * Granted Queue: empty | 1421 | * Granted Queue: empty |
@@ -1287,41 +1424,52 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb) | |||
1287 | * | 1424 | * |
1288 | * The first lock can't be granted because of the granted mode of the second | 1425 | * The first lock can't be granted because of the granted mode of the second |
1289 | * lock and the second lock can't be granted because it's not first in the | 1426 | * lock and the second lock can't be granted because it's not first in the |
1290 | * list. We demote the granted mode of the second lock (the lkb passed to this | 1427 | * list. We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we |
1291 | * function). | 1428 | * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK |
1429 | * flag set and return DEMOTED in the lksb flags. | ||
1430 | * | ||
1431 | * Originally, this function detected conv-deadlk in a more limited scope: | ||
1432 | * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or | ||
1433 | * - if lkb1 was the first entry in the queue (not just earlier), and was | ||
1434 | * blocked by the granted mode of lkb2, and there was nothing on the | ||
1435 | * granted queue preventing lkb1 from being granted immediately, i.e. | ||
1436 | * lkb2 was the only thing preventing lkb1 from being granted. | ||
1437 | * | ||
1438 | * That second condition meant we'd only say there was conv-deadlk if | ||
1439 | * resolving it (by demotion) would lead to the first lock on the convert | ||
1440 | * queue being granted right away. It allowed conversion deadlocks to exist | ||
1441 | * between locks on the convert queue while they couldn't be granted anyway. | ||
1292 | * | 1442 | * |
1293 | * After the resolution, the "grant pending" function needs to go back and try | 1443 | * Now, we detect and take action on conversion deadlocks immediately when |
1294 | * to grant locks on the convert queue again since the first lock can now be | 1444 | * they're created, even if they may not be immediately consequential. If |
1295 | * granted. | 1445 | * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted |
1446 | * mode that would prevent lkb1's conversion from being granted, we do a | ||
1447 | * deadlk/demote on lkb2 right away and don't let it onto the convert queue. | ||
1448 | * I think this means that the lkb_is_ahead condition below should always | ||
1449 | * be zero, i.e. there will never be conv-deadlk between two locks that are | ||
1450 | * both already on the convert queue. | ||
1296 | */ | 1451 | */ |
1297 | 1452 | ||
1298 | static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb) | 1453 | static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2) |
1299 | { | 1454 | { |
1300 | struct dlm_lkb *this, *first = NULL, *self = NULL; | 1455 | struct dlm_lkb *lkb1; |
1456 | int lkb_is_ahead = 0; | ||
1301 | 1457 | ||
1302 | list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) { | 1458 | list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) { |
1303 | if (!first) | 1459 | if (lkb1 == lkb2) { |
1304 | first = this; | 1460 | lkb_is_ahead = 1; |
1305 | if (this == lkb) { | ||
1306 | self = lkb; | ||
1307 | continue; | 1461 | continue; |
1308 | } | 1462 | } |
1309 | 1463 | ||
1310 | if (!modes_compat(this, lkb) && !modes_compat(lkb, this)) | 1464 | if (!lkb_is_ahead) { |
1311 | return 1; | 1465 | if (!modes_compat(lkb2, lkb1)) |
1312 | } | 1466 | return 1; |
1313 | 1467 | } else { | |
1314 | /* if lkb is on the convert queue and is preventing the first | 1468 | if (!modes_compat(lkb2, lkb1) && |
1315 | from being granted, then there's deadlock and we demote lkb. | 1469 | !modes_compat(lkb1, lkb2)) |
1316 | multiple converting locks may need to do this before the first | 1470 | return 1; |
1317 | converting lock can be granted. */ | 1471 | } |
1318 | |||
1319 | if (self && self != first) { | ||
1320 | if (!modes_compat(lkb, first) && | ||
1321 | !queue_conflict(&rsb->res_grantqueue, first)) | ||
1322 | return 1; | ||
1323 | } | 1472 | } |
1324 | |||
1325 | return 0; | 1473 | return 0; |
1326 | } | 1474 | } |
1327 | 1475 | ||
@@ -1450,42 +1598,57 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) | |||
1450 | if (!now && !conv && list_empty(&r->res_convertqueue) && | 1598 | if (!now && !conv && list_empty(&r->res_convertqueue) && |
1451 | first_in_list(lkb, &r->res_waitqueue)) | 1599 | first_in_list(lkb, &r->res_waitqueue)) |
1452 | return 1; | 1600 | return 1; |
1453 | |||
1454 | out: | 1601 | out: |
1455 | /* | ||
1456 | * The following, enabled by CONVDEADLK, departs from VMS. | ||
1457 | */ | ||
1458 | |||
1459 | if (conv && (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) && | ||
1460 | conversion_deadlock_detect(r, lkb)) { | ||
1461 | lkb->lkb_grmode = DLM_LOCK_NL; | ||
1462 | lkb->lkb_sbflags |= DLM_SBF_DEMOTED; | ||
1463 | } | ||
1464 | |||
1465 | return 0; | 1602 | return 0; |
1466 | } | 1603 | } |
1467 | 1604 | ||
1468 | /* | 1605 | static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, |
1469 | * The ALTPR and ALTCW flags aren't traditional lock manager flags, but are a | 1606 | int *err) |
1470 | * simple way to provide a big optimization to applications that can use them. | ||
1471 | */ | ||
1472 | |||
1473 | static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) | ||
1474 | { | 1607 | { |
1475 | uint32_t flags = lkb->lkb_exflags; | ||
1476 | int rv; | 1608 | int rv; |
1477 | int8_t alt = 0, rqmode = lkb->lkb_rqmode; | 1609 | int8_t alt = 0, rqmode = lkb->lkb_rqmode; |
1610 | int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV); | ||
1611 | |||
1612 | if (err) | ||
1613 | *err = 0; | ||
1478 | 1614 | ||
1479 | rv = _can_be_granted(r, lkb, now); | 1615 | rv = _can_be_granted(r, lkb, now); |
1480 | if (rv) | 1616 | if (rv) |
1481 | goto out; | 1617 | goto out; |
1482 | 1618 | ||
1483 | if (lkb->lkb_sbflags & DLM_SBF_DEMOTED) | 1619 | /* |
1620 | * The CONVDEADLK flag is non-standard and tells the dlm to resolve | ||
1621 | * conversion deadlocks by demoting grmode to NL, otherwise the dlm | ||
1622 | * cancels one of the locks. | ||
1623 | */ | ||
1624 | |||
1625 | if (is_convert && can_be_queued(lkb) && | ||
1626 | conversion_deadlock_detect(r, lkb)) { | ||
1627 | if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) { | ||
1628 | lkb->lkb_grmode = DLM_LOCK_NL; | ||
1629 | lkb->lkb_sbflags |= DLM_SBF_DEMOTED; | ||
1630 | } else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) { | ||
1631 | if (err) | ||
1632 | *err = -EDEADLK; | ||
1633 | else { | ||
1634 | log_print("can_be_granted deadlock %x now %d", | ||
1635 | lkb->lkb_id, now); | ||
1636 | dlm_dump_rsb(r); | ||
1637 | } | ||
1638 | } | ||
1484 | goto out; | 1639 | goto out; |
1640 | } | ||
1485 | 1641 | ||
1486 | if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR) | 1642 | /* |
1643 | * The ALTPR and ALTCW flags are non-standard and tell the dlm to try | ||
1644 | * to grant a request in a mode other than the normal rqmode. It's a | ||
1645 | * simple way to provide a big optimization to applications that can | ||
1646 | * use them. | ||
1647 | */ | ||
1648 | |||
1649 | if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR)) | ||
1487 | alt = DLM_LOCK_PR; | 1650 | alt = DLM_LOCK_PR; |
1488 | else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW) | 1651 | else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW)) |
1489 | alt = DLM_LOCK_CW; | 1652 | alt = DLM_LOCK_CW; |
1490 | 1653 | ||
1491 | if (alt) { | 1654 | if (alt) { |
@@ -1500,10 +1663,20 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) | |||
1500 | return rv; | 1663 | return rv; |
1501 | } | 1664 | } |
1502 | 1665 | ||
1666 | /* FIXME: I don't think that can_be_granted() can/will demote or find deadlock | ||
1667 | for locks pending on the convert list. Once verified (watch for these | ||
1668 | log_prints), we should be able to just call _can_be_granted() and not | ||
1669 | bother with the demote/deadlk cases here (and there's no easy way to deal | ||
1670 | with a deadlk here, we'd have to generate something like grant_lock with | ||
1671 | the deadlk error.) */ | ||
1672 | |||
1673 | /* returns the highest requested mode of all blocked conversions */ | ||
1674 | |||
1503 | static int grant_pending_convert(struct dlm_rsb *r, int high) | 1675 | static int grant_pending_convert(struct dlm_rsb *r, int high) |
1504 | { | 1676 | { |
1505 | struct dlm_lkb *lkb, *s; | 1677 | struct dlm_lkb *lkb, *s; |
1506 | int hi, demoted, quit, grant_restart, demote_restart; | 1678 | int hi, demoted, quit, grant_restart, demote_restart; |
1679 | int deadlk; | ||
1507 | 1680 | ||
1508 | quit = 0; | 1681 | quit = 0; |
1509 | restart: | 1682 | restart: |
@@ -1513,14 +1686,29 @@ static int grant_pending_convert(struct dlm_rsb *r, int high) | |||
1513 | 1686 | ||
1514 | list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) { | 1687 | list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) { |
1515 | demoted = is_demoted(lkb); | 1688 | demoted = is_demoted(lkb); |
1516 | if (can_be_granted(r, lkb, 0)) { | 1689 | deadlk = 0; |
1690 | |||
1691 | if (can_be_granted(r, lkb, 0, &deadlk)) { | ||
1517 | grant_lock_pending(r, lkb); | 1692 | grant_lock_pending(r, lkb); |
1518 | grant_restart = 1; | 1693 | grant_restart = 1; |
1519 | } else { | 1694 | continue; |
1520 | hi = max_t(int, lkb->lkb_rqmode, hi); | ||
1521 | if (!demoted && is_demoted(lkb)) | ||
1522 | demote_restart = 1; | ||
1523 | } | 1695 | } |
1696 | |||
1697 | if (!demoted && is_demoted(lkb)) { | ||
1698 | log_print("WARN: pending demoted %x node %d %s", | ||
1699 | lkb->lkb_id, lkb->lkb_nodeid, r->res_name); | ||
1700 | demote_restart = 1; | ||
1701 | continue; | ||
1702 | } | ||
1703 | |||
1704 | if (deadlk) { | ||
1705 | log_print("WARN: pending deadlock %x node %d %s", | ||
1706 | lkb->lkb_id, lkb->lkb_nodeid, r->res_name); | ||
1707 | dlm_dump_rsb(r); | ||
1708 | continue; | ||
1709 | } | ||
1710 | |||
1711 | hi = max_t(int, lkb->lkb_rqmode, hi); | ||
1524 | } | 1712 | } |
1525 | 1713 | ||
1526 | if (grant_restart) | 1714 | if (grant_restart) |
@@ -1538,7 +1726,7 @@ static int grant_pending_wait(struct dlm_rsb *r, int high) | |||
1538 | struct dlm_lkb *lkb, *s; | 1726 | struct dlm_lkb *lkb, *s; |
1539 | 1727 | ||
1540 | list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) { | 1728 | list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) { |
1541 | if (can_be_granted(r, lkb, 0)) | 1729 | if (can_be_granted(r, lkb, 0, NULL)) |
1542 | grant_lock_pending(r, lkb); | 1730 | grant_lock_pending(r, lkb); |
1543 | else | 1731 | else |
1544 | high = max_t(int, lkb->lkb_rqmode, high); | 1732 | high = max_t(int, lkb->lkb_rqmode, high); |
@@ -1733,7 +1921,7 @@ static void confirm_master(struct dlm_rsb *r, int error) | |||
1733 | } | 1921 | } |
1734 | 1922 | ||
1735 | static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | 1923 | static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, |
1736 | int namelen, uint32_t parent_lkid, void *ast, | 1924 | int namelen, unsigned long timeout_cs, void *ast, |
1737 | void *astarg, void *bast, struct dlm_args *args) | 1925 | void *astarg, void *bast, struct dlm_args *args) |
1738 | { | 1926 | { |
1739 | int rv = -EINVAL; | 1927 | int rv = -EINVAL; |
@@ -1776,10 +1964,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | |||
1776 | if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) | 1964 | if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) |
1777 | goto out; | 1965 | goto out; |
1778 | 1966 | ||
1779 | /* parent/child locks not yet supported */ | ||
1780 | if (parent_lkid) | ||
1781 | goto out; | ||
1782 | |||
1783 | if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) | 1967 | if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) |
1784 | goto out; | 1968 | goto out; |
1785 | 1969 | ||
@@ -1791,6 +1975,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, | |||
1791 | args->astaddr = ast; | 1975 | args->astaddr = ast; |
1792 | args->astparam = (long) astarg; | 1976 | args->astparam = (long) astarg; |
1793 | args->bastaddr = bast; | 1977 | args->bastaddr = bast; |
1978 | args->timeout = timeout_cs; | ||
1794 | args->mode = mode; | 1979 | args->mode = mode; |
1795 | args->lksb = lksb; | 1980 | args->lksb = lksb; |
1796 | rv = 0; | 1981 | rv = 0; |
@@ -1845,6 +2030,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
1845 | lkb->lkb_lksb = args->lksb; | 2030 | lkb->lkb_lksb = args->lksb; |
1846 | lkb->lkb_lvbptr = args->lksb->sb_lvbptr; | 2031 | lkb->lkb_lvbptr = args->lksb->sb_lvbptr; |
1847 | lkb->lkb_ownpid = (int) current->pid; | 2032 | lkb->lkb_ownpid = (int) current->pid; |
2033 | lkb->lkb_timeout_cs = args->timeout; | ||
1848 | rv = 0; | 2034 | rv = 0; |
1849 | out: | 2035 | out: |
1850 | return rv; | 2036 | return rv; |
@@ -1903,6 +2089,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) | |||
1903 | if (is_overlap(lkb)) | 2089 | if (is_overlap(lkb)) |
1904 | goto out; | 2090 | goto out; |
1905 | 2091 | ||
2092 | /* don't let scand try to do a cancel */ | ||
2093 | del_timeout(lkb); | ||
2094 | |||
1906 | if (lkb->lkb_flags & DLM_IFL_RESEND) { | 2095 | if (lkb->lkb_flags & DLM_IFL_RESEND) { |
1907 | lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; | 2096 | lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; |
1908 | rv = -EBUSY; | 2097 | rv = -EBUSY; |
@@ -1934,6 +2123,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) | |||
1934 | if (is_overlap_unlock(lkb)) | 2123 | if (is_overlap_unlock(lkb)) |
1935 | goto out; | 2124 | goto out; |
1936 | 2125 | ||
2126 | /* don't let scand try to do a cancel */ | ||
2127 | del_timeout(lkb); | ||
2128 | |||
1937 | if (lkb->lkb_flags & DLM_IFL_RESEND) { | 2129 | if (lkb->lkb_flags & DLM_IFL_RESEND) { |
1938 | lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; | 2130 | lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; |
1939 | rv = -EBUSY; | 2131 | rv = -EBUSY; |
@@ -1984,7 +2176,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1984 | { | 2176 | { |
1985 | int error = 0; | 2177 | int error = 0; |
1986 | 2178 | ||
1987 | if (can_be_granted(r, lkb, 1)) { | 2179 | if (can_be_granted(r, lkb, 1, NULL)) { |
1988 | grant_lock(r, lkb); | 2180 | grant_lock(r, lkb); |
1989 | queue_cast(r, lkb, 0); | 2181 | queue_cast(r, lkb, 0); |
1990 | goto out; | 2182 | goto out; |
@@ -1994,6 +2186,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1994 | error = -EINPROGRESS; | 2186 | error = -EINPROGRESS; |
1995 | add_lkb(r, lkb, DLM_LKSTS_WAITING); | 2187 | add_lkb(r, lkb, DLM_LKSTS_WAITING); |
1996 | send_blocking_asts(r, lkb); | 2188 | send_blocking_asts(r, lkb); |
2189 | add_timeout(lkb); | ||
1997 | goto out; | 2190 | goto out; |
1998 | } | 2191 | } |
1999 | 2192 | ||
@@ -2009,16 +2202,32 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
2009 | static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) | 2202 | static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) |
2010 | { | 2203 | { |
2011 | int error = 0; | 2204 | int error = 0; |
2205 | int deadlk = 0; | ||
2012 | 2206 | ||
2013 | /* changing an existing lock may allow others to be granted */ | 2207 | /* changing an existing lock may allow others to be granted */ |
2014 | 2208 | ||
2015 | if (can_be_granted(r, lkb, 1)) { | 2209 | if (can_be_granted(r, lkb, 1, &deadlk)) { |
2016 | grant_lock(r, lkb); | 2210 | grant_lock(r, lkb); |
2017 | queue_cast(r, lkb, 0); | 2211 | queue_cast(r, lkb, 0); |
2018 | grant_pending_locks(r); | 2212 | grant_pending_locks(r); |
2019 | goto out; | 2213 | goto out; |
2020 | } | 2214 | } |
2021 | 2215 | ||
2216 | /* can_be_granted() detected that this lock would block in a conversion | ||
2217 | deadlock, so we leave it on the granted queue and return EDEADLK in | ||
2218 | the ast for the convert. */ | ||
2219 | |||
2220 | if (deadlk) { | ||
2221 | /* it's left on the granted queue */ | ||
2222 | log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s", | ||
2223 | lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status, | ||
2224 | lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name); | ||
2225 | revert_lock(r, lkb); | ||
2226 | queue_cast(r, lkb, -EDEADLK); | ||
2227 | error = -EDEADLK; | ||
2228 | goto out; | ||
2229 | } | ||
2230 | |||
2022 | /* is_demoted() means the can_be_granted() above set the grmode | 2231 | /* is_demoted() means the can_be_granted() above set the grmode |
2023 | to NL, and left us on the granted queue. This auto-demotion | 2232 | to NL, and left us on the granted queue. This auto-demotion |
2024 | (due to CONVDEADLK) might mean other locks, and/or this lock, are | 2233 | (due to CONVDEADLK) might mean other locks, and/or this lock, are |
@@ -2041,6 +2250,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
2041 | del_lkb(r, lkb); | 2250 | del_lkb(r, lkb); |
2042 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); | 2251 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); |
2043 | send_blocking_asts(r, lkb); | 2252 | send_blocking_asts(r, lkb); |
2253 | add_timeout(lkb); | ||
2044 | goto out; | 2254 | goto out; |
2045 | } | 2255 | } |
2046 | 2256 | ||
@@ -2274,7 +2484,7 @@ int dlm_lock(dlm_lockspace_t *lockspace, | |||
2274 | if (!ls) | 2484 | if (!ls) |
2275 | return -EINVAL; | 2485 | return -EINVAL; |
2276 | 2486 | ||
2277 | lock_recovery(ls); | 2487 | dlm_lock_recovery(ls); |
2278 | 2488 | ||
2279 | if (convert) | 2489 | if (convert) |
2280 | error = find_lkb(ls, lksb->sb_lkid, &lkb); | 2490 | error = find_lkb(ls, lksb->sb_lkid, &lkb); |
@@ -2284,7 +2494,7 @@ int dlm_lock(dlm_lockspace_t *lockspace, | |||
2284 | if (error) | 2494 | if (error) |
2285 | goto out; | 2495 | goto out; |
2286 | 2496 | ||
2287 | error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast, | 2497 | error = set_lock_args(mode, lksb, flags, namelen, 0, ast, |
2288 | astarg, bast, &args); | 2498 | astarg, bast, &args); |
2289 | if (error) | 2499 | if (error) |
2290 | goto out_put; | 2500 | goto out_put; |
@@ -2299,10 +2509,10 @@ int dlm_lock(dlm_lockspace_t *lockspace, | |||
2299 | out_put: | 2509 | out_put: |
2300 | if (convert || error) | 2510 | if (convert || error) |
2301 | __put_lkb(ls, lkb); | 2511 | __put_lkb(ls, lkb); |
2302 | if (error == -EAGAIN) | 2512 | if (error == -EAGAIN || error == -EDEADLK) |
2303 | error = 0; | 2513 | error = 0; |
2304 | out: | 2514 | out: |
2305 | unlock_recovery(ls); | 2515 | dlm_unlock_recovery(ls); |
2306 | dlm_put_lockspace(ls); | 2516 | dlm_put_lockspace(ls); |
2307 | return error; | 2517 | return error; |
2308 | } | 2518 | } |
@@ -2322,7 +2532,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace, | |||
2322 | if (!ls) | 2532 | if (!ls) |
2323 | return -EINVAL; | 2533 | return -EINVAL; |
2324 | 2534 | ||
2325 | lock_recovery(ls); | 2535 | dlm_lock_recovery(ls); |
2326 | 2536 | ||
2327 | error = find_lkb(ls, lkid, &lkb); | 2537 | error = find_lkb(ls, lkid, &lkb); |
2328 | if (error) | 2538 | if (error) |
@@ -2344,7 +2554,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace, | |||
2344 | out_put: | 2554 | out_put: |
2345 | dlm_put_lkb(lkb); | 2555 | dlm_put_lkb(lkb); |
2346 | out: | 2556 | out: |
2347 | unlock_recovery(ls); | 2557 | dlm_unlock_recovery(ls); |
2348 | dlm_put_lockspace(ls); | 2558 | dlm_put_lockspace(ls); |
2349 | return error; | 2559 | return error; |
2350 | } | 2560 | } |
@@ -2384,7 +2594,7 @@ static int _create_message(struct dlm_ls *ls, int mb_len, | |||
2384 | pass into lowcomms_commit and a message buffer (mb) that we | 2594 | pass into lowcomms_commit and a message buffer (mb) that we |
2385 | write our data into */ | 2595 | write our data into */ |
2386 | 2596 | ||
2387 | mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb); | 2597 | mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb); |
2388 | if (!mh) | 2598 | if (!mh) |
2389 | return -ENOBUFS; | 2599 | return -ENOBUFS; |
2390 | 2600 | ||
@@ -3111,9 +3321,10 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3111 | lkb->lkb_remid = ms->m_lkid; | 3321 | lkb->lkb_remid = ms->m_lkid; |
3112 | if (is_altmode(lkb)) | 3322 | if (is_altmode(lkb)) |
3113 | munge_altmode(lkb, ms); | 3323 | munge_altmode(lkb, ms); |
3114 | if (result) | 3324 | if (result) { |
3115 | add_lkb(r, lkb, DLM_LKSTS_WAITING); | 3325 | add_lkb(r, lkb, DLM_LKSTS_WAITING); |
3116 | else { | 3326 | add_timeout(lkb); |
3327 | } else { | ||
3117 | grant_lock_pc(r, lkb, ms); | 3328 | grant_lock_pc(r, lkb, ms); |
3118 | queue_cast(r, lkb, 0); | 3329 | queue_cast(r, lkb, 0); |
3119 | } | 3330 | } |
@@ -3172,6 +3383,12 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
3172 | queue_cast(r, lkb, -EAGAIN); | 3383 | queue_cast(r, lkb, -EAGAIN); |
3173 | break; | 3384 | break; |
3174 | 3385 | ||
3386 | case -EDEADLK: | ||
3387 | receive_flags_reply(lkb, ms); | ||
3388 | revert_lock_pc(r, lkb); | ||
3389 | queue_cast(r, lkb, -EDEADLK); | ||
3390 | break; | ||
3391 | |||
3175 | case -EINPROGRESS: | 3392 | case -EINPROGRESS: |
3176 | /* convert was queued on remote master */ | 3393 | /* convert was queued on remote master */ |
3177 | receive_flags_reply(lkb, ms); | 3394 | receive_flags_reply(lkb, ms); |
@@ -3179,6 +3396,7 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
3179 | munge_demoted(lkb, ms); | 3396 | munge_demoted(lkb, ms); |
3180 | del_lkb(r, lkb); | 3397 | del_lkb(r, lkb); |
3181 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); | 3398 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); |
3399 | add_timeout(lkb); | ||
3182 | break; | 3400 | break; |
3183 | 3401 | ||
3184 | case 0: | 3402 | case 0: |
@@ -3298,8 +3516,7 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | |||
3298 | case -DLM_ECANCEL: | 3516 | case -DLM_ECANCEL: |
3299 | receive_flags_reply(lkb, ms); | 3517 | receive_flags_reply(lkb, ms); |
3300 | revert_lock_pc(r, lkb); | 3518 | revert_lock_pc(r, lkb); |
3301 | if (ms->m_result) | 3519 | queue_cast(r, lkb, -DLM_ECANCEL); |
3302 | queue_cast(r, lkb, -DLM_ECANCEL); | ||
3303 | break; | 3520 | break; |
3304 | case 0: | 3521 | case 0: |
3305 | break; | 3522 | break; |
@@ -3424,7 +3641,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) | |||
3424 | } | 3641 | } |
3425 | } | 3642 | } |
3426 | 3643 | ||
3427 | if (lock_recovery_try(ls)) | 3644 | if (dlm_lock_recovery_try(ls)) |
3428 | break; | 3645 | break; |
3429 | schedule(); | 3646 | schedule(); |
3430 | } | 3647 | } |
@@ -3503,7 +3720,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) | |||
3503 | log_error(ls, "unknown message type %d", ms->m_type); | 3720 | log_error(ls, "unknown message type %d", ms->m_type); |
3504 | } | 3721 | } |
3505 | 3722 | ||
3506 | unlock_recovery(ls); | 3723 | dlm_unlock_recovery(ls); |
3507 | out: | 3724 | out: |
3508 | dlm_put_lockspace(ls); | 3725 | dlm_put_lockspace(ls); |
3509 | dlm_astd_wake(); | 3726 | dlm_astd_wake(); |
@@ -4034,13 +4251,13 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
4034 | 4251 | ||
4035 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | 4252 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, |
4036 | int mode, uint32_t flags, void *name, unsigned int namelen, | 4253 | int mode, uint32_t flags, void *name, unsigned int namelen, |
4037 | uint32_t parent_lkid) | 4254 | unsigned long timeout_cs) |
4038 | { | 4255 | { |
4039 | struct dlm_lkb *lkb; | 4256 | struct dlm_lkb *lkb; |
4040 | struct dlm_args args; | 4257 | struct dlm_args args; |
4041 | int error; | 4258 | int error; |
4042 | 4259 | ||
4043 | lock_recovery(ls); | 4260 | dlm_lock_recovery(ls); |
4044 | 4261 | ||
4045 | error = create_lkb(ls, &lkb); | 4262 | error = create_lkb(ls, &lkb); |
4046 | if (error) { | 4263 | if (error) { |
@@ -4062,7 +4279,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
4062 | When DLM_IFL_USER is set, the dlm knows that this is a userspace | 4279 | When DLM_IFL_USER is set, the dlm knows that this is a userspace |
4063 | lock and that lkb_astparam is the dlm_user_args structure. */ | 4280 | lock and that lkb_astparam is the dlm_user_args structure. */ |
4064 | 4281 | ||
4065 | error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid, | 4282 | error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs, |
4066 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); | 4283 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); |
4067 | lkb->lkb_flags |= DLM_IFL_USER; | 4284 | lkb->lkb_flags |= DLM_IFL_USER; |
4068 | ua->old_mode = DLM_LOCK_IV; | 4285 | ua->old_mode = DLM_LOCK_IV; |
@@ -4094,19 +4311,20 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
4094 | list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); | 4311 | list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); |
4095 | spin_unlock(&ua->proc->locks_spin); | 4312 | spin_unlock(&ua->proc->locks_spin); |
4096 | out: | 4313 | out: |
4097 | unlock_recovery(ls); | 4314 | dlm_unlock_recovery(ls); |
4098 | return error; | 4315 | return error; |
4099 | } | 4316 | } |
4100 | 4317 | ||
4101 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 4318 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
4102 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in) | 4319 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in, |
4320 | unsigned long timeout_cs) | ||
4103 | { | 4321 | { |
4104 | struct dlm_lkb *lkb; | 4322 | struct dlm_lkb *lkb; |
4105 | struct dlm_args args; | 4323 | struct dlm_args args; |
4106 | struct dlm_user_args *ua; | 4324 | struct dlm_user_args *ua; |
4107 | int error; | 4325 | int error; |
4108 | 4326 | ||
4109 | lock_recovery(ls); | 4327 | dlm_lock_recovery(ls); |
4110 | 4328 | ||
4111 | error = find_lkb(ls, lkid, &lkb); | 4329 | error = find_lkb(ls, lkid, &lkb); |
4112 | if (error) | 4330 | if (error) |
@@ -4127,6 +4345,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4127 | if (lvb_in && ua->lksb.sb_lvbptr) | 4345 | if (lvb_in && ua->lksb.sb_lvbptr) |
4128 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); | 4346 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); |
4129 | 4347 | ||
4348 | ua->xid = ua_tmp->xid; | ||
4130 | ua->castparam = ua_tmp->castparam; | 4349 | ua->castparam = ua_tmp->castparam; |
4131 | ua->castaddr = ua_tmp->castaddr; | 4350 | ua->castaddr = ua_tmp->castaddr; |
4132 | ua->bastparam = ua_tmp->bastparam; | 4351 | ua->bastparam = ua_tmp->bastparam; |
@@ -4134,19 +4353,19 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4134 | ua->user_lksb = ua_tmp->user_lksb; | 4353 | ua->user_lksb = ua_tmp->user_lksb; |
4135 | ua->old_mode = lkb->lkb_grmode; | 4354 | ua->old_mode = lkb->lkb_grmode; |
4136 | 4355 | ||
4137 | error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST, | 4356 | error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs, |
4138 | ua, DLM_FAKE_USER_AST, &args); | 4357 | DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); |
4139 | if (error) | 4358 | if (error) |
4140 | goto out_put; | 4359 | goto out_put; |
4141 | 4360 | ||
4142 | error = convert_lock(ls, lkb, &args); | 4361 | error = convert_lock(ls, lkb, &args); |
4143 | 4362 | ||
4144 | if (error == -EINPROGRESS || error == -EAGAIN) | 4363 | if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK) |
4145 | error = 0; | 4364 | error = 0; |
4146 | out_put: | 4365 | out_put: |
4147 | dlm_put_lkb(lkb); | 4366 | dlm_put_lkb(lkb); |
4148 | out: | 4367 | out: |
4149 | unlock_recovery(ls); | 4368 | dlm_unlock_recovery(ls); |
4150 | kfree(ua_tmp); | 4369 | kfree(ua_tmp); |
4151 | return error; | 4370 | return error; |
4152 | } | 4371 | } |
@@ -4159,7 +4378,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4159 | struct dlm_user_args *ua; | 4378 | struct dlm_user_args *ua; |
4160 | int error; | 4379 | int error; |
4161 | 4380 | ||
4162 | lock_recovery(ls); | 4381 | dlm_lock_recovery(ls); |
4163 | 4382 | ||
4164 | error = find_lkb(ls, lkid, &lkb); | 4383 | error = find_lkb(ls, lkid, &lkb); |
4165 | if (error) | 4384 | if (error) |
@@ -4194,7 +4413,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4194 | out_put: | 4413 | out_put: |
4195 | dlm_put_lkb(lkb); | 4414 | dlm_put_lkb(lkb); |
4196 | out: | 4415 | out: |
4197 | unlock_recovery(ls); | 4416 | dlm_unlock_recovery(ls); |
4198 | kfree(ua_tmp); | 4417 | kfree(ua_tmp); |
4199 | return error; | 4418 | return error; |
4200 | } | 4419 | } |
@@ -4207,7 +4426,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4207 | struct dlm_user_args *ua; | 4426 | struct dlm_user_args *ua; |
4208 | int error; | 4427 | int error; |
4209 | 4428 | ||
4210 | lock_recovery(ls); | 4429 | dlm_lock_recovery(ls); |
4211 | 4430 | ||
4212 | error = find_lkb(ls, lkid, &lkb); | 4431 | error = find_lkb(ls, lkid, &lkb); |
4213 | if (error) | 4432 | if (error) |
@@ -4231,11 +4450,59 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4231 | out_put: | 4450 | out_put: |
4232 | dlm_put_lkb(lkb); | 4451 | dlm_put_lkb(lkb); |
4233 | out: | 4452 | out: |
4234 | unlock_recovery(ls); | 4453 | dlm_unlock_recovery(ls); |
4235 | kfree(ua_tmp); | 4454 | kfree(ua_tmp); |
4236 | return error; | 4455 | return error; |
4237 | } | 4456 | } |
4238 | 4457 | ||
4458 | int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid) | ||
4459 | { | ||
4460 | struct dlm_lkb *lkb; | ||
4461 | struct dlm_args args; | ||
4462 | struct dlm_user_args *ua; | ||
4463 | struct dlm_rsb *r; | ||
4464 | int error; | ||
4465 | |||
4466 | dlm_lock_recovery(ls); | ||
4467 | |||
4468 | error = find_lkb(ls, lkid, &lkb); | ||
4469 | if (error) | ||
4470 | goto out; | ||
4471 | |||
4472 | ua = (struct dlm_user_args *)lkb->lkb_astparam; | ||
4473 | |||
4474 | error = set_unlock_args(flags, ua, &args); | ||
4475 | if (error) | ||
4476 | goto out_put; | ||
4477 | |||
4478 | /* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */ | ||
4479 | |||
4480 | r = lkb->lkb_resource; | ||
4481 | hold_rsb(r); | ||
4482 | lock_rsb(r); | ||
4483 | |||
4484 | error = validate_unlock_args(lkb, &args); | ||
4485 | if (error) | ||
4486 | goto out_r; | ||
4487 | lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL; | ||
4488 | |||
4489 | error = _cancel_lock(r, lkb); | ||
4490 | out_r: | ||
4491 | unlock_rsb(r); | ||
4492 | put_rsb(r); | ||
4493 | |||
4494 | if (error == -DLM_ECANCEL) | ||
4495 | error = 0; | ||
4496 | /* from validate_unlock_args() */ | ||
4497 | if (error == -EBUSY) | ||
4498 | error = 0; | ||
4499 | out_put: | ||
4500 | dlm_put_lkb(lkb); | ||
4501 | out: | ||
4502 | dlm_unlock_recovery(ls); | ||
4503 | return error; | ||
4504 | } | ||
4505 | |||
4239 | /* lkb's that are removed from the waiters list by revert are just left on the | 4506 | /* lkb's that are removed from the waiters list by revert are just left on the |
4240 | orphans list with the granted orphan locks, to be freed by purge */ | 4507 | orphans list with the granted orphan locks, to be freed by purge */ |
4241 | 4508 | ||
@@ -4314,12 +4581,13 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
4314 | { | 4581 | { |
4315 | struct dlm_lkb *lkb, *safe; | 4582 | struct dlm_lkb *lkb, *safe; |
4316 | 4583 | ||
4317 | lock_recovery(ls); | 4584 | dlm_lock_recovery(ls); |
4318 | 4585 | ||
4319 | while (1) { | 4586 | while (1) { |
4320 | lkb = del_proc_lock(ls, proc); | 4587 | lkb = del_proc_lock(ls, proc); |
4321 | if (!lkb) | 4588 | if (!lkb) |
4322 | break; | 4589 | break; |
4590 | del_timeout(lkb); | ||
4323 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) | 4591 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) |
4324 | orphan_proc_lock(ls, lkb); | 4592 | orphan_proc_lock(ls, lkb); |
4325 | else | 4593 | else |
@@ -4347,7 +4615,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
4347 | } | 4615 | } |
4348 | 4616 | ||
4349 | mutex_unlock(&ls->ls_clear_proc_locks); | 4617 | mutex_unlock(&ls->ls_clear_proc_locks); |
4350 | unlock_recovery(ls); | 4618 | dlm_unlock_recovery(ls); |
4351 | } | 4619 | } |
4352 | 4620 | ||
4353 | static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | 4621 | static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) |
@@ -4429,12 +4697,12 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc, | |||
4429 | if (nodeid != dlm_our_nodeid()) { | 4697 | if (nodeid != dlm_our_nodeid()) { |
4430 | error = send_purge(ls, nodeid, pid); | 4698 | error = send_purge(ls, nodeid, pid); |
4431 | } else { | 4699 | } else { |
4432 | lock_recovery(ls); | 4700 | dlm_lock_recovery(ls); |
4433 | if (pid == current->pid) | 4701 | if (pid == current->pid) |
4434 | purge_proc_locks(ls, proc); | 4702 | purge_proc_locks(ls, proc); |
4435 | else | 4703 | else |
4436 | do_purge(ls, nodeid, pid); | 4704 | do_purge(ls, nodeid, pid); |
4437 | unlock_recovery(ls); | 4705 | dlm_unlock_recovery(ls); |
4438 | } | 4706 | } |
4439 | return error; | 4707 | return error; |
4440 | } | 4708 | } |
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h index 64fc4ec40668..1720313c22df 100644 --- a/fs/dlm/lock.h +++ b/fs/dlm/lock.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -24,6 +24,10 @@ void dlm_put_rsb(struct dlm_rsb *r); | |||
24 | void dlm_hold_rsb(struct dlm_rsb *r); | 24 | void dlm_hold_rsb(struct dlm_rsb *r); |
25 | int dlm_put_lkb(struct dlm_lkb *lkb); | 25 | int dlm_put_lkb(struct dlm_lkb *lkb); |
26 | void dlm_scan_rsbs(struct dlm_ls *ls); | 26 | void dlm_scan_rsbs(struct dlm_ls *ls); |
27 | int dlm_lock_recovery_try(struct dlm_ls *ls); | ||
28 | void dlm_unlock_recovery(struct dlm_ls *ls); | ||
29 | void dlm_scan_timeout(struct dlm_ls *ls); | ||
30 | void dlm_adjust_timeouts(struct dlm_ls *ls); | ||
27 | 31 | ||
28 | int dlm_purge_locks(struct dlm_ls *ls); | 32 | int dlm_purge_locks(struct dlm_ls *ls); |
29 | void dlm_purge_mstcpy_locks(struct dlm_rsb *r); | 33 | void dlm_purge_mstcpy_locks(struct dlm_rsb *r); |
@@ -34,15 +38,18 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc); | |||
34 | int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc); | 38 | int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc); |
35 | 39 | ||
36 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode, | 40 | int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode, |
37 | uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid); | 41 | uint32_t flags, void *name, unsigned int namelen, |
42 | unsigned long timeout_cs); | ||
38 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 43 | int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
39 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in); | 44 | int mode, uint32_t flags, uint32_t lkid, char *lvb_in, |
45 | unsigned long timeout_cs); | ||
40 | int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 46 | int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
41 | uint32_t flags, uint32_t lkid, char *lvb_in); | 47 | uint32_t flags, uint32_t lkid, char *lvb_in); |
42 | int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | 48 | int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, |
43 | uint32_t flags, uint32_t lkid); | 49 | uint32_t flags, uint32_t lkid); |
44 | int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc, | 50 | int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc, |
45 | int nodeid, int pid); | 51 | int nodeid, int pid); |
52 | int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid); | ||
46 | void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc); | 53 | void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc); |
47 | 54 | ||
48 | static inline int is_master(struct dlm_rsb *r) | 55 | static inline int is_master(struct dlm_rsb *r) |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index a677b2a5eed4..1dc72105ab12 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -197,13 +197,24 @@ static int do_uevent(struct dlm_ls *ls, int in) | |||
197 | else | 197 | else |
198 | kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE); | 198 | kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE); |
199 | 199 | ||
200 | log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving"); | ||
201 | |||
202 | /* dlm_controld will see the uevent, do the necessary group management | ||
203 | and then write to sysfs to wake us */ | ||
204 | |||
200 | error = wait_event_interruptible(ls->ls_uevent_wait, | 205 | error = wait_event_interruptible(ls->ls_uevent_wait, |
201 | test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags)); | 206 | test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags)); |
207 | |||
208 | log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result); | ||
209 | |||
202 | if (error) | 210 | if (error) |
203 | goto out; | 211 | goto out; |
204 | 212 | ||
205 | error = ls->ls_uevent_result; | 213 | error = ls->ls_uevent_result; |
206 | out: | 214 | out: |
215 | if (error) | ||
216 | log_error(ls, "group %s failed %d %d", in ? "join" : "leave", | ||
217 | error, ls->ls_uevent_result); | ||
207 | return error; | 218 | return error; |
208 | } | 219 | } |
209 | 220 | ||
@@ -234,8 +245,13 @@ static int dlm_scand(void *data) | |||
234 | struct dlm_ls *ls; | 245 | struct dlm_ls *ls; |
235 | 246 | ||
236 | while (!kthread_should_stop()) { | 247 | while (!kthread_should_stop()) { |
237 | list_for_each_entry(ls, &lslist, ls_list) | 248 | list_for_each_entry(ls, &lslist, ls_list) { |
238 | dlm_scan_rsbs(ls); | 249 | if (dlm_lock_recovery_try(ls)) { |
250 | dlm_scan_rsbs(ls); | ||
251 | dlm_scan_timeout(ls); | ||
252 | dlm_unlock_recovery(ls); | ||
253 | } | ||
254 | } | ||
239 | schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); | 255 | schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); |
240 | } | 256 | } |
241 | return 0; | 257 | return 0; |
@@ -395,6 +411,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
395 | { | 411 | { |
396 | struct dlm_ls *ls; | 412 | struct dlm_ls *ls; |
397 | int i, size, error = -ENOMEM; | 413 | int i, size, error = -ENOMEM; |
414 | int do_unreg = 0; | ||
398 | 415 | ||
399 | if (namelen > DLM_LOCKSPACE_LEN) | 416 | if (namelen > DLM_LOCKSPACE_LEN) |
400 | return -EINVAL; | 417 | return -EINVAL; |
@@ -417,11 +434,22 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
417 | goto out; | 434 | goto out; |
418 | memcpy(ls->ls_name, name, namelen); | 435 | memcpy(ls->ls_name, name, namelen); |
419 | ls->ls_namelen = namelen; | 436 | ls->ls_namelen = namelen; |
420 | ls->ls_exflags = flags; | ||
421 | ls->ls_lvblen = lvblen; | 437 | ls->ls_lvblen = lvblen; |
422 | ls->ls_count = 0; | 438 | ls->ls_count = 0; |
423 | ls->ls_flags = 0; | 439 | ls->ls_flags = 0; |
424 | 440 | ||
441 | if (flags & DLM_LSFL_TIMEWARN) | ||
442 | set_bit(LSFL_TIMEWARN, &ls->ls_flags); | ||
443 | |||
444 | if (flags & DLM_LSFL_FS) | ||
445 | ls->ls_allocation = GFP_NOFS; | ||
446 | else | ||
447 | ls->ls_allocation = GFP_KERNEL; | ||
448 | |||
449 | /* ls_exflags are forced to match among nodes, and we don't | ||
450 | need to require all nodes to have TIMEWARN or FS set */ | ||
451 | ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS)); | ||
452 | |||
425 | size = dlm_config.ci_rsbtbl_size; | 453 | size = dlm_config.ci_rsbtbl_size; |
426 | ls->ls_rsbtbl_size = size; | 454 | ls->ls_rsbtbl_size = size; |
427 | 455 | ||
@@ -461,6 +489,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
461 | mutex_init(&ls->ls_waiters_mutex); | 489 | mutex_init(&ls->ls_waiters_mutex); |
462 | INIT_LIST_HEAD(&ls->ls_orphans); | 490 | INIT_LIST_HEAD(&ls->ls_orphans); |
463 | mutex_init(&ls->ls_orphans_mutex); | 491 | mutex_init(&ls->ls_orphans_mutex); |
492 | INIT_LIST_HEAD(&ls->ls_timeout); | ||
493 | mutex_init(&ls->ls_timeout_mutex); | ||
464 | 494 | ||
465 | INIT_LIST_HEAD(&ls->ls_nodes); | 495 | INIT_LIST_HEAD(&ls->ls_nodes); |
466 | INIT_LIST_HEAD(&ls->ls_nodes_gone); | 496 | INIT_LIST_HEAD(&ls->ls_nodes_gone); |
@@ -477,6 +507,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
477 | 507 | ||
478 | init_waitqueue_head(&ls->ls_uevent_wait); | 508 | init_waitqueue_head(&ls->ls_uevent_wait); |
479 | ls->ls_uevent_result = 0; | 509 | ls->ls_uevent_result = 0; |
510 | init_completion(&ls->ls_members_done); | ||
511 | ls->ls_members_result = -1; | ||
480 | 512 | ||
481 | ls->ls_recoverd_task = NULL; | 513 | ls->ls_recoverd_task = NULL; |
482 | mutex_init(&ls->ls_recoverd_active); | 514 | mutex_init(&ls->ls_recoverd_active); |
@@ -513,32 +545,49 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
513 | error = dlm_recoverd_start(ls); | 545 | error = dlm_recoverd_start(ls); |
514 | if (error) { | 546 | if (error) { |
515 | log_error(ls, "can't start dlm_recoverd %d", error); | 547 | log_error(ls, "can't start dlm_recoverd %d", error); |
516 | goto out_rcomfree; | 548 | goto out_delist; |
517 | } | 549 | } |
518 | 550 | ||
519 | dlm_create_debug_file(ls); | ||
520 | |||
521 | error = kobject_setup(ls); | 551 | error = kobject_setup(ls); |
522 | if (error) | 552 | if (error) |
523 | goto out_del; | 553 | goto out_stop; |
524 | 554 | ||
525 | error = kobject_register(&ls->ls_kobj); | 555 | error = kobject_register(&ls->ls_kobj); |
526 | if (error) | 556 | if (error) |
527 | goto out_del; | 557 | goto out_stop; |
558 | |||
559 | /* let kobject handle freeing of ls if there's an error */ | ||
560 | do_unreg = 1; | ||
561 | |||
562 | /* This uevent triggers dlm_controld in userspace to add us to the | ||
563 | group of nodes that are members of this lockspace (managed by the | ||
564 | cluster infrastructure.) Once it's done that, it tells us who the | ||
565 | current lockspace members are (via configfs) and then tells the | ||
566 | lockspace to start running (via sysfs) in dlm_ls_start(). */ | ||
528 | 567 | ||
529 | error = do_uevent(ls, 1); | 568 | error = do_uevent(ls, 1); |
530 | if (error) | 569 | if (error) |
531 | goto out_unreg; | 570 | goto out_stop; |
571 | |||
572 | wait_for_completion(&ls->ls_members_done); | ||
573 | error = ls->ls_members_result; | ||
574 | if (error) | ||
575 | goto out_members; | ||
576 | |||
577 | dlm_create_debug_file(ls); | ||
578 | |||
579 | log_debug(ls, "join complete"); | ||
532 | 580 | ||
533 | *lockspace = ls; | 581 | *lockspace = ls; |
534 | return 0; | 582 | return 0; |
535 | 583 | ||
536 | out_unreg: | 584 | out_members: |
537 | kobject_unregister(&ls->ls_kobj); | 585 | do_uevent(ls, 0); |
538 | out_del: | 586 | dlm_clear_members(ls); |
539 | dlm_delete_debug_file(ls); | 587 | kfree(ls->ls_node_array); |
588 | out_stop: | ||
540 | dlm_recoverd_stop(ls); | 589 | dlm_recoverd_stop(ls); |
541 | out_rcomfree: | 590 | out_delist: |
542 | spin_lock(&lslist_lock); | 591 | spin_lock(&lslist_lock); |
543 | list_del(&ls->ls_list); | 592 | list_del(&ls->ls_list); |
544 | spin_unlock(&lslist_lock); | 593 | spin_unlock(&lslist_lock); |
@@ -550,7 +599,10 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
550 | out_rsbfree: | 599 | out_rsbfree: |
551 | kfree(ls->ls_rsbtbl); | 600 | kfree(ls->ls_rsbtbl); |
552 | out_lsfree: | 601 | out_lsfree: |
553 | kfree(ls); | 602 | if (do_unreg) |
603 | kobject_unregister(&ls->ls_kobj); | ||
604 | else | ||
605 | kfree(ls); | ||
554 | out: | 606 | out: |
555 | module_put(THIS_MODULE); | 607 | module_put(THIS_MODULE); |
556 | return error; | 608 | return error; |
@@ -570,6 +622,8 @@ int dlm_new_lockspace(char *name, int namelen, void **lockspace, | |||
570 | error = new_lockspace(name, namelen, lockspace, flags, lvblen); | 622 | error = new_lockspace(name, namelen, lockspace, flags, lvblen); |
571 | if (!error) | 623 | if (!error) |
572 | ls_count++; | 624 | ls_count++; |
625 | else if (!ls_count) | ||
626 | threads_stop(); | ||
573 | out: | 627 | out: |
574 | mutex_unlock(&ls_lock); | 628 | mutex_unlock(&ls_lock); |
575 | return error; | 629 | return error; |
@@ -696,7 +750,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
696 | dlm_clear_members_gone(ls); | 750 | dlm_clear_members_gone(ls); |
697 | kfree(ls->ls_node_array); | 751 | kfree(ls->ls_node_array); |
698 | kobject_unregister(&ls->ls_kobj); | 752 | kobject_unregister(&ls->ls_kobj); |
699 | /* The ls structure will be freed when the kobject is done with */ | 753 | /* The ls structure will be freed when the kobject is done with */ |
700 | 754 | ||
701 | mutex_lock(&ls_lock); | 755 | mutex_lock(&ls_lock); |
702 | ls_count--; | 756 | ls_count--; |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 27970a58d29b..0553a6158dcb 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -260,7 +260,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) | |||
260 | static void lowcomms_data_ready(struct sock *sk, int count_unused) | 260 | static void lowcomms_data_ready(struct sock *sk, int count_unused) |
261 | { | 261 | { |
262 | struct connection *con = sock2con(sk); | 262 | struct connection *con = sock2con(sk); |
263 | if (!test_and_set_bit(CF_READ_PENDING, &con->flags)) | 263 | if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags)) |
264 | queue_work(recv_workqueue, &con->rwork); | 264 | queue_work(recv_workqueue, &con->rwork); |
265 | } | 265 | } |
266 | 266 | ||
@@ -268,7 +268,7 @@ static void lowcomms_write_space(struct sock *sk) | |||
268 | { | 268 | { |
269 | struct connection *con = sock2con(sk); | 269 | struct connection *con = sock2con(sk); |
270 | 270 | ||
271 | if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) | 271 | if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags)) |
272 | queue_work(send_workqueue, &con->swork); | 272 | queue_work(send_workqueue, &con->swork); |
273 | } | 273 | } |
274 | 274 | ||
@@ -720,11 +720,17 @@ static int tcp_accept_from_sock(struct connection *con) | |||
720 | INIT_WORK(&othercon->rwork, process_recv_sockets); | 720 | INIT_WORK(&othercon->rwork, process_recv_sockets); |
721 | set_bit(CF_IS_OTHERCON, &othercon->flags); | 721 | set_bit(CF_IS_OTHERCON, &othercon->flags); |
722 | newcon->othercon = othercon; | 722 | newcon->othercon = othercon; |
723 | othercon->sock = newsock; | ||
724 | newsock->sk->sk_user_data = othercon; | ||
725 | add_sock(newsock, othercon); | ||
726 | addcon = othercon; | ||
727 | } | ||
728 | else { | ||
729 | printk("Extra connection from node %d attempted\n", nodeid); | ||
730 | result = -EAGAIN; | ||
731 | mutex_unlock(&newcon->sock_mutex); | ||
732 | goto accept_err; | ||
723 | } | 733 | } |
724 | othercon->sock = newsock; | ||
725 | newsock->sk->sk_user_data = othercon; | ||
726 | add_sock(newsock, othercon); | ||
727 | addcon = othercon; | ||
728 | } | 734 | } |
729 | else { | 735 | else { |
730 | newsock->sk->sk_user_data = newcon; | 736 | newsock->sk->sk_user_data = newcon; |
@@ -1400,8 +1406,11 @@ void dlm_lowcomms_stop(void) | |||
1400 | down(&connections_lock); | 1406 | down(&connections_lock); |
1401 | for (i = 0; i <= max_nodeid; i++) { | 1407 | for (i = 0; i <= max_nodeid; i++) { |
1402 | con = __nodeid2con(i, 0); | 1408 | con = __nodeid2con(i, 0); |
1403 | if (con) | 1409 | if (con) { |
1404 | con->flags |= 0xFF; | 1410 | con->flags |= 0xFF; |
1411 | if (con->sock) | ||
1412 | con->sock->sk->sk_user_data = NULL; | ||
1413 | } | ||
1405 | } | 1414 | } |
1406 | up(&connections_lock); | 1415 | up(&connections_lock); |
1407 | 1416 | ||
diff --git a/fs/dlm/main.c b/fs/dlm/main.c index 162fbae58fe5..eca2907f2386 100644 --- a/fs/dlm/main.c +++ b/fs/dlm/main.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -25,6 +25,8 @@ void dlm_unregister_debugfs(void); | |||
25 | static inline int dlm_register_debugfs(void) { return 0; } | 25 | static inline int dlm_register_debugfs(void) { return 0; } |
26 | static inline void dlm_unregister_debugfs(void) { } | 26 | static inline void dlm_unregister_debugfs(void) { } |
27 | #endif | 27 | #endif |
28 | int dlm_netlink_init(void); | ||
29 | void dlm_netlink_exit(void); | ||
28 | 30 | ||
29 | static int __init init_dlm(void) | 31 | static int __init init_dlm(void) |
30 | { | 32 | { |
@@ -50,10 +52,16 @@ static int __init init_dlm(void) | |||
50 | if (error) | 52 | if (error) |
51 | goto out_debug; | 53 | goto out_debug; |
52 | 54 | ||
55 | error = dlm_netlink_init(); | ||
56 | if (error) | ||
57 | goto out_user; | ||
58 | |||
53 | printk("DLM (built %s %s) installed\n", __DATE__, __TIME__); | 59 | printk("DLM (built %s %s) installed\n", __DATE__, __TIME__); |
54 | 60 | ||
55 | return 0; | 61 | return 0; |
56 | 62 | ||
63 | out_user: | ||
64 | dlm_user_exit(); | ||
57 | out_debug: | 65 | out_debug: |
58 | dlm_unregister_debugfs(); | 66 | dlm_unregister_debugfs(); |
59 | out_config: | 67 | out_config: |
@@ -68,6 +76,7 @@ static int __init init_dlm(void) | |||
68 | 76 | ||
69 | static void __exit exit_dlm(void) | 77 | static void __exit exit_dlm(void) |
70 | { | 78 | { |
79 | dlm_netlink_exit(); | ||
71 | dlm_user_exit(); | 80 | dlm_user_exit(); |
72 | dlm_config_exit(); | 81 | dlm_config_exit(); |
73 | dlm_memory_exit(); | 82 | dlm_memory_exit(); |
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index 85e2897bd740..073599dced2a 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -233,6 +233,12 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | |||
233 | *neg_out = neg; | 233 | *neg_out = neg; |
234 | 234 | ||
235 | error = ping_members(ls); | 235 | error = ping_members(ls); |
236 | if (!error || error == -EPROTO) { | ||
237 | /* new_lockspace() may be waiting to know if the config | ||
238 | is good or bad */ | ||
239 | ls->ls_members_result = error; | ||
240 | complete(&ls->ls_members_done); | ||
241 | } | ||
236 | if (error) | 242 | if (error) |
237 | goto out; | 243 | goto out; |
238 | 244 | ||
@@ -284,6 +290,9 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
284 | dlm_recoverd_suspend(ls); | 290 | dlm_recoverd_suspend(ls); |
285 | ls->ls_recover_status = 0; | 291 | ls->ls_recover_status = 0; |
286 | dlm_recoverd_resume(ls); | 292 | dlm_recoverd_resume(ls); |
293 | |||
294 | if (!ls->ls_recover_begin) | ||
295 | ls->ls_recover_begin = jiffies; | ||
287 | return 0; | 296 | return 0; |
288 | } | 297 | } |
289 | 298 | ||
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c new file mode 100644 index 000000000000..863b87d0dc71 --- /dev/null +++ b/fs/dlm/netlink.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||
3 | * | ||
4 | * This copyrighted material is made available to anyone wishing to use, | ||
5 | * modify, copy, or redistribute it subject to the terms and conditions | ||
6 | * of the GNU General Public License v.2. | ||
7 | */ | ||
8 | |||
9 | #include <net/genetlink.h> | ||
10 | #include <linux/dlm.h> | ||
11 | #include <linux/dlm_netlink.h> | ||
12 | |||
13 | #include "dlm_internal.h" | ||
14 | |||
15 | static uint32_t dlm_nl_seqnum; | ||
16 | static uint32_t listener_nlpid; | ||
17 | |||
18 | static struct genl_family family = { | ||
19 | .id = GENL_ID_GENERATE, | ||
20 | .name = DLM_GENL_NAME, | ||
21 | .version = DLM_GENL_VERSION, | ||
22 | }; | ||
23 | |||
24 | static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size) | ||
25 | { | ||
26 | struct sk_buff *skb; | ||
27 | void *data; | ||
28 | |||
29 | skb = genlmsg_new(size, GFP_KERNEL); | ||
30 | if (!skb) | ||
31 | return -ENOMEM; | ||
32 | |||
33 | /* add the message headers */ | ||
34 | data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd); | ||
35 | if (!data) { | ||
36 | nlmsg_free(skb); | ||
37 | return -EINVAL; | ||
38 | } | ||
39 | |||
40 | *skbp = skb; | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static struct dlm_lock_data *mk_data(struct sk_buff *skb) | ||
45 | { | ||
46 | struct nlattr *ret; | ||
47 | |||
48 | ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data)); | ||
49 | if (!ret) | ||
50 | return NULL; | ||
51 | return nla_data(ret); | ||
52 | } | ||
53 | |||
54 | static int send_data(struct sk_buff *skb) | ||
55 | { | ||
56 | struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); | ||
57 | void *data = genlmsg_data(genlhdr); | ||
58 | int rv; | ||
59 | |||
60 | rv = genlmsg_end(skb, data); | ||
61 | if (rv < 0) { | ||
62 | nlmsg_free(skb); | ||
63 | return rv; | ||
64 | } | ||
65 | |||
66 | return genlmsg_unicast(skb, listener_nlpid); | ||
67 | } | ||
68 | |||
69 | static int user_cmd(struct sk_buff *skb, struct genl_info *info) | ||
70 | { | ||
71 | listener_nlpid = info->snd_pid; | ||
72 | printk("user_cmd nlpid %u\n", listener_nlpid); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static struct genl_ops dlm_nl_ops = { | ||
77 | .cmd = DLM_CMD_HELLO, | ||
78 | .doit = user_cmd, | ||
79 | }; | ||
80 | |||
81 | int dlm_netlink_init(void) | ||
82 | { | ||
83 | int rv; | ||
84 | |||
85 | rv = genl_register_family(&family); | ||
86 | if (rv) | ||
87 | return rv; | ||
88 | |||
89 | rv = genl_register_ops(&family, &dlm_nl_ops); | ||
90 | if (rv < 0) | ||
91 | goto err; | ||
92 | return 0; | ||
93 | err: | ||
94 | genl_unregister_family(&family); | ||
95 | return rv; | ||
96 | } | ||
97 | |||
98 | void dlm_netlink_exit(void) | ||
99 | { | ||
100 | genl_unregister_ops(&family, &dlm_nl_ops); | ||
101 | genl_unregister_family(&family); | ||
102 | } | ||
103 | |||
104 | static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) | ||
105 | { | ||
106 | struct dlm_rsb *r = lkb->lkb_resource; | ||
107 | struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam; | ||
108 | |||
109 | memset(data, 0, sizeof(struct dlm_lock_data)); | ||
110 | |||
111 | data->version = DLM_LOCK_DATA_VERSION; | ||
112 | data->nodeid = lkb->lkb_nodeid; | ||
113 | data->ownpid = lkb->lkb_ownpid; | ||
114 | data->id = lkb->lkb_id; | ||
115 | data->remid = lkb->lkb_remid; | ||
116 | data->status = lkb->lkb_status; | ||
117 | data->grmode = lkb->lkb_grmode; | ||
118 | data->rqmode = lkb->lkb_rqmode; | ||
119 | data->timestamp = lkb->lkb_timestamp; | ||
120 | if (ua) | ||
121 | data->xid = ua->xid; | ||
122 | if (r) { | ||
123 | data->lockspace_id = r->res_ls->ls_global_id; | ||
124 | data->resource_namelen = r->res_length; | ||
125 | memcpy(data->resource_name, r->res_name, r->res_length); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void dlm_timeout_warn(struct dlm_lkb *lkb) | ||
130 | { | ||
131 | struct dlm_lock_data *data; | ||
132 | struct sk_buff *send_skb; | ||
133 | size_t size; | ||
134 | int rv; | ||
135 | |||
136 | size = nla_total_size(sizeof(struct dlm_lock_data)) + | ||
137 | nla_total_size(0); /* why this? */ | ||
138 | |||
139 | rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size); | ||
140 | if (rv < 0) | ||
141 | return; | ||
142 | |||
143 | data = mk_data(send_skb); | ||
144 | if (!data) { | ||
145 | nlmsg_free(send_skb); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | fill_data(data, lkb); | ||
150 | |||
151 | send_data(send_skb); | ||
152 | } | ||
153 | |||
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 6bfbd6153809..e3a1527cbdbe 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -38,7 +38,7 @@ static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, | |||
38 | char *mb; | 38 | char *mb; |
39 | int mb_len = sizeof(struct dlm_rcom) + len; | 39 | int mb_len = sizeof(struct dlm_rcom) + len; |
40 | 40 | ||
41 | mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb); | 41 | mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb); |
42 | if (!mh) { | 42 | if (!mh) { |
43 | log_print("create_rcom to %d type %d len %d ENOBUFS", | 43 | log_print("create_rcom to %d type %d len %d ENOBUFS", |
44 | to_nodeid, type, len); | 44 | to_nodeid, type, len); |
@@ -90,7 +90,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
90 | log_error(ls, "version mismatch: %x nodeid %d: %x", | 90 | log_error(ls, "version mismatch: %x nodeid %d: %x", |
91 | DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, | 91 | DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, |
92 | rc->rc_header.h_version); | 92 | rc->rc_header.h_version); |
93 | return -EINVAL; | 93 | return -EPROTO; |
94 | } | 94 | } |
95 | 95 | ||
96 | if (rf->rf_lvblen != ls->ls_lvblen || | 96 | if (rf->rf_lvblen != ls->ls_lvblen || |
@@ -98,7 +98,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
98 | log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", | 98 | log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", |
99 | ls->ls_lvblen, ls->ls_exflags, | 99 | ls->ls_lvblen, ls->ls_exflags, |
100 | nodeid, rf->rf_lvblen, rf->rf_lsflags); | 100 | nodeid, rf->rf_lvblen, rf->rf_lsflags); |
101 | return -EINVAL; | 101 | return -EPROTO; |
102 | } | 102 | } |
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
@@ -386,7 +386,8 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
386 | dlm_recover_process_copy(ls, rc_in); | 386 | dlm_recover_process_copy(ls, rc_in); |
387 | } | 387 | } |
388 | 388 | ||
389 | static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) | 389 | static int send_ls_not_ready(struct dlm_ls *ls, int nodeid, |
390 | struct dlm_rcom *rc_in) | ||
390 | { | 391 | { |
391 | struct dlm_rcom *rc; | 392 | struct dlm_rcom *rc; |
392 | struct rcom_config *rf; | 393 | struct rcom_config *rf; |
@@ -394,7 +395,7 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) | |||
394 | char *mb; | 395 | char *mb; |
395 | int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); | 396 | int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); |
396 | 397 | ||
397 | mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb); | 398 | mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb); |
398 | if (!mh) | 399 | if (!mh) |
399 | return -ENOBUFS; | 400 | return -ENOBUFS; |
400 | memset(mb, 0, mb_len); | 401 | memset(mb, 0, mb_len); |
@@ -464,7 +465,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) | |||
464 | log_print("lockspace %x from %d type %x not found", | 465 | log_print("lockspace %x from %d type %x not found", |
465 | hd->h_lockspace, nodeid, rc->rc_type); | 466 | hd->h_lockspace, nodeid, rc->rc_type); |
466 | if (rc->rc_type == DLM_RCOM_STATUS) | 467 | if (rc->rc_type == DLM_RCOM_STATUS) |
467 | send_ls_not_ready(nodeid, rc); | 468 | send_ls_not_ready(ls, nodeid, rc); |
468 | return; | 469 | return; |
469 | } | 470 | } |
470 | 471 | ||
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 3cb636d60249..66575997861c 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -190,6 +190,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
190 | 190 | ||
191 | dlm_clear_members_gone(ls); | 191 | dlm_clear_members_gone(ls); |
192 | 192 | ||
193 | dlm_adjust_timeouts(ls); | ||
194 | |||
193 | error = enable_locking(ls, rv->seq); | 195 | error = enable_locking(ls, rv->seq); |
194 | if (error) { | 196 | if (error) { |
195 | log_debug(ls, "enable_locking failed %d", error); | 197 | log_debug(ls, "enable_locking failed %d", error); |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index b0201ec325a7..6438941ab1f8 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -33,16 +33,17 @@ static const struct file_operations device_fops; | |||
33 | struct dlm_lock_params32 { | 33 | struct dlm_lock_params32 { |
34 | __u8 mode; | 34 | __u8 mode; |
35 | __u8 namelen; | 35 | __u8 namelen; |
36 | __u16 flags; | 36 | __u16 unused; |
37 | __u32 flags; | ||
37 | __u32 lkid; | 38 | __u32 lkid; |
38 | __u32 parent; | 39 | __u32 parent; |
39 | 40 | __u64 xid; | |
41 | __u64 timeout; | ||
40 | __u32 castparam; | 42 | __u32 castparam; |
41 | __u32 castaddr; | 43 | __u32 castaddr; |
42 | __u32 bastparam; | 44 | __u32 bastparam; |
43 | __u32 bastaddr; | 45 | __u32 bastaddr; |
44 | __u32 lksb; | 46 | __u32 lksb; |
45 | |||
46 | char lvb[DLM_USER_LVB_LEN]; | 47 | char lvb[DLM_USER_LVB_LEN]; |
47 | char name[0]; | 48 | char name[0]; |
48 | }; | 49 | }; |
@@ -68,6 +69,7 @@ struct dlm_lksb32 { | |||
68 | }; | 69 | }; |
69 | 70 | ||
70 | struct dlm_lock_result32 { | 71 | struct dlm_lock_result32 { |
72 | __u32 version[3]; | ||
71 | __u32 length; | 73 | __u32 length; |
72 | __u32 user_astaddr; | 74 | __u32 user_astaddr; |
73 | __u32 user_astparam; | 75 | __u32 user_astparam; |
@@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb, | |||
102 | kb->i.lock.flags = kb32->i.lock.flags; | 104 | kb->i.lock.flags = kb32->i.lock.flags; |
103 | kb->i.lock.lkid = kb32->i.lock.lkid; | 105 | kb->i.lock.lkid = kb32->i.lock.lkid; |
104 | kb->i.lock.parent = kb32->i.lock.parent; | 106 | kb->i.lock.parent = kb32->i.lock.parent; |
107 | kb->i.lock.xid = kb32->i.lock.xid; | ||
108 | kb->i.lock.timeout = kb32->i.lock.timeout; | ||
105 | kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam; | 109 | kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam; |
106 | kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr; | 110 | kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr; |
107 | kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam; | 111 | kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam; |
@@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb, | |||
115 | static void compat_output(struct dlm_lock_result *res, | 119 | static void compat_output(struct dlm_lock_result *res, |
116 | struct dlm_lock_result32 *res32) | 120 | struct dlm_lock_result32 *res32) |
117 | { | 121 | { |
122 | res32->version[0] = res->version[0]; | ||
123 | res32->version[1] = res->version[1]; | ||
124 | res32->version[2] = res->version[2]; | ||
125 | |||
118 | res32->user_astaddr = (__u32)(long)res->user_astaddr; | 126 | res32->user_astaddr = (__u32)(long)res->user_astaddr; |
119 | res32->user_astparam = (__u32)(long)res->user_astparam; | 127 | res32->user_astparam = (__u32)(long)res->user_astparam; |
120 | res32->user_lksb = (__u32)(long)res->user_lksb; | 128 | res32->user_lksb = (__u32)(long)res->user_lksb; |
@@ -130,6 +138,36 @@ static void compat_output(struct dlm_lock_result *res, | |||
130 | } | 138 | } |
131 | #endif | 139 | #endif |
132 | 140 | ||
141 | /* Figure out if this lock is at the end of its life and no longer | ||
142 | available for the application to use. The lkb still exists until | ||
143 | the final ast is read. A lock becomes EOL in three situations: | ||
144 | 1. a noqueue request fails with EAGAIN | ||
145 | 2. an unlock completes with EUNLOCK | ||
146 | 3. a cancel of a waiting request completes with ECANCEL/EDEADLK | ||
147 | An EOL lock needs to be removed from the process's list of locks. | ||
148 | And we can't allow any new operation on an EOL lock. This is | ||
149 | not related to the lifetime of the lkb struct which is managed | ||
150 | entirely by refcount. */ | ||
151 | |||
152 | static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type) | ||
153 | { | ||
154 | switch (sb_status) { | ||
155 | case -DLM_EUNLOCK: | ||
156 | return 1; | ||
157 | case -DLM_ECANCEL: | ||
158 | case -ETIMEDOUT: | ||
159 | case -EDEADLK: | ||
160 | if (lkb->lkb_grmode == DLM_LOCK_IV) | ||
161 | return 1; | ||
162 | break; | ||
163 | case -EAGAIN: | ||
164 | if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV) | ||
165 | return 1; | ||
166 | break; | ||
167 | } | ||
168 | return 0; | ||
169 | } | ||
170 | |||
133 | /* we could possibly check if the cancel of an orphan has resulted in the lkb | 171 | /* we could possibly check if the cancel of an orphan has resulted in the lkb |
134 | being removed and then remove that lkb from the orphans list and free it */ | 172 | being removed and then remove that lkb from the orphans list and free it */ |
135 | 173 | ||
@@ -176,25 +214,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
176 | log_debug(ls, "ast overlap %x status %x %x", | 214 | log_debug(ls, "ast overlap %x status %x %x", |
177 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); | 215 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); |
178 | 216 | ||
179 | /* Figure out if this lock is at the end of its life and no longer | 217 | eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); |
180 | available for the application to use. The lkb still exists until | ||
181 | the final ast is read. A lock becomes EOL in three situations: | ||
182 | 1. a noqueue request fails with EAGAIN | ||
183 | 2. an unlock completes with EUNLOCK | ||
184 | 3. a cancel of a waiting request completes with ECANCEL | ||
185 | An EOL lock needs to be removed from the process's list of locks. | ||
186 | And we can't allow any new operation on an EOL lock. This is | ||
187 | not related to the lifetime of the lkb struct which is managed | ||
188 | entirely by refcount. */ | ||
189 | |||
190 | if (type == AST_COMP && | ||
191 | lkb->lkb_grmode == DLM_LOCK_IV && | ||
192 | ua->lksb.sb_status == -EAGAIN) | ||
193 | eol = 1; | ||
194 | else if (ua->lksb.sb_status == -DLM_EUNLOCK || | ||
195 | (ua->lksb.sb_status == -DLM_ECANCEL && | ||
196 | lkb->lkb_grmode == DLM_LOCK_IV)) | ||
197 | eol = 1; | ||
198 | if (eol) { | 218 | if (eol) { |
199 | lkb->lkb_ast_type &= ~AST_BAST; | 219 | lkb->lkb_ast_type &= ~AST_BAST; |
200 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | 220 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; |
@@ -252,16 +272,18 @@ static int device_user_lock(struct dlm_user_proc *proc, | |||
252 | ua->castaddr = params->castaddr; | 272 | ua->castaddr = params->castaddr; |
253 | ua->bastparam = params->bastparam; | 273 | ua->bastparam = params->bastparam; |
254 | ua->bastaddr = params->bastaddr; | 274 | ua->bastaddr = params->bastaddr; |
275 | ua->xid = params->xid; | ||
255 | 276 | ||
256 | if (params->flags & DLM_LKF_CONVERT) | 277 | if (params->flags & DLM_LKF_CONVERT) |
257 | error = dlm_user_convert(ls, ua, | 278 | error = dlm_user_convert(ls, ua, |
258 | params->mode, params->flags, | 279 | params->mode, params->flags, |
259 | params->lkid, params->lvb); | 280 | params->lkid, params->lvb, |
281 | (unsigned long) params->timeout); | ||
260 | else { | 282 | else { |
261 | error = dlm_user_request(ls, ua, | 283 | error = dlm_user_request(ls, ua, |
262 | params->mode, params->flags, | 284 | params->mode, params->flags, |
263 | params->name, params->namelen, | 285 | params->name, params->namelen, |
264 | params->parent); | 286 | (unsigned long) params->timeout); |
265 | if (!error) | 287 | if (!error) |
266 | error = ua->lksb.sb_lkid; | 288 | error = ua->lksb.sb_lkid; |
267 | } | 289 | } |
@@ -299,6 +321,22 @@ static int device_user_unlock(struct dlm_user_proc *proc, | |||
299 | return error; | 321 | return error; |
300 | } | 322 | } |
301 | 323 | ||
324 | static int device_user_deadlock(struct dlm_user_proc *proc, | ||
325 | struct dlm_lock_params *params) | ||
326 | { | ||
327 | struct dlm_ls *ls; | ||
328 | int error; | ||
329 | |||
330 | ls = dlm_find_lockspace_local(proc->lockspace); | ||
331 | if (!ls) | ||
332 | return -ENOENT; | ||
333 | |||
334 | error = dlm_user_deadlock(ls, params->flags, params->lkid); | ||
335 | |||
336 | dlm_put_lockspace(ls); | ||
337 | return error; | ||
338 | } | ||
339 | |||
302 | static int create_misc_device(struct dlm_ls *ls, char *name) | 340 | static int create_misc_device(struct dlm_ls *ls, char *name) |
303 | { | 341 | { |
304 | int error, len; | 342 | int error, len; |
@@ -348,7 +386,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params) | |||
348 | return -EPERM; | 386 | return -EPERM; |
349 | 387 | ||
350 | error = dlm_new_lockspace(params->name, strlen(params->name), | 388 | error = dlm_new_lockspace(params->name, strlen(params->name), |
351 | &lockspace, 0, DLM_USER_LVB_LEN); | 389 | &lockspace, params->flags, DLM_USER_LVB_LEN); |
352 | if (error) | 390 | if (error) |
353 | return error; | 391 | return error; |
354 | 392 | ||
@@ -524,6 +562,14 @@ static ssize_t device_write(struct file *file, const char __user *buf, | |||
524 | error = device_user_unlock(proc, &kbuf->i.lock); | 562 | error = device_user_unlock(proc, &kbuf->i.lock); |
525 | break; | 563 | break; |
526 | 564 | ||
565 | case DLM_USER_DEADLOCK: | ||
566 | if (!proc) { | ||
567 | log_print("no locking on control device"); | ||
568 | goto out_sig; | ||
569 | } | ||
570 | error = device_user_deadlock(proc, &kbuf->i.lock); | ||
571 | break; | ||
572 | |||
527 | case DLM_USER_CREATE_LOCKSPACE: | 573 | case DLM_USER_CREATE_LOCKSPACE: |
528 | if (proc) { | 574 | if (proc) { |
529 | log_print("create/remove only on control device"); | 575 | log_print("create/remove only on control device"); |
@@ -641,6 +687,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
641 | int struct_len; | 687 | int struct_len; |
642 | 688 | ||
643 | memset(&result, 0, sizeof(struct dlm_lock_result)); | 689 | memset(&result, 0, sizeof(struct dlm_lock_result)); |
690 | result.version[0] = DLM_DEVICE_VERSION_MAJOR; | ||
691 | result.version[1] = DLM_DEVICE_VERSION_MINOR; | ||
692 | result.version[2] = DLM_DEVICE_VERSION_PATCH; | ||
644 | memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb)); | 693 | memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb)); |
645 | result.user_lksb = ua->user_lksb; | 694 | result.user_lksb = ua->user_lksb; |
646 | 695 | ||
@@ -699,6 +748,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
699 | return error; | 748 | return error; |
700 | } | 749 | } |
701 | 750 | ||
751 | static int copy_version_to_user(char __user *buf, size_t count) | ||
752 | { | ||
753 | struct dlm_device_version ver; | ||
754 | |||
755 | memset(&ver, 0, sizeof(struct dlm_device_version)); | ||
756 | ver.version[0] = DLM_DEVICE_VERSION_MAJOR; | ||
757 | ver.version[1] = DLM_DEVICE_VERSION_MINOR; | ||
758 | ver.version[2] = DLM_DEVICE_VERSION_PATCH; | ||
759 | |||
760 | if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version))) | ||
761 | return -EFAULT; | ||
762 | return sizeof(struct dlm_device_version); | ||
763 | } | ||
764 | |||
702 | /* a read returns a single ast described in a struct dlm_lock_result */ | 765 | /* a read returns a single ast described in a struct dlm_lock_result */ |
703 | 766 | ||
704 | static ssize_t device_read(struct file *file, char __user *buf, size_t count, | 767 | static ssize_t device_read(struct file *file, char __user *buf, size_t count, |
@@ -710,6 +773,16 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
710 | DECLARE_WAITQUEUE(wait, current); | 773 | DECLARE_WAITQUEUE(wait, current); |
711 | int error, type=0, bmode=0, removed = 0; | 774 | int error, type=0, bmode=0, removed = 0; |
712 | 775 | ||
776 | if (count == sizeof(struct dlm_device_version)) { | ||
777 | error = copy_version_to_user(buf, count); | ||
778 | return error; | ||
779 | } | ||
780 | |||
781 | if (!proc) { | ||
782 | log_print("non-version read from control device %zu", count); | ||
783 | return -EINVAL; | ||
784 | } | ||
785 | |||
713 | #ifdef CONFIG_COMPAT | 786 | #ifdef CONFIG_COMPAT |
714 | if (count < sizeof(struct dlm_lock_result32)) | 787 | if (count < sizeof(struct dlm_lock_result32)) |
715 | #else | 788 | #else |
@@ -747,11 +820,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
747 | } | 820 | } |
748 | } | 821 | } |
749 | 822 | ||
750 | if (list_empty(&proc->asts)) { | ||
751 | spin_unlock(&proc->asts_spin); | ||
752 | return -EAGAIN; | ||
753 | } | ||
754 | |||
755 | /* there may be both completion and blocking asts to return for | 823 | /* there may be both completion and blocking asts to return for |
756 | the lkb, don't remove lkb from asts list unless no asts remain */ | 824 | the lkb, don't remove lkb from asts list unless no asts remain */ |
757 | 825 | ||
@@ -823,6 +891,7 @@ static const struct file_operations device_fops = { | |||
823 | static const struct file_operations ctl_device_fops = { | 891 | static const struct file_operations ctl_device_fops = { |
824 | .open = ctl_device_open, | 892 | .open = ctl_device_open, |
825 | .release = ctl_device_close, | 893 | .release = ctl_device_close, |
894 | .read = device_read, | ||
826 | .write = device_write, | 895 | .write = device_write, |
827 | .owner = THIS_MODULE, | 896 | .owner = THIS_MODULE, |
828 | }; | 897 | }; |
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile index e3f1ada643ac..04ad0caebedb 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | obj-$(CONFIG_GFS2_FS) += gfs2.o | 1 | obj-$(CONFIG_GFS2_FS) += gfs2.o |
2 | gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ | 2 | gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ |
3 | glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \ | 3 | glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \ |
4 | mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ | 4 | mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ |
5 | ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \ | 5 | ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \ |
6 | recovery.o rgrp.o super.o sys.o trans.o util.o | 6 | recovery.o rgrp.o super.o sys.o trans.o util.o |
7 | 7 | ||
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index c53a5d2d0590..cd805a66880d 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -718,7 +718,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
718 | for (x = 0; x < rlist.rl_rgrps; x++) { | 718 | for (x = 0; x < rlist.rl_rgrps; x++) { |
719 | struct gfs2_rgrpd *rgd; | 719 | struct gfs2_rgrpd *rgd; |
720 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; | 720 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; |
721 | rg_blocks += rgd->rd_ri.ri_length; | 721 | rg_blocks += rgd->rd_length; |
722 | } | 722 | } |
723 | 723 | ||
724 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); | 724 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); |
@@ -772,7 +772,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
772 | gfs2_free_data(ip, bstart, blen); | 772 | gfs2_free_data(ip, bstart, blen); |
773 | } | 773 | } |
774 | 774 | ||
775 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 775 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
776 | 776 | ||
777 | gfs2_dinode_out(ip, dibh->b_data); | 777 | gfs2_dinode_out(ip, dibh->b_data); |
778 | 778 | ||
@@ -824,7 +824,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
824 | goto out_gunlock_q; | 824 | goto out_gunlock_q; |
825 | 825 | ||
826 | error = gfs2_trans_begin(sdp, | 826 | error = gfs2_trans_begin(sdp, |
827 | sdp->sd_max_height + al->al_rgd->rd_ri.ri_length + | 827 | sdp->sd_max_height + al->al_rgd->rd_length + |
828 | RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0); | 828 | RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0); |
829 | if (error) | 829 | if (error) |
830 | goto out_ipres; | 830 | goto out_ipres; |
@@ -847,7 +847,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
847 | } | 847 | } |
848 | 848 | ||
849 | ip->i_di.di_size = size; | 849 | ip->i_di.di_size = size; |
850 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 850 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
851 | 851 | ||
852 | error = gfs2_meta_inode_buffer(ip, &dibh); | 852 | error = gfs2_meta_inode_buffer(ip, &dibh); |
853 | if (error) | 853 | if (error) |
@@ -885,7 +885,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping) | |||
885 | unsigned blocksize, iblock, length, pos; | 885 | unsigned blocksize, iblock, length, pos; |
886 | struct buffer_head *bh; | 886 | struct buffer_head *bh; |
887 | struct page *page; | 887 | struct page *page; |
888 | void *kaddr; | ||
889 | int err; | 888 | int err; |
890 | 889 | ||
891 | page = grab_cache_page(mapping, index); | 890 | page = grab_cache_page(mapping, index); |
@@ -928,15 +927,13 @@ static int gfs2_block_truncate_page(struct address_space *mapping) | |||
928 | /* Uhhuh. Read error. Complain and punt. */ | 927 | /* Uhhuh. Read error. Complain and punt. */ |
929 | if (!buffer_uptodate(bh)) | 928 | if (!buffer_uptodate(bh)) |
930 | goto unlock; | 929 | goto unlock; |
930 | err = 0; | ||
931 | } | 931 | } |
932 | 932 | ||
933 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) | 933 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) |
934 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | 934 | gfs2_trans_add_bh(ip->i_gl, bh, 0); |
935 | 935 | ||
936 | kaddr = kmap_atomic(page, KM_USER0); | 936 | zero_user_page(page, offset, length, KM_USER0); |
937 | memset(kaddr + offset, 0, length); | ||
938 | flush_dcache_page(page); | ||
939 | kunmap_atomic(kaddr, KM_USER0); | ||
940 | 937 | ||
941 | unlock: | 938 | unlock: |
942 | unlock_page(page); | 939 | unlock_page(page); |
@@ -962,7 +959,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) | |||
962 | 959 | ||
963 | if (gfs2_is_stuffed(ip)) { | 960 | if (gfs2_is_stuffed(ip)) { |
964 | ip->i_di.di_size = size; | 961 | ip->i_di.di_size = size; |
965 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 962 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
966 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 963 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
967 | gfs2_dinode_out(ip, dibh->b_data); | 964 | gfs2_dinode_out(ip, dibh->b_data); |
968 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size); | 965 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size); |
@@ -974,7 +971,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) | |||
974 | 971 | ||
975 | if (!error) { | 972 | if (!error) { |
976 | ip->i_di.di_size = size; | 973 | ip->i_di.di_size = size; |
977 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 974 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
978 | ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG; | 975 | ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG; |
979 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 976 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
980 | gfs2_dinode_out(ip, dibh->b_data); | 977 | gfs2_dinode_out(ip, dibh->b_data); |
@@ -1044,10 +1041,10 @@ static int trunc_end(struct gfs2_inode *ip) | |||
1044 | ip->i_di.di_height = 0; | 1041 | ip->i_di.di_height = 0; |
1045 | ip->i_di.di_goal_meta = | 1042 | ip->i_di.di_goal_meta = |
1046 | ip->i_di.di_goal_data = | 1043 | ip->i_di.di_goal_data = |
1047 | ip->i_num.no_addr; | 1044 | ip->i_no_addr; |
1048 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 1045 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
1049 | } | 1046 | } |
1050 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 1047 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
1051 | ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; | 1048 | ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; |
1052 | 1049 | ||
1053 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1050 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c index 683cb5bda870..3548d9f31e0d 100644 --- a/fs/gfs2/daemon.c +++ b/fs/gfs2/daemon.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/gfs2_ondisk.h> | 17 | #include <linux/gfs2_ondisk.h> |
18 | #include <linux/lm_interface.h> | 18 | #include <linux/lm_interface.h> |
19 | #include <linux/freezer.h> | ||
19 | 20 | ||
20 | #include "gfs2.h" | 21 | #include "gfs2.h" |
21 | #include "incore.h" | 22 | #include "incore.h" |
@@ -49,6 +50,8 @@ int gfs2_scand(void *data) | |||
49 | while (!kthread_should_stop()) { | 50 | while (!kthread_should_stop()) { |
50 | gfs2_scand_internal(sdp); | 51 | gfs2_scand_internal(sdp); |
51 | t = gfs2_tune_get(sdp, gt_scand_secs) * HZ; | 52 | t = gfs2_tune_get(sdp, gt_scand_secs) * HZ; |
53 | if (freezing(current)) | ||
54 | refrigerator(); | ||
52 | schedule_timeout_interruptible(t); | 55 | schedule_timeout_interruptible(t); |
53 | } | 56 | } |
54 | 57 | ||
@@ -74,6 +77,8 @@ int gfs2_glockd(void *data) | |||
74 | wait_event_interruptible(sdp->sd_reclaim_wq, | 77 | wait_event_interruptible(sdp->sd_reclaim_wq, |
75 | (atomic_read(&sdp->sd_reclaim_count) || | 78 | (atomic_read(&sdp->sd_reclaim_count) || |
76 | kthread_should_stop())); | 79 | kthread_should_stop())); |
80 | if (freezing(current)) | ||
81 | refrigerator(); | ||
77 | } | 82 | } |
78 | 83 | ||
79 | return 0; | 84 | return 0; |
@@ -93,6 +98,8 @@ int gfs2_recoverd(void *data) | |||
93 | while (!kthread_should_stop()) { | 98 | while (!kthread_should_stop()) { |
94 | gfs2_check_journals(sdp); | 99 | gfs2_check_journals(sdp); |
95 | t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ; | 100 | t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ; |
101 | if (freezing(current)) | ||
102 | refrigerator(); | ||
96 | schedule_timeout_interruptible(t); | 103 | schedule_timeout_interruptible(t); |
97 | } | 104 | } |
98 | 105 | ||
@@ -141,6 +148,8 @@ int gfs2_logd(void *data) | |||
141 | } | 148 | } |
142 | 149 | ||
143 | t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; | 150 | t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; |
151 | if (freezing(current)) | ||
152 | refrigerator(); | ||
144 | schedule_timeout_interruptible(t); | 153 | schedule_timeout_interruptible(t); |
145 | } | 154 | } |
146 | 155 | ||
@@ -191,6 +200,8 @@ int gfs2_quotad(void *data) | |||
191 | gfs2_quota_scan(sdp); | 200 | gfs2_quota_scan(sdp); |
192 | 201 | ||
193 | t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ; | 202 | t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ; |
203 | if (freezing(current)) | ||
204 | refrigerator(); | ||
194 | schedule_timeout_interruptible(t); | 205 | schedule_timeout_interruptible(t); |
195 | } | 206 | } |
196 | 207 | ||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index a96fa07b3f3b..2beb2f401aa2 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -130,7 +130,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, | |||
130 | memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); | 130 | memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); |
131 | if (ip->i_di.di_size < offset + size) | 131 | if (ip->i_di.di_size < offset + size) |
132 | ip->i_di.di_size = offset + size; | 132 | ip->i_di.di_size = offset + size; |
133 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 133 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
134 | gfs2_dinode_out(ip, dibh->b_data); | 134 | gfs2_dinode_out(ip, dibh->b_data); |
135 | 135 | ||
136 | brelse(dibh); | 136 | brelse(dibh); |
@@ -228,7 +228,7 @@ out: | |||
228 | 228 | ||
229 | if (ip->i_di.di_size < offset + copied) | 229 | if (ip->i_di.di_size < offset + copied) |
230 | ip->i_di.di_size = offset + copied; | 230 | ip->i_di.di_size = offset + copied; |
231 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 231 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
232 | 232 | ||
233 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 233 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
234 | gfs2_dinode_out(ip, dibh->b_data); | 234 | gfs2_dinode_out(ip, dibh->b_data); |
@@ -1456,7 +1456,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1456 | if (dip->i_di.di_entries != g.offset) { | 1456 | if (dip->i_di.di_entries != g.offset) { |
1457 | fs_warn(sdp, "Number of entries corrupt in dir %llu, " | 1457 | fs_warn(sdp, "Number of entries corrupt in dir %llu, " |
1458 | "ip->i_di.di_entries (%u) != g.offset (%u)\n", | 1458 | "ip->i_di.di_entries (%u) != g.offset (%u)\n", |
1459 | (unsigned long long)dip->i_num.no_addr, | 1459 | (unsigned long long)dip->i_no_addr, |
1460 | dip->i_di.di_entries, | 1460 | dip->i_di.di_entries, |
1461 | g.offset); | 1461 | g.offset); |
1462 | error = -EIO; | 1462 | error = -EIO; |
@@ -1488,24 +1488,55 @@ out: | |||
1488 | * Returns: errno | 1488 | * Returns: errno |
1489 | */ | 1489 | */ |
1490 | 1490 | ||
1491 | int gfs2_dir_search(struct inode *dir, const struct qstr *name, | 1491 | struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) |
1492 | struct gfs2_inum_host *inum, unsigned int *type) | ||
1493 | { | 1492 | { |
1494 | struct buffer_head *bh; | 1493 | struct buffer_head *bh; |
1495 | struct gfs2_dirent *dent; | 1494 | struct gfs2_dirent *dent; |
1495 | struct inode *inode; | ||
1496 | |||
1497 | dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); | ||
1498 | if (dent) { | ||
1499 | if (IS_ERR(dent)) | ||
1500 | return ERR_PTR(PTR_ERR(dent)); | ||
1501 | inode = gfs2_inode_lookup(dir->i_sb, | ||
1502 | be16_to_cpu(dent->de_type), | ||
1503 | be64_to_cpu(dent->de_inum.no_addr), | ||
1504 | be64_to_cpu(dent->de_inum.no_formal_ino)); | ||
1505 | brelse(bh); | ||
1506 | return inode; | ||
1507 | } | ||
1508 | return ERR_PTR(-ENOENT); | ||
1509 | } | ||
1510 | |||
1511 | int gfs2_dir_check(struct inode *dir, const struct qstr *name, | ||
1512 | const struct gfs2_inode *ip) | ||
1513 | { | ||
1514 | struct buffer_head *bh; | ||
1515 | struct gfs2_dirent *dent; | ||
1516 | int ret = -ENOENT; | ||
1496 | 1517 | ||
1497 | dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); | 1518 | dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); |
1498 | if (dent) { | 1519 | if (dent) { |
1499 | if (IS_ERR(dent)) | 1520 | if (IS_ERR(dent)) |
1500 | return PTR_ERR(dent); | 1521 | return PTR_ERR(dent); |
1501 | if (inum) | 1522 | if (ip) { |
1502 | gfs2_inum_in(inum, (char *)&dent->de_inum); | 1523 | if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr) |
1503 | if (type) | 1524 | goto out; |
1504 | *type = be16_to_cpu(dent->de_type); | 1525 | if (be64_to_cpu(dent->de_inum.no_formal_ino) != |
1526 | ip->i_no_formal_ino) | ||
1527 | goto out; | ||
1528 | if (unlikely(IF2DT(ip->i_inode.i_mode) != | ||
1529 | be16_to_cpu(dent->de_type))) { | ||
1530 | gfs2_consist_inode(GFS2_I(dir)); | ||
1531 | ret = -EIO; | ||
1532 | goto out; | ||
1533 | } | ||
1534 | } | ||
1535 | ret = 0; | ||
1536 | out: | ||
1505 | brelse(bh); | 1537 | brelse(bh); |
1506 | return 0; | ||
1507 | } | 1538 | } |
1508 | return -ENOENT; | 1539 | return ret; |
1509 | } | 1540 | } |
1510 | 1541 | ||
1511 | static int dir_new_leaf(struct inode *inode, const struct qstr *name) | 1542 | static int dir_new_leaf(struct inode *inode, const struct qstr *name) |
@@ -1565,7 +1596,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
1565 | */ | 1596 | */ |
1566 | 1597 | ||
1567 | int gfs2_dir_add(struct inode *inode, const struct qstr *name, | 1598 | int gfs2_dir_add(struct inode *inode, const struct qstr *name, |
1568 | const struct gfs2_inum_host *inum, unsigned type) | 1599 | const struct gfs2_inode *nip, unsigned type) |
1569 | { | 1600 | { |
1570 | struct gfs2_inode *ip = GFS2_I(inode); | 1601 | struct gfs2_inode *ip = GFS2_I(inode); |
1571 | struct buffer_head *bh; | 1602 | struct buffer_head *bh; |
@@ -1580,7 +1611,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1580 | if (IS_ERR(dent)) | 1611 | if (IS_ERR(dent)) |
1581 | return PTR_ERR(dent); | 1612 | return PTR_ERR(dent); |
1582 | dent = gfs2_init_dirent(inode, dent, name, bh); | 1613 | dent = gfs2_init_dirent(inode, dent, name, bh); |
1583 | gfs2_inum_out(inum, (char *)&dent->de_inum); | 1614 | gfs2_inum_out(nip, dent); |
1584 | dent->de_type = cpu_to_be16(type); | 1615 | dent->de_type = cpu_to_be16(type); |
1585 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { | 1616 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { |
1586 | leaf = (struct gfs2_leaf *)bh->b_data; | 1617 | leaf = (struct gfs2_leaf *)bh->b_data; |
@@ -1592,7 +1623,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1592 | break; | 1623 | break; |
1593 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 1624 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
1594 | ip->i_di.di_entries++; | 1625 | ip->i_di.di_entries++; |
1595 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 1626 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
1596 | gfs2_dinode_out(ip, bh->b_data); | 1627 | gfs2_dinode_out(ip, bh->b_data); |
1597 | brelse(bh); | 1628 | brelse(bh); |
1598 | error = 0; | 1629 | error = 0; |
@@ -1678,7 +1709,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) | |||
1678 | gfs2_consist_inode(dip); | 1709 | gfs2_consist_inode(dip); |
1679 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | 1710 | gfs2_trans_add_bh(dip->i_gl, bh, 1); |
1680 | dip->i_di.di_entries--; | 1711 | dip->i_di.di_entries--; |
1681 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; | 1712 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; |
1682 | gfs2_dinode_out(dip, bh->b_data); | 1713 | gfs2_dinode_out(dip, bh->b_data); |
1683 | brelse(bh); | 1714 | brelse(bh); |
1684 | mark_inode_dirty(&dip->i_inode); | 1715 | mark_inode_dirty(&dip->i_inode); |
@@ -1700,7 +1731,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) | |||
1700 | */ | 1731 | */ |
1701 | 1732 | ||
1702 | int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | 1733 | int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, |
1703 | struct gfs2_inum_host *inum, unsigned int new_type) | 1734 | const struct gfs2_inode *nip, unsigned int new_type) |
1704 | { | 1735 | { |
1705 | struct buffer_head *bh; | 1736 | struct buffer_head *bh; |
1706 | struct gfs2_dirent *dent; | 1737 | struct gfs2_dirent *dent; |
@@ -1715,7 +1746,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | |||
1715 | return PTR_ERR(dent); | 1746 | return PTR_ERR(dent); |
1716 | 1747 | ||
1717 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | 1748 | gfs2_trans_add_bh(dip->i_gl, bh, 1); |
1718 | gfs2_inum_out(inum, (char *)&dent->de_inum); | 1749 | gfs2_inum_out(nip, dent); |
1719 | dent->de_type = cpu_to_be16(new_type); | 1750 | dent->de_type = cpu_to_be16(new_type); |
1720 | 1751 | ||
1721 | if (dip->i_di.di_flags & GFS2_DIF_EXHASH) { | 1752 | if (dip->i_di.di_flags & GFS2_DIF_EXHASH) { |
@@ -1726,7 +1757,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | |||
1726 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | 1757 | gfs2_trans_add_bh(dip->i_gl, bh, 1); |
1727 | } | 1758 | } |
1728 | 1759 | ||
1729 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; | 1760 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; |
1730 | gfs2_dinode_out(dip, bh->b_data); | 1761 | gfs2_dinode_out(dip, bh->b_data); |
1731 | brelse(bh); | 1762 | brelse(bh); |
1732 | return 0; | 1763 | return 0; |
@@ -1867,7 +1898,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1867 | for (x = 0; x < rlist.rl_rgrps; x++) { | 1898 | for (x = 0; x < rlist.rl_rgrps; x++) { |
1868 | struct gfs2_rgrpd *rgd; | 1899 | struct gfs2_rgrpd *rgd; |
1869 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; | 1900 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; |
1870 | rg_blocks += rgd->rd_ri.ri_length; | 1901 | rg_blocks += rgd->rd_length; |
1871 | } | 1902 | } |
1872 | 1903 | ||
1873 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); | 1904 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); |
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h index 48fe89046bba..8a468cac9328 100644 --- a/fs/gfs2/dir.h +++ b/fs/gfs2/dir.h | |||
@@ -16,15 +16,16 @@ struct inode; | |||
16 | struct gfs2_inode; | 16 | struct gfs2_inode; |
17 | struct gfs2_inum; | 17 | struct gfs2_inum; |
18 | 18 | ||
19 | int gfs2_dir_search(struct inode *dir, const struct qstr *filename, | 19 | struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename); |
20 | struct gfs2_inum_host *inum, unsigned int *type); | 20 | int gfs2_dir_check(struct inode *dir, const struct qstr *filename, |
21 | const struct gfs2_inode *ip); | ||
21 | int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 22 | int gfs2_dir_add(struct inode *inode, const struct qstr *filename, |
22 | const struct gfs2_inum_host *inum, unsigned int type); | 23 | const struct gfs2_inode *ip, unsigned int type); |
23 | int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); | 24 | int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); |
24 | int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | 25 | int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, |
25 | filldir_t filldir); | 26 | filldir_t filldir); |
26 | int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | 27 | int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, |
27 | struct gfs2_inum_host *new_inum, unsigned int new_type); | 28 | const struct gfs2_inode *nip, unsigned int new_type); |
28 | 29 | ||
29 | int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); | 30 | int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); |
30 | 31 | ||
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index 5b83ca6acab1..2a7435b5c4dc 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c | |||
@@ -254,7 +254,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
254 | if (error) | 254 | if (error) |
255 | return error; | 255 | return error; |
256 | 256 | ||
257 | error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_length + RES_DINODE + | 257 | error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE + |
258 | RES_EATTR + RES_STATFS + RES_QUOTA, blks); | 258 | RES_EATTR + RES_STATFS + RES_QUOTA, blks); |
259 | if (error) | 259 | if (error) |
260 | goto out_gunlock; | 260 | goto out_gunlock; |
@@ -300,7 +300,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
300 | 300 | ||
301 | error = gfs2_meta_inode_buffer(ip, &dibh); | 301 | error = gfs2_meta_inode_buffer(ip, &dibh); |
302 | if (!error) { | 302 | if (!error) { |
303 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 303 | ip->i_inode.i_ctime = CURRENT_TIME; |
304 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 304 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
305 | gfs2_dinode_out(ip, dibh->b_data); | 305 | gfs2_dinode_out(ip, dibh->b_data); |
306 | brelse(dibh); | 306 | brelse(dibh); |
@@ -700,7 +700,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
700 | goto out_gunlock_q; | 700 | goto out_gunlock_q; |
701 | 701 | ||
702 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), | 702 | error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), |
703 | blks + al->al_rgd->rd_ri.ri_length + | 703 | blks + al->al_rgd->rd_length + |
704 | RES_DINODE + RES_STATFS + RES_QUOTA, 0); | 704 | RES_DINODE + RES_STATFS + RES_QUOTA, 0); |
705 | if (error) | 705 | if (error) |
706 | goto out_ipres; | 706 | goto out_ipres; |
@@ -717,7 +717,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
717 | (er->er_mode & S_IFMT)); | 717 | (er->er_mode & S_IFMT)); |
718 | ip->i_inode.i_mode = er->er_mode; | 718 | ip->i_inode.i_mode = er->er_mode; |
719 | } | 719 | } |
720 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 720 | ip->i_inode.i_ctime = CURRENT_TIME; |
721 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 721 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
722 | gfs2_dinode_out(ip, dibh->b_data); | 722 | gfs2_dinode_out(ip, dibh->b_data); |
723 | brelse(dibh); | 723 | brelse(dibh); |
@@ -852,7 +852,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, | |||
852 | (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); | 852 | (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); |
853 | ip->i_inode.i_mode = er->er_mode; | 853 | ip->i_inode.i_mode = er->er_mode; |
854 | } | 854 | } |
855 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 855 | ip->i_inode.i_ctime = CURRENT_TIME; |
856 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 856 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
857 | gfs2_dinode_out(ip, dibh->b_data); | 857 | gfs2_dinode_out(ip, dibh->b_data); |
858 | brelse(dibh); | 858 | brelse(dibh); |
@@ -1133,7 +1133,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) | |||
1133 | 1133 | ||
1134 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1134 | error = gfs2_meta_inode_buffer(ip, &dibh); |
1135 | if (!error) { | 1135 | if (!error) { |
1136 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 1136 | ip->i_inode.i_ctime = CURRENT_TIME; |
1137 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1137 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
1138 | gfs2_dinode_out(ip, dibh->b_data); | 1138 | gfs2_dinode_out(ip, dibh->b_data); |
1139 | brelse(dibh); | 1139 | brelse(dibh); |
@@ -1352,7 +1352,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) | |||
1352 | for (x = 0; x < rlist.rl_rgrps; x++) { | 1352 | for (x = 0; x < rlist.rl_rgrps; x++) { |
1353 | struct gfs2_rgrpd *rgd; | 1353 | struct gfs2_rgrpd *rgd; |
1354 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; | 1354 | rgd = rlist.rl_ghs[x].gh_gl->gl_object; |
1355 | rg_blocks += rgd->rd_ri.ri_length; | 1355 | rg_blocks += rgd->rd_length; |
1356 | } | 1356 | } |
1357 | 1357 | ||
1358 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); | 1358 | error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 1815429a2978..3f0974e1afef 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -422,11 +422,11 @@ void gfs2_holder_uninit(struct gfs2_holder *gh) | |||
422 | static void gfs2_holder_wake(struct gfs2_holder *gh) | 422 | static void gfs2_holder_wake(struct gfs2_holder *gh) |
423 | { | 423 | { |
424 | clear_bit(HIF_WAIT, &gh->gh_iflags); | 424 | clear_bit(HIF_WAIT, &gh->gh_iflags); |
425 | smp_mb(); | 425 | smp_mb__after_clear_bit(); |
426 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); | 426 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); |
427 | } | 427 | } |
428 | 428 | ||
429 | static int holder_wait(void *word) | 429 | static int just_schedule(void *word) |
430 | { | 430 | { |
431 | schedule(); | 431 | schedule(); |
432 | return 0; | 432 | return 0; |
@@ -435,7 +435,20 @@ static int holder_wait(void *word) | |||
435 | static void wait_on_holder(struct gfs2_holder *gh) | 435 | static void wait_on_holder(struct gfs2_holder *gh) |
436 | { | 436 | { |
437 | might_sleep(); | 437 | might_sleep(); |
438 | wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE); | 438 | wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE); |
439 | } | ||
440 | |||
441 | static void gfs2_demote_wake(struct gfs2_glock *gl) | ||
442 | { | ||
443 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | ||
444 | smp_mb__after_clear_bit(); | ||
445 | wake_up_bit(&gl->gl_flags, GLF_DEMOTE); | ||
446 | } | ||
447 | |||
448 | static void wait_on_demote(struct gfs2_glock *gl) | ||
449 | { | ||
450 | might_sleep(); | ||
451 | wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE); | ||
439 | } | 452 | } |
440 | 453 | ||
441 | /** | 454 | /** |
@@ -528,7 +541,7 @@ static int rq_demote(struct gfs2_glock *gl) | |||
528 | 541 | ||
529 | if (gl->gl_state == gl->gl_demote_state || | 542 | if (gl->gl_state == gl->gl_demote_state || |
530 | gl->gl_state == LM_ST_UNLOCKED) { | 543 | gl->gl_state == LM_ST_UNLOCKED) { |
531 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 544 | gfs2_demote_wake(gl); |
532 | return 0; | 545 | return 0; |
533 | } | 546 | } |
534 | set_bit(GLF_LOCK, &gl->gl_flags); | 547 | set_bit(GLF_LOCK, &gl->gl_flags); |
@@ -666,12 +679,22 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl) | |||
666 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED | 679 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED |
667 | */ | 680 | */ |
668 | 681 | ||
669 | static void handle_callback(struct gfs2_glock *gl, unsigned int state) | 682 | static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote) |
670 | { | 683 | { |
671 | spin_lock(&gl->gl_spin); | 684 | spin_lock(&gl->gl_spin); |
672 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { | 685 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { |
673 | gl->gl_demote_state = state; | 686 | gl->gl_demote_state = state; |
674 | gl->gl_demote_time = jiffies; | 687 | gl->gl_demote_time = jiffies; |
688 | if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN && | ||
689 | gl->gl_object) { | ||
690 | struct inode *inode = igrab(gl->gl_object); | ||
691 | spin_unlock(&gl->gl_spin); | ||
692 | if (inode) { | ||
693 | d_prune_aliases(inode); | ||
694 | iput(inode); | ||
695 | } | ||
696 | return; | ||
697 | } | ||
675 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { | 698 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { |
676 | gl->gl_demote_state = state; | 699 | gl->gl_demote_state = state; |
677 | } | 700 | } |
@@ -740,7 +763,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
740 | if (ret & LM_OUT_CANCELED) | 763 | if (ret & LM_OUT_CANCELED) |
741 | op_done = 0; | 764 | op_done = 0; |
742 | else | 765 | else |
743 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 766 | gfs2_demote_wake(gl); |
744 | } else { | 767 | } else { |
745 | spin_lock(&gl->gl_spin); | 768 | spin_lock(&gl->gl_spin); |
746 | list_del_init(&gh->gh_list); | 769 | list_del_init(&gh->gh_list); |
@@ -848,7 +871,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
848 | gfs2_assert_warn(sdp, !ret); | 871 | gfs2_assert_warn(sdp, !ret); |
849 | 872 | ||
850 | state_change(gl, LM_ST_UNLOCKED); | 873 | state_change(gl, LM_ST_UNLOCKED); |
851 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 874 | gfs2_demote_wake(gl); |
852 | 875 | ||
853 | if (glops->go_inval) | 876 | if (glops->go_inval) |
854 | glops->go_inval(gl, DIO_METADATA); | 877 | glops->go_inval(gl, DIO_METADATA); |
@@ -1174,7 +1197,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1174 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 1197 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
1175 | 1198 | ||
1176 | if (gh->gh_flags & GL_NOCACHE) | 1199 | if (gh->gh_flags & GL_NOCACHE) |
1177 | handle_callback(gl, LM_ST_UNLOCKED); | 1200 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1178 | 1201 | ||
1179 | gfs2_glmutex_lock(gl); | 1202 | gfs2_glmutex_lock(gl); |
1180 | 1203 | ||
@@ -1196,6 +1219,13 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1196 | spin_unlock(&gl->gl_spin); | 1219 | spin_unlock(&gl->gl_spin); |
1197 | } | 1220 | } |
1198 | 1221 | ||
1222 | void gfs2_glock_dq_wait(struct gfs2_holder *gh) | ||
1223 | { | ||
1224 | struct gfs2_glock *gl = gh->gh_gl; | ||
1225 | gfs2_glock_dq(gh); | ||
1226 | wait_on_demote(gl); | ||
1227 | } | ||
1228 | |||
1199 | /** | 1229 | /** |
1200 | * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it | 1230 | * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it |
1201 | * @gh: the holder structure | 1231 | * @gh: the holder structure |
@@ -1297,10 +1327,6 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs, | |||
1297 | * @num_gh: the number of structures | 1327 | * @num_gh: the number of structures |
1298 | * @ghs: an array of struct gfs2_holder structures | 1328 | * @ghs: an array of struct gfs2_holder structures |
1299 | * | 1329 | * |
1300 | * Figure out how big an impact this function has. Either: | ||
1301 | * 1) Replace this code with code that calls gfs2_glock_prefetch() | ||
1302 | * 2) Forget async stuff and just call nq_m_sync() | ||
1303 | * 3) Leave it like it is | ||
1304 | * | 1330 | * |
1305 | * Returns: 0 on success (all glocks acquired), | 1331 | * Returns: 0 on success (all glocks acquired), |
1306 | * errno on failure (no glocks acquired) | 1332 | * errno on failure (no glocks acquired) |
@@ -1308,62 +1334,28 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs, | |||
1308 | 1334 | ||
1309 | int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs) | 1335 | int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs) |
1310 | { | 1336 | { |
1311 | int *e; | 1337 | struct gfs2_holder *tmp[4]; |
1312 | unsigned int x; | 1338 | struct gfs2_holder **pph = tmp; |
1313 | int borked = 0, serious = 0; | ||
1314 | int error = 0; | 1339 | int error = 0; |
1315 | 1340 | ||
1316 | if (!num_gh) | 1341 | switch(num_gh) { |
1342 | case 0: | ||
1317 | return 0; | 1343 | return 0; |
1318 | 1344 | case 1: | |
1319 | if (num_gh == 1) { | ||
1320 | ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); | 1345 | ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); |
1321 | return gfs2_glock_nq(ghs); | 1346 | return gfs2_glock_nq(ghs); |
1322 | } | 1347 | default: |
1323 | 1348 | if (num_gh <= 4) | |
1324 | e = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL); | ||
1325 | if (!e) | ||
1326 | return -ENOMEM; | ||
1327 | |||
1328 | for (x = 0; x < num_gh; x++) { | ||
1329 | ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC; | ||
1330 | error = gfs2_glock_nq(&ghs[x]); | ||
1331 | if (error) { | ||
1332 | borked = 1; | ||
1333 | serious = error; | ||
1334 | num_gh = x; | ||
1335 | break; | 1349 | break; |
1336 | } | 1350 | pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS); |
1337 | } | 1351 | if (!pph) |
1338 | 1352 | return -ENOMEM; | |
1339 | for (x = 0; x < num_gh; x++) { | ||
1340 | error = e[x] = glock_wait_internal(&ghs[x]); | ||
1341 | if (error) { | ||
1342 | borked = 1; | ||
1343 | if (error != GLR_TRYFAILED && error != GLR_CANCELED) | ||
1344 | serious = error; | ||
1345 | } | ||
1346 | } | 1353 | } |
1347 | 1354 | ||
1348 | if (!borked) { | 1355 | error = nq_m_sync(num_gh, ghs, pph); |
1349 | kfree(e); | ||
1350 | return 0; | ||
1351 | } | ||
1352 | |||
1353 | for (x = 0; x < num_gh; x++) | ||
1354 | if (!e[x]) | ||
1355 | gfs2_glock_dq(&ghs[x]); | ||
1356 | |||
1357 | if (serious) | ||
1358 | error = serious; | ||
1359 | else { | ||
1360 | for (x = 0; x < num_gh; x++) | ||
1361 | gfs2_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags, | ||
1362 | &ghs[x]); | ||
1363 | error = nq_m_sync(num_gh, ghs, (struct gfs2_holder **)e); | ||
1364 | } | ||
1365 | 1356 | ||
1366 | kfree(e); | 1357 | if (pph != tmp) |
1358 | kfree(pph); | ||
1367 | 1359 | ||
1368 | return error; | 1360 | return error; |
1369 | } | 1361 | } |
@@ -1456,7 +1448,7 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, | |||
1456 | if (!gl) | 1448 | if (!gl) |
1457 | return; | 1449 | return; |
1458 | 1450 | ||
1459 | handle_callback(gl, state); | 1451 | handle_callback(gl, state, 1); |
1460 | 1452 | ||
1461 | spin_lock(&gl->gl_spin); | 1453 | spin_lock(&gl->gl_spin); |
1462 | run_queue(gl); | 1454 | run_queue(gl); |
@@ -1596,7 +1588,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp) | |||
1596 | if (gfs2_glmutex_trylock(gl)) { | 1588 | if (gfs2_glmutex_trylock(gl)) { |
1597 | if (list_empty(&gl->gl_holders) && | 1589 | if (list_empty(&gl->gl_holders) && |
1598 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) | 1590 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) |
1599 | handle_callback(gl, LM_ST_UNLOCKED); | 1591 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1600 | gfs2_glmutex_unlock(gl); | 1592 | gfs2_glmutex_unlock(gl); |
1601 | } | 1593 | } |
1602 | 1594 | ||
@@ -1709,7 +1701,7 @@ static void clear_glock(struct gfs2_glock *gl) | |||
1709 | if (gfs2_glmutex_trylock(gl)) { | 1701 | if (gfs2_glmutex_trylock(gl)) { |
1710 | if (list_empty(&gl->gl_holders) && | 1702 | if (list_empty(&gl->gl_holders) && |
1711 | gl->gl_state != LM_ST_UNLOCKED) | 1703 | gl->gl_state != LM_ST_UNLOCKED) |
1712 | handle_callback(gl, LM_ST_UNLOCKED); | 1704 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
1713 | gfs2_glmutex_unlock(gl); | 1705 | gfs2_glmutex_unlock(gl); |
1714 | } | 1706 | } |
1715 | } | 1707 | } |
@@ -1823,7 +1815,8 @@ static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip) | |||
1823 | 1815 | ||
1824 | print_dbg(gi, " Inode:\n"); | 1816 | print_dbg(gi, " Inode:\n"); |
1825 | print_dbg(gi, " num = %llu/%llu\n", | 1817 | print_dbg(gi, " num = %llu/%llu\n", |
1826 | ip->i_num.no_formal_ino, ip->i_num.no_addr); | 1818 | (unsigned long long)ip->i_no_formal_ino, |
1819 | (unsigned long long)ip->i_no_addr); | ||
1827 | print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode)); | 1820 | print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode)); |
1828 | print_dbg(gi, " i_flags ="); | 1821 | print_dbg(gi, " i_flags ="); |
1829 | for (x = 0; x < 32; x++) | 1822 | for (x = 0; x < 32; x++) |
@@ -1909,8 +1902,8 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) | |||
1909 | } | 1902 | } |
1910 | if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { | 1903 | if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { |
1911 | print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n", | 1904 | print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n", |
1912 | gl->gl_demote_state, | 1905 | gl->gl_demote_state, (unsigned long long) |
1913 | (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ)); | 1906 | (jiffies - gl->gl_demote_time)*(1000000/HZ)); |
1914 | } | 1907 | } |
1915 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { | 1908 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { |
1916 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && | 1909 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index b3e152db70c8..7721ca3fff9e 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -87,6 +87,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh); | |||
87 | int gfs2_glock_poll(struct gfs2_holder *gh); | 87 | int gfs2_glock_poll(struct gfs2_holder *gh); |
88 | int gfs2_glock_wait(struct gfs2_holder *gh); | 88 | int gfs2_glock_wait(struct gfs2_holder *gh); |
89 | void gfs2_glock_dq(struct gfs2_holder *gh); | 89 | void gfs2_glock_dq(struct gfs2_holder *gh); |
90 | void gfs2_glock_dq_wait(struct gfs2_holder *gh); | ||
90 | 91 | ||
91 | void gfs2_glock_dq_uninit(struct gfs2_holder *gh); | 92 | void gfs2_glock_dq_uninit(struct gfs2_holder *gh); |
92 | int gfs2_glock_nq_num(struct gfs2_sbd *sdp, | 93 | int gfs2_glock_nq_num(struct gfs2_sbd *sdp, |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 7b82657a9910..777ca46010e8 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -156,9 +156,9 @@ static void inode_go_sync(struct gfs2_glock *gl) | |||
156 | ip = NULL; | 156 | ip = NULL; |
157 | 157 | ||
158 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { | 158 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { |
159 | gfs2_log_flush(gl->gl_sbd, gl); | ||
160 | if (ip) | 159 | if (ip) |
161 | filemap_fdatawrite(ip->i_inode.i_mapping); | 160 | filemap_fdatawrite(ip->i_inode.i_mapping); |
161 | gfs2_log_flush(gl->gl_sbd, gl); | ||
162 | gfs2_meta_sync(gl); | 162 | gfs2_meta_sync(gl); |
163 | if (ip) { | 163 | if (ip) { |
164 | struct address_space *mapping = ip->i_inode.i_mapping; | 164 | struct address_space *mapping = ip->i_inode.i_mapping; |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index d995441373ab..170ba93829c0 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -28,6 +28,14 @@ struct gfs2_sbd; | |||
28 | 28 | ||
29 | typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret); | 29 | typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret); |
30 | 30 | ||
31 | struct gfs2_log_header_host { | ||
32 | u64 lh_sequence; /* Sequence number of this transaction */ | ||
33 | u32 lh_flags; /* GFS2_LOG_HEAD_... */ | ||
34 | u32 lh_tail; /* Block number of log tail */ | ||
35 | u32 lh_blkno; | ||
36 | u32 lh_hash; | ||
37 | }; | ||
38 | |||
31 | /* | 39 | /* |
32 | * Structure of operations that are associated with each | 40 | * Structure of operations that are associated with each |
33 | * type of element in the log. | 41 | * type of element in the log. |
@@ -60,12 +68,23 @@ struct gfs2_bitmap { | |||
60 | u32 bi_len; | 68 | u32 bi_len; |
61 | }; | 69 | }; |
62 | 70 | ||
71 | struct gfs2_rgrp_host { | ||
72 | u32 rg_flags; | ||
73 | u32 rg_free; | ||
74 | u32 rg_dinodes; | ||
75 | u64 rg_igeneration; | ||
76 | }; | ||
77 | |||
63 | struct gfs2_rgrpd { | 78 | struct gfs2_rgrpd { |
64 | struct list_head rd_list; /* Link with superblock */ | 79 | struct list_head rd_list; /* Link with superblock */ |
65 | struct list_head rd_list_mru; | 80 | struct list_head rd_list_mru; |
66 | struct list_head rd_recent; /* Recently used rgrps */ | 81 | struct list_head rd_recent; /* Recently used rgrps */ |
67 | struct gfs2_glock *rd_gl; /* Glock for this rgrp */ | 82 | struct gfs2_glock *rd_gl; /* Glock for this rgrp */ |
68 | struct gfs2_rindex_host rd_ri; | 83 | u64 rd_addr; /* grp block disk address */ |
84 | u64 rd_data0; /* first data location */ | ||
85 | u32 rd_length; /* length of rgrp header in fs blocks */ | ||
86 | u32 rd_data; /* num of data blocks in rgrp */ | ||
87 | u32 rd_bitbytes; /* number of bytes in data bitmaps */ | ||
69 | struct gfs2_rgrp_host rd_rg; | 88 | struct gfs2_rgrp_host rd_rg; |
70 | u64 rd_rg_vn; | 89 | u64 rd_rg_vn; |
71 | struct gfs2_bitmap *rd_bits; | 90 | struct gfs2_bitmap *rd_bits; |
@@ -76,6 +95,8 @@ struct gfs2_rgrpd { | |||
76 | u32 rd_last_alloc_data; | 95 | u32 rd_last_alloc_data; |
77 | u32 rd_last_alloc_meta; | 96 | u32 rd_last_alloc_meta; |
78 | struct gfs2_sbd *rd_sbd; | 97 | struct gfs2_sbd *rd_sbd; |
98 | unsigned long rd_flags; | ||
99 | #define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */ | ||
79 | }; | 100 | }; |
80 | 101 | ||
81 | enum gfs2_state_bits { | 102 | enum gfs2_state_bits { |
@@ -211,10 +232,24 @@ enum { | |||
211 | GIF_SW_PAGED = 3, | 232 | GIF_SW_PAGED = 3, |
212 | }; | 233 | }; |
213 | 234 | ||
235 | struct gfs2_dinode_host { | ||
236 | u64 di_size; /* number of bytes in file */ | ||
237 | u64 di_blocks; /* number of blocks in file */ | ||
238 | u64 di_goal_meta; /* rgrp to alloc from next */ | ||
239 | u64 di_goal_data; /* data block goal */ | ||
240 | u64 di_generation; /* generation number for NFS */ | ||
241 | u32 di_flags; /* GFS2_DIF_... */ | ||
242 | u16 di_height; /* height of metadata */ | ||
243 | /* These only apply to directories */ | ||
244 | u16 di_depth; /* Number of bits in the table */ | ||
245 | u32 di_entries; /* The number of entries in the directory */ | ||
246 | u64 di_eattr; /* extended attribute block number */ | ||
247 | }; | ||
248 | |||
214 | struct gfs2_inode { | 249 | struct gfs2_inode { |
215 | struct inode i_inode; | 250 | struct inode i_inode; |
216 | struct gfs2_inum_host i_num; | 251 | u64 i_no_addr; |
217 | 252 | u64 i_no_formal_ino; | |
218 | unsigned long i_flags; /* GIF_... */ | 253 | unsigned long i_flags; /* GIF_... */ |
219 | 254 | ||
220 | struct gfs2_dinode_host i_di; /* To be replaced by ref to block */ | 255 | struct gfs2_dinode_host i_di; /* To be replaced by ref to block */ |
@@ -275,14 +310,6 @@ enum { | |||
275 | QDF_LOCKED = 2, | 310 | QDF_LOCKED = 2, |
276 | }; | 311 | }; |
277 | 312 | ||
278 | struct gfs2_quota_lvb { | ||
279 | __be32 qb_magic; | ||
280 | u32 __pad; | ||
281 | __be64 qb_limit; /* Hard limit of # blocks to alloc */ | ||
282 | __be64 qb_warn; /* Warn user when alloc is above this # */ | ||
283 | __be64 qb_value; /* Current # blocks allocated */ | ||
284 | }; | ||
285 | |||
286 | struct gfs2_quota_data { | 313 | struct gfs2_quota_data { |
287 | struct list_head qd_list; | 314 | struct list_head qd_list; |
288 | unsigned int qd_count; | 315 | unsigned int qd_count; |
@@ -327,7 +354,9 @@ struct gfs2_trans { | |||
327 | 354 | ||
328 | unsigned int tr_num_buf; | 355 | unsigned int tr_num_buf; |
329 | unsigned int tr_num_buf_new; | 356 | unsigned int tr_num_buf_new; |
357 | unsigned int tr_num_databuf_new; | ||
330 | unsigned int tr_num_buf_rm; | 358 | unsigned int tr_num_buf_rm; |
359 | unsigned int tr_num_databuf_rm; | ||
331 | struct list_head tr_list_buf; | 360 | struct list_head tr_list_buf; |
332 | 361 | ||
333 | unsigned int tr_num_revoke; | 362 | unsigned int tr_num_revoke; |
@@ -354,6 +383,12 @@ struct gfs2_jdesc { | |||
354 | unsigned int jd_blocks; | 383 | unsigned int jd_blocks; |
355 | }; | 384 | }; |
356 | 385 | ||
386 | struct gfs2_statfs_change_host { | ||
387 | s64 sc_total; | ||
388 | s64 sc_free; | ||
389 | s64 sc_dinodes; | ||
390 | }; | ||
391 | |||
357 | #define GFS2_GLOCKD_DEFAULT 1 | 392 | #define GFS2_GLOCKD_DEFAULT 1 |
358 | #define GFS2_GLOCKD_MAX 16 | 393 | #define GFS2_GLOCKD_MAX 16 |
359 | 394 | ||
@@ -426,6 +461,28 @@ enum { | |||
426 | 461 | ||
427 | #define GFS2_FSNAME_LEN 256 | 462 | #define GFS2_FSNAME_LEN 256 |
428 | 463 | ||
464 | struct gfs2_inum_host { | ||
465 | u64 no_formal_ino; | ||
466 | u64 no_addr; | ||
467 | }; | ||
468 | |||
469 | struct gfs2_sb_host { | ||
470 | u32 sb_magic; | ||
471 | u32 sb_type; | ||
472 | u32 sb_format; | ||
473 | |||
474 | u32 sb_fs_format; | ||
475 | u32 sb_multihost_format; | ||
476 | u32 sb_bsize; | ||
477 | u32 sb_bsize_shift; | ||
478 | |||
479 | struct gfs2_inum_host sb_master_dir; | ||
480 | struct gfs2_inum_host sb_root_dir; | ||
481 | |||
482 | char sb_lockproto[GFS2_LOCKNAME_LEN]; | ||
483 | char sb_locktable[GFS2_LOCKNAME_LEN]; | ||
484 | }; | ||
485 | |||
429 | struct gfs2_sbd { | 486 | struct gfs2_sbd { |
430 | struct super_block *sd_vfs; | 487 | struct super_block *sd_vfs; |
431 | struct super_block *sd_vfs_meta; | 488 | struct super_block *sd_vfs_meta; |
@@ -544,6 +601,7 @@ struct gfs2_sbd { | |||
544 | 601 | ||
545 | unsigned int sd_log_blks_reserved; | 602 | unsigned int sd_log_blks_reserved; |
546 | unsigned int sd_log_commited_buf; | 603 | unsigned int sd_log_commited_buf; |
604 | unsigned int sd_log_commited_databuf; | ||
547 | unsigned int sd_log_commited_revoke; | 605 | unsigned int sd_log_commited_revoke; |
548 | 606 | ||
549 | unsigned int sd_log_num_gl; | 607 | unsigned int sd_log_num_gl; |
@@ -552,7 +610,6 @@ struct gfs2_sbd { | |||
552 | unsigned int sd_log_num_rg; | 610 | unsigned int sd_log_num_rg; |
553 | unsigned int sd_log_num_databuf; | 611 | unsigned int sd_log_num_databuf; |
554 | unsigned int sd_log_num_jdata; | 612 | unsigned int sd_log_num_jdata; |
555 | unsigned int sd_log_num_hdrs; | ||
556 | 613 | ||
557 | struct list_head sd_log_le_gl; | 614 | struct list_head sd_log_le_gl; |
558 | struct list_head sd_log_le_buf; | 615 | struct list_head sd_log_le_buf; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index df0b8b3018b9..34f7bcdea1e9 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -38,12 +38,17 @@ | |||
38 | #include "trans.h" | 38 | #include "trans.h" |
39 | #include "util.h" | 39 | #include "util.h" |
40 | 40 | ||
41 | struct gfs2_inum_range_host { | ||
42 | u64 ir_start; | ||
43 | u64 ir_length; | ||
44 | }; | ||
45 | |||
41 | static int iget_test(struct inode *inode, void *opaque) | 46 | static int iget_test(struct inode *inode, void *opaque) |
42 | { | 47 | { |
43 | struct gfs2_inode *ip = GFS2_I(inode); | 48 | struct gfs2_inode *ip = GFS2_I(inode); |
44 | struct gfs2_inum_host *inum = opaque; | 49 | u64 *no_addr = opaque; |
45 | 50 | ||
46 | if (ip->i_num.no_addr == inum->no_addr && | 51 | if (ip->i_no_addr == *no_addr && |
47 | inode->i_private != NULL) | 52 | inode->i_private != NULL) |
48 | return 1; | 53 | return 1; |
49 | 54 | ||
@@ -53,37 +58,70 @@ static int iget_test(struct inode *inode, void *opaque) | |||
53 | static int iget_set(struct inode *inode, void *opaque) | 58 | static int iget_set(struct inode *inode, void *opaque) |
54 | { | 59 | { |
55 | struct gfs2_inode *ip = GFS2_I(inode); | 60 | struct gfs2_inode *ip = GFS2_I(inode); |
56 | struct gfs2_inum_host *inum = opaque; | 61 | u64 *no_addr = opaque; |
57 | 62 | ||
58 | ip->i_num = *inum; | 63 | inode->i_ino = (unsigned long)*no_addr; |
59 | inode->i_ino = inum->no_addr; | 64 | ip->i_no_addr = *no_addr; |
60 | return 0; | 65 | return 0; |
61 | } | 66 | } |
62 | 67 | ||
63 | struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum) | 68 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) |
69 | { | ||
70 | unsigned long hash = (unsigned long)no_addr; | ||
71 | return ilookup5(sb, hash, iget_test, &no_addr); | ||
72 | } | ||
73 | |||
74 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | ||
64 | { | 75 | { |
65 | return ilookup5(sb, (unsigned long)inum->no_addr, | 76 | unsigned long hash = (unsigned long)no_addr; |
66 | iget_test, inum); | 77 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); |
67 | } | 78 | } |
68 | 79 | ||
69 | static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum) | 80 | /** |
81 | * GFS2 lookup code fills in vfs inode contents based on info obtained | ||
82 | * from directory entry inside gfs2_inode_lookup(). This has caused issues | ||
83 | * with NFS code path since its get_dentry routine doesn't have the relevant | ||
84 | * directory entry when gfs2_inode_lookup() is invoked. Part of the code | ||
85 | * segment inside gfs2_inode_lookup code needs to get moved around. | ||
86 | * | ||
87 | * Clean up I_LOCK and I_NEW as well. | ||
88 | **/ | ||
89 | |||
90 | void gfs2_set_iop(struct inode *inode) | ||
70 | { | 91 | { |
71 | return iget5_locked(sb, (unsigned long)inum->no_addr, | 92 | umode_t mode = inode->i_mode; |
72 | iget_test, iget_set, inum); | 93 | |
94 | if (S_ISREG(mode)) { | ||
95 | inode->i_op = &gfs2_file_iops; | ||
96 | inode->i_fop = &gfs2_file_fops; | ||
97 | inode->i_mapping->a_ops = &gfs2_file_aops; | ||
98 | } else if (S_ISDIR(mode)) { | ||
99 | inode->i_op = &gfs2_dir_iops; | ||
100 | inode->i_fop = &gfs2_dir_fops; | ||
101 | } else if (S_ISLNK(mode)) { | ||
102 | inode->i_op = &gfs2_symlink_iops; | ||
103 | } else { | ||
104 | inode->i_op = &gfs2_dev_iops; | ||
105 | } | ||
106 | |||
107 | unlock_new_inode(inode); | ||
73 | } | 108 | } |
74 | 109 | ||
75 | /** | 110 | /** |
76 | * gfs2_inode_lookup - Lookup an inode | 111 | * gfs2_inode_lookup - Lookup an inode |
77 | * @sb: The super block | 112 | * @sb: The super block |
78 | * @inum: The inode number | 113 | * @no_addr: The inode number |
79 | * @type: The type of the inode | 114 | * @type: The type of the inode |
80 | * | 115 | * |
81 | * Returns: A VFS inode, or an error | 116 | * Returns: A VFS inode, or an error |
82 | */ | 117 | */ |
83 | 118 | ||
84 | struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type) | 119 | struct inode *gfs2_inode_lookup(struct super_block *sb, |
120 | unsigned int type, | ||
121 | u64 no_addr, | ||
122 | u64 no_formal_ino) | ||
85 | { | 123 | { |
86 | struct inode *inode = gfs2_iget(sb, inum); | 124 | struct inode *inode = gfs2_iget(sb, no_addr); |
87 | struct gfs2_inode *ip = GFS2_I(inode); | 125 | struct gfs2_inode *ip = GFS2_I(inode); |
88 | struct gfs2_glock *io_gl; | 126 | struct gfs2_glock *io_gl; |
89 | int error; | 127 | int error; |
@@ -93,29 +131,15 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i | |||
93 | 131 | ||
94 | if (inode->i_state & I_NEW) { | 132 | if (inode->i_state & I_NEW) { |
95 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 133 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
96 | umode_t mode = DT2IF(type); | ||
97 | inode->i_private = ip; | 134 | inode->i_private = ip; |
98 | inode->i_mode = mode; | 135 | ip->i_no_formal_ino = no_formal_ino; |
99 | |||
100 | if (S_ISREG(mode)) { | ||
101 | inode->i_op = &gfs2_file_iops; | ||
102 | inode->i_fop = &gfs2_file_fops; | ||
103 | inode->i_mapping->a_ops = &gfs2_file_aops; | ||
104 | } else if (S_ISDIR(mode)) { | ||
105 | inode->i_op = &gfs2_dir_iops; | ||
106 | inode->i_fop = &gfs2_dir_fops; | ||
107 | } else if (S_ISLNK(mode)) { | ||
108 | inode->i_op = &gfs2_symlink_iops; | ||
109 | } else { | ||
110 | inode->i_op = &gfs2_dev_iops; | ||
111 | } | ||
112 | 136 | ||
113 | error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); | 137 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
114 | if (unlikely(error)) | 138 | if (unlikely(error)) |
115 | goto fail; | 139 | goto fail; |
116 | ip->i_gl->gl_object = ip; | 140 | ip->i_gl->gl_object = ip; |
117 | 141 | ||
118 | error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl); | 142 | error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); |
119 | if (unlikely(error)) | 143 | if (unlikely(error)) |
120 | goto fail_put; | 144 | goto fail_put; |
121 | 145 | ||
@@ -123,12 +147,38 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i | |||
123 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); | 147 | error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); |
124 | if (unlikely(error)) | 148 | if (unlikely(error)) |
125 | goto fail_iopen; | 149 | goto fail_iopen; |
150 | ip->i_iopen_gh.gh_gl->gl_object = ip; | ||
126 | 151 | ||
127 | gfs2_glock_put(io_gl); | 152 | gfs2_glock_put(io_gl); |
128 | unlock_new_inode(inode); | 153 | |
154 | if ((type == DT_UNKNOWN) && (no_formal_ino == 0)) | ||
155 | goto gfs2_nfsbypass; | ||
156 | |||
157 | inode->i_mode = DT2IF(type); | ||
158 | |||
159 | /* | ||
160 | * We must read the inode in order to work out its type in | ||
161 | * this case. Note that this doesn't happen often as we normally | ||
162 | * know the type beforehand. This code path only occurs during | ||
163 | * unlinked inode recovery (where it is safe to do this glock, | ||
164 | * which is not true in the general case). | ||
165 | */ | ||
166 | if (type == DT_UNKNOWN) { | ||
167 | struct gfs2_holder gh; | ||
168 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
169 | if (unlikely(error)) | ||
170 | goto fail_glock; | ||
171 | /* Inode is now uptodate */ | ||
172 | gfs2_glock_dq_uninit(&gh); | ||
173 | } | ||
174 | |||
175 | gfs2_set_iop(inode); | ||
129 | } | 176 | } |
130 | 177 | ||
178 | gfs2_nfsbypass: | ||
131 | return inode; | 179 | return inode; |
180 | fail_glock: | ||
181 | gfs2_glock_dq(&ip->i_iopen_gh); | ||
132 | fail_iopen: | 182 | fail_iopen: |
133 | gfs2_glock_put(io_gl); | 183 | gfs2_glock_put(io_gl); |
134 | fail_put: | 184 | fail_put: |
@@ -144,14 +194,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
144 | struct gfs2_dinode_host *di = &ip->i_di; | 194 | struct gfs2_dinode_host *di = &ip->i_di; |
145 | const struct gfs2_dinode *str = buf; | 195 | const struct gfs2_dinode *str = buf; |
146 | 196 | ||
147 | if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) { | 197 | if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) { |
148 | if (gfs2_consist_inode(ip)) | 198 | if (gfs2_consist_inode(ip)) |
149 | gfs2_dinode_print(ip); | 199 | gfs2_dinode_print(ip); |
150 | return -EIO; | 200 | return -EIO; |
151 | } | 201 | } |
152 | if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino)) | 202 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); |
153 | return -ESTALE; | ||
154 | |||
155 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); | 203 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); |
156 | ip->i_inode.i_rdev = 0; | 204 | ip->i_inode.i_rdev = 0; |
157 | switch (ip->i_inode.i_mode & S_IFMT) { | 205 | switch (ip->i_inode.i_mode & S_IFMT) { |
@@ -175,11 +223,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
175 | di->di_blocks = be64_to_cpu(str->di_blocks); | 223 | di->di_blocks = be64_to_cpu(str->di_blocks); |
176 | gfs2_set_inode_blocks(&ip->i_inode); | 224 | gfs2_set_inode_blocks(&ip->i_inode); |
177 | ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); | 225 | ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); |
178 | ip->i_inode.i_atime.tv_nsec = 0; | 226 | ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); |
179 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); | 227 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); |
180 | ip->i_inode.i_mtime.tv_nsec = 0; | 228 | ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); |
181 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); | 229 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); |
182 | ip->i_inode.i_ctime.tv_nsec = 0; | 230 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); |
183 | 231 | ||
184 | di->di_goal_meta = be64_to_cpu(str->di_goal_meta); | 232 | di->di_goal_meta = be64_to_cpu(str->di_goal_meta); |
185 | di->di_goal_data = be64_to_cpu(str->di_goal_data); | 233 | di->di_goal_data = be64_to_cpu(str->di_goal_data); |
@@ -247,7 +295,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) | |||
247 | if (error) | 295 | if (error) |
248 | goto out_qs; | 296 | goto out_qs; |
249 | 297 | ||
250 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | 298 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); |
251 | if (!rgd) { | 299 | if (!rgd) { |
252 | gfs2_consist_inode(ip); | 300 | gfs2_consist_inode(ip); |
253 | error = -EIO; | 301 | error = -EIO; |
@@ -314,7 +362,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) | |||
314 | else | 362 | else |
315 | drop_nlink(&ip->i_inode); | 363 | drop_nlink(&ip->i_inode); |
316 | 364 | ||
317 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 365 | ip->i_inode.i_ctime = CURRENT_TIME; |
318 | 366 | ||
319 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 367 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
320 | gfs2_dinode_out(ip, dibh->b_data); | 368 | gfs2_dinode_out(ip, dibh->b_data); |
@@ -366,9 +414,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
366 | struct super_block *sb = dir->i_sb; | 414 | struct super_block *sb = dir->i_sb; |
367 | struct gfs2_inode *dip = GFS2_I(dir); | 415 | struct gfs2_inode *dip = GFS2_I(dir); |
368 | struct gfs2_holder d_gh; | 416 | struct gfs2_holder d_gh; |
369 | struct gfs2_inum_host inum; | 417 | int error = 0; |
370 | unsigned int type; | ||
371 | int error; | ||
372 | struct inode *inode = NULL; | 418 | struct inode *inode = NULL; |
373 | int unlock = 0; | 419 | int unlock = 0; |
374 | 420 | ||
@@ -395,12 +441,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
395 | goto out; | 441 | goto out; |
396 | } | 442 | } |
397 | 443 | ||
398 | error = gfs2_dir_search(dir, name, &inum, &type); | 444 | inode = gfs2_dir_search(dir, name); |
399 | if (error) | 445 | if (IS_ERR(inode)) |
400 | goto out; | 446 | error = PTR_ERR(inode); |
401 | |||
402 | inode = gfs2_inode_lookup(sb, &inum, type); | ||
403 | |||
404 | out: | 447 | out: |
405 | if (unlock) | 448 | if (unlock) |
406 | gfs2_glock_dq_uninit(&d_gh); | 449 | gfs2_glock_dq_uninit(&d_gh); |
@@ -409,6 +452,22 @@ out: | |||
409 | return inode ? inode : ERR_PTR(error); | 452 | return inode ? inode : ERR_PTR(error); |
410 | } | 453 | } |
411 | 454 | ||
455 | static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf) | ||
456 | { | ||
457 | const struct gfs2_inum_range *str = buf; | ||
458 | |||
459 | ir->ir_start = be64_to_cpu(str->ir_start); | ||
460 | ir->ir_length = be64_to_cpu(str->ir_length); | ||
461 | } | ||
462 | |||
463 | static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf) | ||
464 | { | ||
465 | struct gfs2_inum_range *str = buf; | ||
466 | |||
467 | str->ir_start = cpu_to_be64(ir->ir_start); | ||
468 | str->ir_length = cpu_to_be64(ir->ir_length); | ||
469 | } | ||
470 | |||
412 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) | 471 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) |
413 | { | 472 | { |
414 | struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode); | 473 | struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode); |
@@ -548,7 +607,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
548 | if (!dip->i_inode.i_nlink) | 607 | if (!dip->i_inode.i_nlink) |
549 | return -EPERM; | 608 | return -EPERM; |
550 | 609 | ||
551 | error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL); | 610 | error = gfs2_dir_check(&dip->i_inode, name, NULL); |
552 | switch (error) { | 611 | switch (error) { |
553 | case -ENOENT: | 612 | case -ENOENT: |
554 | error = 0; | 613 | error = 0; |
@@ -588,8 +647,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, | |||
588 | *gid = current->fsgid; | 647 | *gid = current->fsgid; |
589 | } | 648 | } |
590 | 649 | ||
591 | static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum, | 650 | static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) |
592 | u64 *generation) | ||
593 | { | 651 | { |
594 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 652 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
595 | int error; | 653 | int error; |
@@ -605,7 +663,7 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum, | |||
605 | if (error) | 663 | if (error) |
606 | goto out_ipreserv; | 664 | goto out_ipreserv; |
607 | 665 | ||
608 | inum->no_addr = gfs2_alloc_di(dip, generation); | 666 | *no_addr = gfs2_alloc_di(dip, generation); |
609 | 667 | ||
610 | gfs2_trans_end(sdp); | 668 | gfs2_trans_end(sdp); |
611 | 669 | ||
@@ -635,6 +693,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
635 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 693 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
636 | struct gfs2_dinode *di; | 694 | struct gfs2_dinode *di; |
637 | struct buffer_head *dibh; | 695 | struct buffer_head *dibh; |
696 | struct timespec tv = CURRENT_TIME; | ||
638 | 697 | ||
639 | dibh = gfs2_meta_new(gl, inum->no_addr); | 698 | dibh = gfs2_meta_new(gl, inum->no_addr); |
640 | gfs2_trans_add_bh(gl, dibh, 1); | 699 | gfs2_trans_add_bh(gl, dibh, 1); |
@@ -650,7 +709,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
650 | di->di_nlink = 0; | 709 | di->di_nlink = 0; |
651 | di->di_size = 0; | 710 | di->di_size = 0; |
652 | di->di_blocks = cpu_to_be64(1); | 711 | di->di_blocks = cpu_to_be64(1); |
653 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds()); | 712 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); |
654 | di->di_major = cpu_to_be32(MAJOR(dev)); | 713 | di->di_major = cpu_to_be32(MAJOR(dev)); |
655 | di->di_minor = cpu_to_be32(MINOR(dev)); | 714 | di->di_minor = cpu_to_be32(MINOR(dev)); |
656 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); | 715 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); |
@@ -680,6 +739,9 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
680 | di->di_entries = 0; | 739 | di->di_entries = 0; |
681 | memset(&di->__pad4, 0, sizeof(di->__pad4)); | 740 | memset(&di->__pad4, 0, sizeof(di->__pad4)); |
682 | di->di_eattr = 0; | 741 | di->di_eattr = 0; |
742 | di->di_atime_nsec = cpu_to_be32(tv.tv_nsec); | ||
743 | di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); | ||
744 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); | ||
683 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); | 745 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); |
684 | 746 | ||
685 | brelse(dibh); | 747 | brelse(dibh); |
@@ -749,7 +811,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, | |||
749 | goto fail_quota_locks; | 811 | goto fail_quota_locks; |
750 | 812 | ||
751 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 813 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
752 | al->al_rgd->rd_ri.ri_length + | 814 | al->al_rgd->rd_length + |
753 | 2 * RES_DINODE + | 815 | 2 * RES_DINODE + |
754 | RES_STATFS + RES_QUOTA, 0); | 816 | RES_STATFS + RES_QUOTA, 0); |
755 | if (error) | 817 | if (error) |
@@ -760,7 +822,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, | |||
760 | goto fail_quota_locks; | 822 | goto fail_quota_locks; |
761 | } | 823 | } |
762 | 824 | ||
763 | error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode)); | 825 | error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode)); |
764 | if (error) | 826 | if (error) |
765 | goto fail_end_trans; | 827 | goto fail_end_trans; |
766 | 828 | ||
@@ -840,11 +902,11 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip) | |||
840 | struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | 902 | struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, |
841 | unsigned int mode, dev_t dev) | 903 | unsigned int mode, dev_t dev) |
842 | { | 904 | { |
843 | struct inode *inode; | 905 | struct inode *inode = NULL; |
844 | struct gfs2_inode *dip = ghs->gh_gl->gl_object; | 906 | struct gfs2_inode *dip = ghs->gh_gl->gl_object; |
845 | struct inode *dir = &dip->i_inode; | 907 | struct inode *dir = &dip->i_inode; |
846 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 908 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
847 | struct gfs2_inum_host inum; | 909 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; |
848 | int error; | 910 | int error; |
849 | u64 generation; | 911 | u64 generation; |
850 | 912 | ||
@@ -864,7 +926,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
864 | if (error) | 926 | if (error) |
865 | goto fail_gunlock; | 927 | goto fail_gunlock; |
866 | 928 | ||
867 | error = alloc_dinode(dip, &inum, &generation); | 929 | error = alloc_dinode(dip, &inum.no_addr, &generation); |
868 | if (error) | 930 | if (error) |
869 | goto fail_gunlock; | 931 | goto fail_gunlock; |
870 | 932 | ||
@@ -877,34 +939,36 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
877 | if (error) | 939 | if (error) |
878 | goto fail_gunlock2; | 940 | goto fail_gunlock2; |
879 | 941 | ||
880 | inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode)); | 942 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), |
943 | inum.no_addr, | ||
944 | inum.no_formal_ino); | ||
881 | if (IS_ERR(inode)) | 945 | if (IS_ERR(inode)) |
882 | goto fail_gunlock2; | 946 | goto fail_gunlock2; |
883 | 947 | ||
884 | error = gfs2_inode_refresh(GFS2_I(inode)); | 948 | error = gfs2_inode_refresh(GFS2_I(inode)); |
885 | if (error) | 949 | if (error) |
886 | goto fail_iput; | 950 | goto fail_gunlock2; |
887 | 951 | ||
888 | error = gfs2_acl_create(dip, GFS2_I(inode)); | 952 | error = gfs2_acl_create(dip, GFS2_I(inode)); |
889 | if (error) | 953 | if (error) |
890 | goto fail_iput; | 954 | goto fail_gunlock2; |
891 | 955 | ||
892 | error = gfs2_security_init(dip, GFS2_I(inode)); | 956 | error = gfs2_security_init(dip, GFS2_I(inode)); |
893 | if (error) | 957 | if (error) |
894 | goto fail_iput; | 958 | goto fail_gunlock2; |
895 | 959 | ||
896 | error = link_dinode(dip, name, GFS2_I(inode)); | 960 | error = link_dinode(dip, name, GFS2_I(inode)); |
897 | if (error) | 961 | if (error) |
898 | goto fail_iput; | 962 | goto fail_gunlock2; |
899 | 963 | ||
900 | if (!inode) | 964 | if (!inode) |
901 | return ERR_PTR(-ENOMEM); | 965 | return ERR_PTR(-ENOMEM); |
902 | return inode; | 966 | return inode; |
903 | 967 | ||
904 | fail_iput: | ||
905 | iput(inode); | ||
906 | fail_gunlock2: | 968 | fail_gunlock2: |
907 | gfs2_glock_dq_uninit(ghs + 1); | 969 | gfs2_glock_dq_uninit(ghs + 1); |
970 | if (inode) | ||
971 | iput(inode); | ||
908 | fail_gunlock: | 972 | fail_gunlock: |
909 | gfs2_glock_dq(ghs); | 973 | gfs2_glock_dq(ghs); |
910 | fail: | 974 | fail: |
@@ -976,10 +1040,8 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, | |||
976 | */ | 1040 | */ |
977 | 1041 | ||
978 | int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | 1042 | int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, |
979 | struct gfs2_inode *ip) | 1043 | const struct gfs2_inode *ip) |
980 | { | 1044 | { |
981 | struct gfs2_inum_host inum; | ||
982 | unsigned int type; | ||
983 | int error; | 1045 | int error; |
984 | 1046 | ||
985 | if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode)) | 1047 | if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode)) |
@@ -997,18 +1059,10 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
997 | if (error) | 1059 | if (error) |
998 | return error; | 1060 | return error; |
999 | 1061 | ||
1000 | error = gfs2_dir_search(&dip->i_inode, name, &inum, &type); | 1062 | error = gfs2_dir_check(&dip->i_inode, name, ip); |
1001 | if (error) | 1063 | if (error) |
1002 | return error; | 1064 | return error; |
1003 | 1065 | ||
1004 | if (!gfs2_inum_equal(&inum, &ip->i_num)) | ||
1005 | return -ENOENT; | ||
1006 | |||
1007 | if (IF2DT(ip->i_inode.i_mode) != type) { | ||
1008 | gfs2_consist_inode(dip); | ||
1009 | return -EIO; | ||
1010 | } | ||
1011 | |||
1012 | return 0; | 1066 | return 0; |
1013 | } | 1067 | } |
1014 | 1068 | ||
@@ -1132,10 +1186,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) | |||
1132 | struct gfs2_glock *gl = gh->gh_gl; | 1186 | struct gfs2_glock *gl = gh->gh_gl; |
1133 | struct gfs2_sbd *sdp = gl->gl_sbd; | 1187 | struct gfs2_sbd *sdp = gl->gl_sbd; |
1134 | struct gfs2_inode *ip = gl->gl_object; | 1188 | struct gfs2_inode *ip = gl->gl_object; |
1135 | s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum); | 1189 | s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum); |
1136 | unsigned int state; | 1190 | unsigned int state; |
1137 | int flags; | 1191 | int flags; |
1138 | int error; | 1192 | int error; |
1193 | struct timespec tv = CURRENT_TIME; | ||
1139 | 1194 | ||
1140 | if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) || | 1195 | if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) || |
1141 | gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || | 1196 | gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || |
@@ -1153,8 +1208,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) | |||
1153 | (sdp->sd_vfs->s_flags & MS_RDONLY)) | 1208 | (sdp->sd_vfs->s_flags & MS_RDONLY)) |
1154 | return 0; | 1209 | return 0; |
1155 | 1210 | ||
1156 | curtime = get_seconds(); | 1211 | if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { |
1157 | if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) { | ||
1158 | gfs2_glock_dq(gh); | 1212 | gfs2_glock_dq(gh); |
1159 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, | 1213 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, |
1160 | gh); | 1214 | gh); |
@@ -1165,8 +1219,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) | |||
1165 | /* Verify that atime hasn't been updated while we were | 1219 | /* Verify that atime hasn't been updated while we were |
1166 | trying to get exclusive lock. */ | 1220 | trying to get exclusive lock. */ |
1167 | 1221 | ||
1168 | curtime = get_seconds(); | 1222 | tv = CURRENT_TIME; |
1169 | if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) { | 1223 | if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { |
1170 | struct buffer_head *dibh; | 1224 | struct buffer_head *dibh; |
1171 | struct gfs2_dinode *di; | 1225 | struct gfs2_dinode *di; |
1172 | 1226 | ||
@@ -1180,11 +1234,12 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) | |||
1180 | if (error) | 1234 | if (error) |
1181 | goto fail_end_trans; | 1235 | goto fail_end_trans; |
1182 | 1236 | ||
1183 | ip->i_inode.i_atime.tv_sec = curtime; | 1237 | ip->i_inode.i_atime = tv; |
1184 | 1238 | ||
1185 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1239 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
1186 | di = (struct gfs2_dinode *)dibh->b_data; | 1240 | di = (struct gfs2_dinode *)dibh->b_data; |
1187 | di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | 1241 | di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); |
1242 | di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); | ||
1188 | brelse(dibh); | 1243 | brelse(dibh); |
1189 | 1244 | ||
1190 | gfs2_trans_end(sdp); | 1245 | gfs2_trans_end(sdp); |
@@ -1252,3 +1307,66 @@ int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | |||
1252 | return error; | 1307 | return error; |
1253 | } | 1308 | } |
1254 | 1309 | ||
1310 | void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | ||
1311 | { | ||
1312 | const struct gfs2_dinode_host *di = &ip->i_di; | ||
1313 | struct gfs2_dinode *str = buf; | ||
1314 | |||
1315 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
1316 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); | ||
1317 | str->di_header.__pad0 = 0; | ||
1318 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); | ||
1319 | str->di_header.__pad1 = 0; | ||
1320 | str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); | ||
1321 | str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); | ||
1322 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); | ||
1323 | str->di_uid = cpu_to_be32(ip->i_inode.i_uid); | ||
1324 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); | ||
1325 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); | ||
1326 | str->di_size = cpu_to_be64(di->di_size); | ||
1327 | str->di_blocks = cpu_to_be64(di->di_blocks); | ||
1328 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | ||
1329 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); | ||
1330 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); | ||
1331 | |||
1332 | str->di_goal_meta = cpu_to_be64(di->di_goal_meta); | ||
1333 | str->di_goal_data = cpu_to_be64(di->di_goal_data); | ||
1334 | str->di_generation = cpu_to_be64(di->di_generation); | ||
1335 | |||
1336 | str->di_flags = cpu_to_be32(di->di_flags); | ||
1337 | str->di_height = cpu_to_be16(di->di_height); | ||
1338 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && | ||
1339 | !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? | ||
1340 | GFS2_FORMAT_DE : 0); | ||
1341 | str->di_depth = cpu_to_be16(di->di_depth); | ||
1342 | str->di_entries = cpu_to_be32(di->di_entries); | ||
1343 | |||
1344 | str->di_eattr = cpu_to_be64(di->di_eattr); | ||
1345 | str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); | ||
1346 | str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec); | ||
1347 | str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec); | ||
1348 | } | ||
1349 | |||
1350 | void gfs2_dinode_print(const struct gfs2_inode *ip) | ||
1351 | { | ||
1352 | const struct gfs2_dinode_host *di = &ip->i_di; | ||
1353 | |||
1354 | printk(KERN_INFO " no_formal_ino = %llu\n", | ||
1355 | (unsigned long long)ip->i_no_formal_ino); | ||
1356 | printk(KERN_INFO " no_addr = %llu\n", | ||
1357 | (unsigned long long)ip->i_no_addr); | ||
1358 | printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); | ||
1359 | printk(KERN_INFO " di_blocks = %llu\n", | ||
1360 | (unsigned long long)di->di_blocks); | ||
1361 | printk(KERN_INFO " di_goal_meta = %llu\n", | ||
1362 | (unsigned long long)di->di_goal_meta); | ||
1363 | printk(KERN_INFO " di_goal_data = %llu\n", | ||
1364 | (unsigned long long)di->di_goal_data); | ||
1365 | printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags); | ||
1366 | printk(KERN_INFO " di_height = %u\n", di->di_height); | ||
1367 | printk(KERN_INFO " di_depth = %u\n", di->di_depth); | ||
1368 | printk(KERN_INFO " di_entries = %u\n", di->di_entries); | ||
1369 | printk(KERN_INFO " di_eattr = %llu\n", | ||
1370 | (unsigned long long)di->di_eattr); | ||
1371 | } | ||
1372 | |||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index b57f448b15bc..4517ac82c01c 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -10,17 +10,17 @@ | |||
10 | #ifndef __INODE_DOT_H__ | 10 | #ifndef __INODE_DOT_H__ |
11 | #define __INODE_DOT_H__ | 11 | #define __INODE_DOT_H__ |
12 | 12 | ||
13 | static inline int gfs2_is_stuffed(struct gfs2_inode *ip) | 13 | static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) |
14 | { | 14 | { |
15 | return !ip->i_di.di_height; | 15 | return !ip->i_di.di_height; |
16 | } | 16 | } |
17 | 17 | ||
18 | static inline int gfs2_is_jdata(struct gfs2_inode *ip) | 18 | static inline int gfs2_is_jdata(const struct gfs2_inode *ip) |
19 | { | 19 | { |
20 | return ip->i_di.di_flags & GFS2_DIF_JDATA; | 20 | return ip->i_di.di_flags & GFS2_DIF_JDATA; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline int gfs2_is_dir(struct gfs2_inode *ip) | 23 | static inline int gfs2_is_dir(const struct gfs2_inode *ip) |
24 | { | 24 | { |
25 | return S_ISDIR(ip->i_inode.i_mode); | 25 | return S_ISDIR(ip->i_inode.i_mode); |
26 | } | 26 | } |
@@ -32,9 +32,25 @@ static inline void gfs2_set_inode_blocks(struct inode *inode) | |||
32 | (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); | 32 | (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); |
33 | } | 33 | } |
34 | 34 | ||
35 | static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr, | ||
36 | u64 no_formal_ino) | ||
37 | { | ||
38 | return ip->i_no_addr == no_addr && ip->i_no_formal_ino == no_formal_ino; | ||
39 | } | ||
40 | |||
41 | static inline void gfs2_inum_out(const struct gfs2_inode *ip, | ||
42 | struct gfs2_dirent *dent) | ||
43 | { | ||
44 | dent->de_inum.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); | ||
45 | dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr); | ||
46 | } | ||
47 | |||
48 | |||
35 | void gfs2_inode_attr_in(struct gfs2_inode *ip); | 49 | void gfs2_inode_attr_in(struct gfs2_inode *ip); |
36 | struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type); | 50 | void gfs2_set_iop(struct inode *inode); |
37 | struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum); | 51 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, |
52 | u64 no_addr, u64 no_formal_ino); | ||
53 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); | ||
38 | 54 | ||
39 | int gfs2_inode_refresh(struct gfs2_inode *ip); | 55 | int gfs2_inode_refresh(struct gfs2_inode *ip); |
40 | 56 | ||
@@ -47,12 +63,14 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
47 | int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, | 63 | int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, |
48 | struct gfs2_inode *ip); | 64 | struct gfs2_inode *ip); |
49 | int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | 65 | int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, |
50 | struct gfs2_inode *ip); | 66 | const struct gfs2_inode *ip); |
51 | int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to); | 67 | int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to); |
52 | int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len); | 68 | int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len); |
53 | int gfs2_glock_nq_atime(struct gfs2_holder *gh); | 69 | int gfs2_glock_nq_atime(struct gfs2_holder *gh); |
54 | int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); | 70 | int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); |
55 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); | 71 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); |
72 | void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | ||
73 | void gfs2_dinode_print(const struct gfs2_inode *ip); | ||
56 | 74 | ||
57 | #endif /* __INODE_DOT_H__ */ | 75 | #endif /* __INODE_DOT_H__ */ |
58 | 76 | ||
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c index c305255bfe8a..542a797ac89a 100644 --- a/fs/gfs2/locking/dlm/lock.c +++ b/fs/gfs2/locking/dlm/lock.c | |||
@@ -174,7 +174,6 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, | |||
174 | lp->cur = DLM_LOCK_IV; | 174 | lp->cur = DLM_LOCK_IV; |
175 | lp->lvb = NULL; | 175 | lp->lvb = NULL; |
176 | lp->hold_null = NULL; | 176 | lp->hold_null = NULL; |
177 | init_completion(&lp->ast_wait); | ||
178 | INIT_LIST_HEAD(&lp->clist); | 177 | INIT_LIST_HEAD(&lp->clist); |
179 | INIT_LIST_HEAD(&lp->blist); | 178 | INIT_LIST_HEAD(&lp->blist); |
180 | INIT_LIST_HEAD(&lp->delay_list); | 179 | INIT_LIST_HEAD(&lp->delay_list); |
@@ -399,6 +398,12 @@ static void gdlm_del_lvb(struct gdlm_lock *lp) | |||
399 | lp->lksb.sb_lvbptr = NULL; | 398 | lp->lksb.sb_lvbptr = NULL; |
400 | } | 399 | } |
401 | 400 | ||
401 | static int gdlm_ast_wait(void *word) | ||
402 | { | ||
403 | schedule(); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
402 | /* This can do a synchronous dlm request (requiring a lock_dlm thread to get | 407 | /* This can do a synchronous dlm request (requiring a lock_dlm thread to get |
403 | the completion) because gfs won't call hold_lvb() during a callback (from | 408 | the completion) because gfs won't call hold_lvb() during a callback (from |
404 | the context of a lock_dlm thread). */ | 409 | the context of a lock_dlm thread). */ |
@@ -424,10 +429,10 @@ static int hold_null_lock(struct gdlm_lock *lp) | |||
424 | lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE; | 429 | lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE; |
425 | set_bit(LFL_NOBAST, &lpn->flags); | 430 | set_bit(LFL_NOBAST, &lpn->flags); |
426 | set_bit(LFL_INLOCK, &lpn->flags); | 431 | set_bit(LFL_INLOCK, &lpn->flags); |
432 | set_bit(LFL_AST_WAIT, &lpn->flags); | ||
427 | 433 | ||
428 | init_completion(&lpn->ast_wait); | ||
429 | gdlm_do_lock(lpn); | 434 | gdlm_do_lock(lpn); |
430 | wait_for_completion(&lpn->ast_wait); | 435 | wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE); |
431 | error = lpn->lksb.sb_status; | 436 | error = lpn->lksb.sb_status; |
432 | if (error) { | 437 | if (error) { |
433 | printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", | 438 | printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", |
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h index d074c6e6f9bf..24d70f73b651 100644 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ b/fs/gfs2/locking/dlm/lock_dlm.h | |||
@@ -101,6 +101,7 @@ enum { | |||
101 | LFL_NOBAST = 10, | 101 | LFL_NOBAST = 10, |
102 | LFL_HEADQUE = 11, | 102 | LFL_HEADQUE = 11, |
103 | LFL_UNLOCK_DELETE = 12, | 103 | LFL_UNLOCK_DELETE = 12, |
104 | LFL_AST_WAIT = 13, | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | struct gdlm_lock { | 107 | struct gdlm_lock { |
@@ -117,7 +118,6 @@ struct gdlm_lock { | |||
117 | unsigned long flags; /* lock_dlm flags LFL_ */ | 118 | unsigned long flags; /* lock_dlm flags LFL_ */ |
118 | 119 | ||
119 | int bast_mode; /* protected by async_lock */ | 120 | int bast_mode; /* protected by async_lock */ |
120 | struct completion ast_wait; | ||
121 | 121 | ||
122 | struct list_head clist; /* complete */ | 122 | struct list_head clist; /* complete */ |
123 | struct list_head blist; /* blocking */ | 123 | struct list_head blist; /* blocking */ |
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c index 1d8faa3da8af..41c5b04caaba 100644 --- a/fs/gfs2/locking/dlm/mount.c +++ b/fs/gfs2/locking/dlm/mount.c | |||
@@ -147,7 +147,7 @@ static int gdlm_mount(char *table_name, char *host_data, | |||
147 | 147 | ||
148 | error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), | 148 | error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), |
149 | &ls->dlm_lockspace, | 149 | &ls->dlm_lockspace, |
150 | nodir ? DLM_LSFL_NODIR : 0, | 150 | DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0), |
151 | GDLM_LVB_SIZE); | 151 | GDLM_LVB_SIZE); |
152 | if (error) { | 152 | if (error) { |
153 | log_error("dlm_new_lockspace error %d", error); | 153 | log_error("dlm_new_lockspace error %d", error); |
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c index f82495e18c2d..fba1f1d87e4f 100644 --- a/fs/gfs2/locking/dlm/plock.c +++ b/fs/gfs2/locking/dlm/plock.c | |||
@@ -242,7 +242,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name, | |||
242 | op->info.number = name->ln_number; | 242 | op->info.number = name->ln_number; |
243 | op->info.start = fl->fl_start; | 243 | op->info.start = fl->fl_start; |
244 | op->info.end = fl->fl_end; | 244 | op->info.end = fl->fl_end; |
245 | 245 | op->info.owner = (__u64)(long) fl->fl_owner; | |
246 | 246 | ||
247 | send_op(op); | 247 | send_op(op); |
248 | wait_event(recv_wq, (op->done != 0)); | 248 | wait_event(recv_wq, (op->done != 0)); |
@@ -254,16 +254,20 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name, | |||
254 | } | 254 | } |
255 | spin_unlock(&ops_lock); | 255 | spin_unlock(&ops_lock); |
256 | 256 | ||
257 | /* info.rv from userspace is 1 for conflict, 0 for no-conflict, | ||
258 | -ENOENT if there are no locks on the file */ | ||
259 | |||
257 | rv = op->info.rv; | 260 | rv = op->info.rv; |
258 | 261 | ||
259 | fl->fl_type = F_UNLCK; | 262 | fl->fl_type = F_UNLCK; |
260 | if (rv == -ENOENT) | 263 | if (rv == -ENOENT) |
261 | rv = 0; | 264 | rv = 0; |
262 | else if (rv == 0 && op->info.pid != fl->fl_pid) { | 265 | else if (rv > 0) { |
263 | fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; | 266 | fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; |
264 | fl->fl_pid = op->info.pid; | 267 | fl->fl_pid = op->info.pid; |
265 | fl->fl_start = op->info.start; | 268 | fl->fl_start = op->info.start; |
266 | fl->fl_end = op->info.end; | 269 | fl->fl_end = op->info.end; |
270 | rv = 0; | ||
267 | } | 271 | } |
268 | 272 | ||
269 | kfree(op); | 273 | kfree(op); |
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c index 9cf1f168eaf8..1aca51e45092 100644 --- a/fs/gfs2/locking/dlm/thread.c +++ b/fs/gfs2/locking/dlm/thread.c | |||
@@ -44,6 +44,13 @@ static void process_blocking(struct gdlm_lock *lp, int bast_mode) | |||
44 | ls->fscb(ls->sdp, cb, &lp->lockname); | 44 | ls->fscb(ls->sdp, cb, &lp->lockname); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void wake_up_ast(struct gdlm_lock *lp) | ||
48 | { | ||
49 | clear_bit(LFL_AST_WAIT, &lp->flags); | ||
50 | smp_mb__after_clear_bit(); | ||
51 | wake_up_bit(&lp->flags, LFL_AST_WAIT); | ||
52 | } | ||
53 | |||
47 | static void process_complete(struct gdlm_lock *lp) | 54 | static void process_complete(struct gdlm_lock *lp) |
48 | { | 55 | { |
49 | struct gdlm_ls *ls = lp->ls; | 56 | struct gdlm_ls *ls = lp->ls; |
@@ -136,7 +143,7 @@ static void process_complete(struct gdlm_lock *lp) | |||
136 | */ | 143 | */ |
137 | 144 | ||
138 | if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { | 145 | if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { |
139 | complete(&lp->ast_wait); | 146 | wake_up_ast(lp); |
140 | return; | 147 | return; |
141 | } | 148 | } |
142 | 149 | ||
@@ -214,7 +221,7 @@ out: | |||
214 | if (test_bit(LFL_INLOCK, &lp->flags)) { | 221 | if (test_bit(LFL_INLOCK, &lp->flags)) { |
215 | clear_bit(LFL_NOBLOCK, &lp->flags); | 222 | clear_bit(LFL_NOBLOCK, &lp->flags); |
216 | lp->cur = lp->req; | 223 | lp->cur = lp->req; |
217 | complete(&lp->ast_wait); | 224 | wake_up_ast(lp); |
218 | return; | 225 | return; |
219 | } | 226 | } |
220 | 227 | ||
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 291415ddfe51..f49a12e24086 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -83,6 +83,11 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
83 | 83 | ||
84 | gfs2_assert(sdp, bd->bd_ail == ai); | 84 | gfs2_assert(sdp, bd->bd_ail == ai); |
85 | 85 | ||
86 | if (!bh){ | ||
87 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
88 | continue; | ||
89 | } | ||
90 | |||
86 | if (!buffer_busy(bh)) { | 91 | if (!buffer_busy(bh)) { |
87 | if (!buffer_uptodate(bh)) { | 92 | if (!buffer_uptodate(bh)) { |
88 | gfs2_log_unlock(sdp); | 93 | gfs2_log_unlock(sdp); |
@@ -125,6 +130,11 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
125 | bd_ail_st_list) { | 130 | bd_ail_st_list) { |
126 | bh = bd->bd_bh; | 131 | bh = bd->bd_bh; |
127 | 132 | ||
133 | if (!bh){ | ||
134 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
135 | continue; | ||
136 | } | ||
137 | |||
128 | gfs2_assert(sdp, bd->bd_ail == ai); | 138 | gfs2_assert(sdp, bd->bd_ail == ai); |
129 | 139 | ||
130 | if (buffer_busy(bh)) { | 140 | if (buffer_busy(bh)) { |
@@ -262,8 +272,8 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
262 | * @sdp: The GFS2 superblock | 272 | * @sdp: The GFS2 superblock |
263 | * @blks: The number of blocks to reserve | 273 | * @blks: The number of blocks to reserve |
264 | * | 274 | * |
265 | * Note that we never give out the last 6 blocks of the journal. Thats | 275 | * Note that we never give out the last few blocks of the journal. Thats |
266 | * due to the fact that there is are a small number of header blocks | 276 | * due to the fact that there is a small number of header blocks |
267 | * associated with each log flush. The exact number can't be known until | 277 | * associated with each log flush. The exact number can't be known until |
268 | * flush time, so we ensure that we have just enough free blocks at all | 278 | * flush time, so we ensure that we have just enough free blocks at all |
269 | * times to avoid running out during a log flush. | 279 | * times to avoid running out during a log flush. |
@@ -274,6 +284,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
274 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 284 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) |
275 | { | 285 | { |
276 | unsigned int try = 0; | 286 | unsigned int try = 0; |
287 | unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize); | ||
277 | 288 | ||
278 | if (gfs2_assert_warn(sdp, blks) || | 289 | if (gfs2_assert_warn(sdp, blks) || |
279 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) | 290 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) |
@@ -281,7 +292,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | |||
281 | 292 | ||
282 | mutex_lock(&sdp->sd_log_reserve_mutex); | 293 | mutex_lock(&sdp->sd_log_reserve_mutex); |
283 | gfs2_log_lock(sdp); | 294 | gfs2_log_lock(sdp); |
284 | while(sdp->sd_log_blks_free <= (blks + 6)) { | 295 | while(sdp->sd_log_blks_free <= (blks + reserved_blks)) { |
285 | gfs2_log_unlock(sdp); | 296 | gfs2_log_unlock(sdp); |
286 | gfs2_ail1_empty(sdp, 0); | 297 | gfs2_ail1_empty(sdp, 0); |
287 | gfs2_log_flush(sdp, NULL); | 298 | gfs2_log_flush(sdp, NULL); |
@@ -357,6 +368,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer | |||
357 | return dist; | 368 | return dist; |
358 | } | 369 | } |
359 | 370 | ||
371 | /** | ||
372 | * calc_reserved - Calculate the number of blocks to reserve when | ||
373 | * refunding a transaction's unused buffers. | ||
374 | * @sdp: The GFS2 superblock | ||
375 | * | ||
376 | * This is complex. We need to reserve room for all our currently used | ||
377 | * metadata buffers (e.g. normal file I/O rewriting file time stamps) and | ||
378 | * all our journaled data buffers for journaled files (e.g. files in the | ||
379 | * meta_fs like rindex, or files for which chattr +j was done.) | ||
380 | * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush | ||
381 | * will count it as free space (sd_log_blks_free) and corruption will follow. | ||
382 | * | ||
383 | * We can have metadata bufs and jdata bufs in the same journal. So each | ||
384 | * type gets its own log header, for which we need to reserve a block. | ||
385 | * In fact, each type has the potential for needing more than one header | ||
386 | * in cases where we have more buffers than will fit on a journal page. | ||
387 | * Metadata journal entries take up half the space of journaled buffer entries. | ||
388 | * Thus, metadata entries have buf_limit (502) and journaled buffers have | ||
389 | * databuf_limit (251) before they cause a wrap around. | ||
390 | * | ||
391 | * Also, we need to reserve blocks for revoke journal entries and one for an | ||
392 | * overall header for the lot. | ||
393 | * | ||
394 | * Returns: the number of blocks reserved | ||
395 | */ | ||
396 | static unsigned int calc_reserved(struct gfs2_sbd *sdp) | ||
397 | { | ||
398 | unsigned int reserved = 0; | ||
399 | unsigned int mbuf_limit, metabufhdrs_needed; | ||
400 | unsigned int dbuf_limit, databufhdrs_needed; | ||
401 | unsigned int revokes = 0; | ||
402 | |||
403 | mbuf_limit = buf_limit(sdp); | ||
404 | metabufhdrs_needed = (sdp->sd_log_commited_buf + | ||
405 | (mbuf_limit - 1)) / mbuf_limit; | ||
406 | dbuf_limit = databuf_limit(sdp); | ||
407 | databufhdrs_needed = (sdp->sd_log_commited_databuf + | ||
408 | (dbuf_limit - 1)) / dbuf_limit; | ||
409 | |||
410 | if (sdp->sd_log_commited_revoke) | ||
411 | revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, | ||
412 | sizeof(u64)); | ||
413 | |||
414 | reserved = sdp->sd_log_commited_buf + metabufhdrs_needed + | ||
415 | sdp->sd_log_commited_databuf + databufhdrs_needed + | ||
416 | revokes; | ||
417 | /* One for the overall header */ | ||
418 | if (reserved) | ||
419 | reserved++; | ||
420 | return reserved; | ||
421 | } | ||
422 | |||
360 | static unsigned int current_tail(struct gfs2_sbd *sdp) | 423 | static unsigned int current_tail(struct gfs2_sbd *sdp) |
361 | { | 424 | { |
362 | struct gfs2_ail *ai; | 425 | struct gfs2_ail *ai; |
@@ -447,14 +510,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | |||
447 | return bh; | 510 | return bh; |
448 | } | 511 | } |
449 | 512 | ||
450 | static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull) | 513 | static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) |
451 | { | 514 | { |
452 | unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); | 515 | unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail); |
453 | 516 | ||
454 | ail2_empty(sdp, new_tail); | 517 | ail2_empty(sdp, new_tail); |
455 | 518 | ||
456 | gfs2_log_lock(sdp); | 519 | gfs2_log_lock(sdp); |
457 | sdp->sd_log_blks_free += dist - (pull ? 1 : 0); | 520 | sdp->sd_log_blks_free += dist; |
458 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); | 521 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); |
459 | gfs2_log_unlock(sdp); | 522 | gfs2_log_unlock(sdp); |
460 | 523 | ||
@@ -504,7 +567,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) | |||
504 | brelse(bh); | 567 | brelse(bh); |
505 | 568 | ||
506 | if (sdp->sd_log_tail != tail) | 569 | if (sdp->sd_log_tail != tail) |
507 | log_pull_tail(sdp, tail, pull); | 570 | log_pull_tail(sdp, tail); |
508 | else | 571 | else |
509 | gfs2_assert_withdraw(sdp, !pull); | 572 | gfs2_assert_withdraw(sdp, !pull); |
510 | 573 | ||
@@ -517,6 +580,7 @@ static void log_flush_commit(struct gfs2_sbd *sdp) | |||
517 | struct list_head *head = &sdp->sd_log_flush_list; | 580 | struct list_head *head = &sdp->sd_log_flush_list; |
518 | struct gfs2_log_buf *lb; | 581 | struct gfs2_log_buf *lb; |
519 | struct buffer_head *bh; | 582 | struct buffer_head *bh; |
583 | int flushcount = 0; | ||
520 | 584 | ||
521 | while (!list_empty(head)) { | 585 | while (!list_empty(head)) { |
522 | lb = list_entry(head->next, struct gfs2_log_buf, lb_list); | 586 | lb = list_entry(head->next, struct gfs2_log_buf, lb_list); |
@@ -533,9 +597,20 @@ static void log_flush_commit(struct gfs2_sbd *sdp) | |||
533 | } else | 597 | } else |
534 | brelse(bh); | 598 | brelse(bh); |
535 | kfree(lb); | 599 | kfree(lb); |
600 | flushcount++; | ||
536 | } | 601 | } |
537 | 602 | ||
538 | log_write_header(sdp, 0, 0); | 603 | /* If nothing was journaled, the header is unplanned and unwanted. */ |
604 | if (flushcount) { | ||
605 | log_write_header(sdp, 0, 0); | ||
606 | } else { | ||
607 | unsigned int tail; | ||
608 | tail = current_tail(sdp); | ||
609 | |||
610 | gfs2_ail1_empty(sdp, 0); | ||
611 | if (sdp->sd_log_tail != tail) | ||
612 | log_pull_tail(sdp, tail); | ||
613 | } | ||
539 | } | 614 | } |
540 | 615 | ||
541 | /** | 616 | /** |
@@ -565,7 +640,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
565 | INIT_LIST_HEAD(&ai->ai_ail1_list); | 640 | INIT_LIST_HEAD(&ai->ai_ail1_list); |
566 | INIT_LIST_HEAD(&ai->ai_ail2_list); | 641 | INIT_LIST_HEAD(&ai->ai_ail2_list); |
567 | 642 | ||
568 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf); | 643 | gfs2_assert_withdraw(sdp, |
644 | sdp->sd_log_num_buf + sdp->sd_log_num_jdata == | ||
645 | sdp->sd_log_commited_buf + | ||
646 | sdp->sd_log_commited_databuf); | ||
569 | gfs2_assert_withdraw(sdp, | 647 | gfs2_assert_withdraw(sdp, |
570 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); | 648 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); |
571 | 649 | ||
@@ -576,16 +654,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
576 | lops_before_commit(sdp); | 654 | lops_before_commit(sdp); |
577 | if (!list_empty(&sdp->sd_log_flush_list)) | 655 | if (!list_empty(&sdp->sd_log_flush_list)) |
578 | log_flush_commit(sdp); | 656 | log_flush_commit(sdp); |
579 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle) | 657 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ |
658 | gfs2_log_lock(sdp); | ||
659 | sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */ | ||
660 | gfs2_log_unlock(sdp); | ||
580 | log_write_header(sdp, 0, PULL); | 661 | log_write_header(sdp, 0, PULL); |
662 | } | ||
581 | lops_after_commit(sdp, ai); | 663 | lops_after_commit(sdp, ai); |
582 | 664 | ||
583 | gfs2_log_lock(sdp); | 665 | gfs2_log_lock(sdp); |
584 | sdp->sd_log_head = sdp->sd_log_flush_head; | 666 | sdp->sd_log_head = sdp->sd_log_flush_head; |
585 | sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs; | ||
586 | sdp->sd_log_blks_reserved = 0; | 667 | sdp->sd_log_blks_reserved = 0; |
587 | sdp->sd_log_commited_buf = 0; | 668 | sdp->sd_log_commited_buf = 0; |
588 | sdp->sd_log_num_hdrs = 0; | 669 | sdp->sd_log_commited_databuf = 0; |
589 | sdp->sd_log_commited_revoke = 0; | 670 | sdp->sd_log_commited_revoke = 0; |
590 | 671 | ||
591 | if (!list_empty(&ai->ai_ail1_list)) { | 672 | if (!list_empty(&ai->ai_ail1_list)) { |
@@ -602,32 +683,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
602 | 683 | ||
603 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 684 | static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
604 | { | 685 | { |
605 | unsigned int reserved = 0; | 686 | unsigned int reserved; |
606 | unsigned int old; | 687 | unsigned int old; |
607 | 688 | ||
608 | gfs2_log_lock(sdp); | 689 | gfs2_log_lock(sdp); |
609 | 690 | ||
610 | sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; | 691 | sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; |
611 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0); | 692 | sdp->sd_log_commited_databuf += tr->tr_num_databuf_new - |
693 | tr->tr_num_databuf_rm; | ||
694 | gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || | ||
695 | (((int)sdp->sd_log_commited_databuf) >= 0)); | ||
612 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; | 696 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; |
613 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); | 697 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); |
614 | 698 | reserved = calc_reserved(sdp); | |
615 | if (sdp->sd_log_commited_buf) | ||
616 | reserved += sdp->sd_log_commited_buf; | ||
617 | if (sdp->sd_log_commited_revoke) | ||
618 | reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, | ||
619 | sizeof(u64)); | ||
620 | if (reserved) | ||
621 | reserved++; | ||
622 | |||
623 | old = sdp->sd_log_blks_free; | 699 | old = sdp->sd_log_blks_free; |
624 | sdp->sd_log_blks_free += tr->tr_reserved - | 700 | sdp->sd_log_blks_free += tr->tr_reserved - |
625 | (reserved - sdp->sd_log_blks_reserved); | 701 | (reserved - sdp->sd_log_blks_reserved); |
626 | 702 | ||
627 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old); | 703 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old); |
628 | gfs2_assert_withdraw(sdp, | 704 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= |
629 | sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks + | 705 | sdp->sd_jdesc->jd_blocks); |
630 | sdp->sd_log_num_hdrs); | ||
631 | 706 | ||
632 | sdp->sd_log_blks_reserved = reserved; | 707 | sdp->sd_log_blks_reserved = reserved; |
633 | 708 | ||
@@ -673,13 +748,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) | |||
673 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 748 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
674 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); | 749 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); |
675 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); | 750 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); |
676 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs); | ||
677 | gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); | 751 | gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); |
678 | 752 | ||
679 | sdp->sd_log_flush_head = sdp->sd_log_head; | 753 | sdp->sd_log_flush_head = sdp->sd_log_head; |
680 | sdp->sd_log_flush_wrapped = 0; | 754 | sdp->sd_log_flush_wrapped = 0; |
681 | 755 | ||
682 | log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0); | 756 | log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, |
757 | (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); | ||
683 | 758 | ||
684 | gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); | 759 | gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks); |
685 | gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); | 760 | gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index f82d84d05d23..aff70f0698fd 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include "gfs2.h" | 18 | #include "gfs2.h" |
19 | #include "incore.h" | 19 | #include "incore.h" |
20 | #include "inode.h" | ||
20 | #include "glock.h" | 21 | #include "glock.h" |
21 | #include "log.h" | 22 | #include "log.h" |
22 | #include "lops.h" | 23 | #include "lops.h" |
@@ -117,15 +118,13 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
117 | struct gfs2_log_descriptor *ld; | 118 | struct gfs2_log_descriptor *ld; |
118 | struct gfs2_bufdata *bd1 = NULL, *bd2; | 119 | struct gfs2_bufdata *bd1 = NULL, *bd2; |
119 | unsigned int total = sdp->sd_log_num_buf; | 120 | unsigned int total = sdp->sd_log_num_buf; |
120 | unsigned int offset = sizeof(struct gfs2_log_descriptor); | 121 | unsigned int offset = BUF_OFFSET; |
121 | unsigned int limit; | 122 | unsigned int limit; |
122 | unsigned int num; | 123 | unsigned int num; |
123 | unsigned n; | 124 | unsigned n; |
124 | __be64 *ptr; | 125 | __be64 *ptr; |
125 | 126 | ||
126 | offset += sizeof(__be64) - 1; | 127 | limit = buf_limit(sdp); |
127 | offset &= ~(sizeof(__be64) - 1); | ||
128 | limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64); | ||
129 | /* for 4k blocks, limit = 503 */ | 128 | /* for 4k blocks, limit = 503 */ |
130 | 129 | ||
131 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); | 130 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); |
@@ -134,7 +133,6 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
134 | if (total > limit) | 133 | if (total > limit) |
135 | num = limit; | 134 | num = limit; |
136 | bh = gfs2_log_get_buf(sdp); | 135 | bh = gfs2_log_get_buf(sdp); |
137 | sdp->sd_log_num_hdrs++; | ||
138 | ld = (struct gfs2_log_descriptor *)bh->b_data; | 136 | ld = (struct gfs2_log_descriptor *)bh->b_data; |
139 | ptr = (__be64 *)(bh->b_data + offset); | 137 | ptr = (__be64 *)(bh->b_data + offset); |
140 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 138 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
@@ -469,25 +467,28 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
469 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 467 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
470 | 468 | ||
471 | gfs2_log_lock(sdp); | 469 | gfs2_log_lock(sdp); |
470 | if (!list_empty(&bd->bd_list_tr)) { | ||
471 | gfs2_log_unlock(sdp); | ||
472 | return; | ||
473 | } | ||
472 | tr->tr_touched = 1; | 474 | tr->tr_touched = 1; |
473 | if (list_empty(&bd->bd_list_tr) && | 475 | if (gfs2_is_jdata(ip)) { |
474 | (ip->i_di.di_flags & GFS2_DIF_JDATA)) { | ||
475 | tr->tr_num_buf++; | 476 | tr->tr_num_buf++; |
476 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 477 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
477 | gfs2_log_unlock(sdp); | ||
478 | gfs2_pin(sdp, bd->bd_bh); | ||
479 | tr->tr_num_buf_new++; | ||
480 | } else { | ||
481 | gfs2_log_unlock(sdp); | ||
482 | } | 478 | } |
479 | gfs2_log_unlock(sdp); | ||
480 | if (!list_empty(&le->le_list)) | ||
481 | return; | ||
482 | |||
483 | gfs2_trans_add_gl(bd->bd_gl); | 483 | gfs2_trans_add_gl(bd->bd_gl); |
484 | gfs2_log_lock(sdp); | 484 | if (gfs2_is_jdata(ip)) { |
485 | if (list_empty(&le->le_list)) { | 485 | sdp->sd_log_num_jdata++; |
486 | if (ip->i_di.di_flags & GFS2_DIF_JDATA) | 486 | gfs2_pin(sdp, bd->bd_bh); |
487 | sdp->sd_log_num_jdata++; | 487 | tr->tr_num_databuf_new++; |
488 | sdp->sd_log_num_databuf++; | ||
489 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
490 | } | 488 | } |
489 | sdp->sd_log_num_databuf++; | ||
490 | gfs2_log_lock(sdp); | ||
491 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
491 | gfs2_log_unlock(sdp); | 492 | gfs2_log_unlock(sdp); |
492 | } | 493 | } |
493 | 494 | ||
@@ -520,7 +521,6 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
520 | LIST_HEAD(started); | 521 | LIST_HEAD(started); |
521 | struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; | 522 | struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; |
522 | struct buffer_head *bh = NULL,*bh1 = NULL; | 523 | struct buffer_head *bh = NULL,*bh1 = NULL; |
523 | unsigned int offset = sizeof(struct gfs2_log_descriptor); | ||
524 | struct gfs2_log_descriptor *ld; | 524 | struct gfs2_log_descriptor *ld; |
525 | unsigned int limit; | 525 | unsigned int limit; |
526 | unsigned int total_dbuf = sdp->sd_log_num_databuf; | 526 | unsigned int total_dbuf = sdp->sd_log_num_databuf; |
@@ -528,9 +528,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
528 | unsigned int num, n; | 528 | unsigned int num, n; |
529 | __be64 *ptr = NULL; | 529 | __be64 *ptr = NULL; |
530 | 530 | ||
531 | offset += 2*sizeof(__be64) - 1; | 531 | limit = databuf_limit(sdp); |
532 | offset &= ~(2*sizeof(__be64) - 1); | ||
533 | limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64); | ||
534 | 532 | ||
535 | /* | 533 | /* |
536 | * Start writing ordered buffers, write journaled buffers | 534 | * Start writing ordered buffers, write journaled buffers |
@@ -581,10 +579,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
581 | gfs2_log_unlock(sdp); | 579 | gfs2_log_unlock(sdp); |
582 | if (!bh) { | 580 | if (!bh) { |
583 | bh = gfs2_log_get_buf(sdp); | 581 | bh = gfs2_log_get_buf(sdp); |
584 | sdp->sd_log_num_hdrs++; | ||
585 | ld = (struct gfs2_log_descriptor *) | 582 | ld = (struct gfs2_log_descriptor *) |
586 | bh->b_data; | 583 | bh->b_data; |
587 | ptr = (__be64 *)(bh->b_data + offset); | 584 | ptr = (__be64 *)(bh->b_data + |
585 | DATABUF_OFFSET); | ||
588 | ld->ld_header.mh_magic = | 586 | ld->ld_header.mh_magic = |
589 | cpu_to_be32(GFS2_MAGIC); | 587 | cpu_to_be32(GFS2_MAGIC); |
590 | ld->ld_header.mh_type = | 588 | ld->ld_header.mh_type = |
@@ -605,7 +603,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
605 | if (unlikely(magic != 0)) | 603 | if (unlikely(magic != 0)) |
606 | set_buffer_escaped(bh1); | 604 | set_buffer_escaped(bh1); |
607 | gfs2_log_lock(sdp); | 605 | gfs2_log_lock(sdp); |
608 | if (n++ > num) | 606 | if (++n >= num) |
609 | break; | 607 | break; |
610 | } else if (!bh1) { | 608 | } else if (!bh1) { |
611 | total_dbuf--; | 609 | total_dbuf--; |
@@ -622,6 +620,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | |||
622 | } | 620 | } |
623 | gfs2_log_unlock(sdp); | 621 | gfs2_log_unlock(sdp); |
624 | if (bh) { | 622 | if (bh) { |
623 | set_buffer_mapped(bh); | ||
625 | set_buffer_dirty(bh); | 624 | set_buffer_dirty(bh); |
626 | ll_rw_block(WRITE, 1, &bh); | 625 | ll_rw_block(WRITE, 1, &bh); |
627 | bh = NULL; | 626 | bh = NULL; |
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index 965bc65c7c64..41a00df75587 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h | |||
@@ -13,6 +13,13 @@ | |||
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include "incore.h" | 14 | #include "incore.h" |
15 | 15 | ||
16 | #define BUF_OFFSET \ | ||
17 | ((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \ | ||
18 | ~(sizeof(__be64) - 1)) | ||
19 | #define DATABUF_OFFSET \ | ||
20 | ((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \ | ||
21 | ~(2 * sizeof(__be64) - 1)) | ||
22 | |||
16 | extern const struct gfs2_log_operations gfs2_glock_lops; | 23 | extern const struct gfs2_log_operations gfs2_glock_lops; |
17 | extern const struct gfs2_log_operations gfs2_buf_lops; | 24 | extern const struct gfs2_log_operations gfs2_buf_lops; |
18 | extern const struct gfs2_log_operations gfs2_revoke_lops; | 25 | extern const struct gfs2_log_operations gfs2_revoke_lops; |
@@ -21,6 +28,22 @@ extern const struct gfs2_log_operations gfs2_databuf_lops; | |||
21 | 28 | ||
22 | extern const struct gfs2_log_operations *gfs2_log_ops[]; | 29 | extern const struct gfs2_log_operations *gfs2_log_ops[]; |
23 | 30 | ||
31 | static inline unsigned int buf_limit(struct gfs2_sbd *sdp) | ||
32 | { | ||
33 | unsigned int limit; | ||
34 | |||
35 | limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64); | ||
36 | return limit; | ||
37 | } | ||
38 | |||
39 | static inline unsigned int databuf_limit(struct gfs2_sbd *sdp) | ||
40 | { | ||
41 | unsigned int limit; | ||
42 | |||
43 | limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64)); | ||
44 | return limit; | ||
45 | } | ||
46 | |||
24 | static inline void lops_init_le(struct gfs2_log_element *le, | 47 | static inline void lops_init_le(struct gfs2_log_element *le, |
25 | const struct gfs2_log_operations *lops) | 48 | const struct gfs2_log_operations *lops) |
26 | { | 49 | { |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index e62d4f620c58..8da343b34ae7 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -387,12 +387,18 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) | |||
387 | 387 | ||
388 | if (test_clear_buffer_pinned(bh)) { | 388 | if (test_clear_buffer_pinned(bh)) { |
389 | struct gfs2_trans *tr = current->journal_info; | 389 | struct gfs2_trans *tr = current->journal_info; |
390 | struct gfs2_inode *bh_ip = | ||
391 | GFS2_I(bh->b_page->mapping->host); | ||
392 | |||
390 | gfs2_log_lock(sdp); | 393 | gfs2_log_lock(sdp); |
391 | list_del_init(&bd->bd_le.le_list); | 394 | list_del_init(&bd->bd_le.le_list); |
392 | gfs2_assert_warn(sdp, sdp->sd_log_num_buf); | 395 | gfs2_assert_warn(sdp, sdp->sd_log_num_buf); |
393 | sdp->sd_log_num_buf--; | 396 | sdp->sd_log_num_buf--; |
394 | gfs2_log_unlock(sdp); | 397 | gfs2_log_unlock(sdp); |
395 | tr->tr_num_buf_rm++; | 398 | if (bh_ip->i_inode.i_private != NULL) |
399 | tr->tr_num_databuf_rm++; | ||
400 | else | ||
401 | tr->tr_num_buf_rm++; | ||
396 | brelse(bh); | 402 | brelse(bh); |
397 | } | 403 | } |
398 | if (bd) { | 404 | if (bd) { |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index e037425bc042..527bf19d9690 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -63,7 +63,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, | |||
63 | static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip, | 63 | static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip, |
64 | struct buffer_head **bhp) | 64 | struct buffer_head **bhp) |
65 | { | 65 | { |
66 | return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp); | 66 | return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp); |
67 | } | 67 | } |
68 | 68 | ||
69 | struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); | 69 | struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); |
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 4864659555d4..6f006a804db3 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c | |||
@@ -82,20 +82,19 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
82 | char *options, *o, *v; | 82 | char *options, *o, *v; |
83 | int error = 0; | 83 | int error = 0; |
84 | 84 | ||
85 | if (!remount) { | 85 | /* If someone preloaded options, use those instead */ |
86 | /* If someone preloaded options, use those instead */ | 86 | spin_lock(&gfs2_sys_margs_lock); |
87 | spin_lock(&gfs2_sys_margs_lock); | 87 | if (!remount && gfs2_sys_margs) { |
88 | if (gfs2_sys_margs) { | 88 | data = gfs2_sys_margs; |
89 | data = gfs2_sys_margs; | 89 | gfs2_sys_margs = NULL; |
90 | gfs2_sys_margs = NULL; | ||
91 | } | ||
92 | spin_unlock(&gfs2_sys_margs_lock); | ||
93 | |||
94 | /* Set some defaults */ | ||
95 | args->ar_num_glockd = GFS2_GLOCKD_DEFAULT; | ||
96 | args->ar_quota = GFS2_QUOTA_DEFAULT; | ||
97 | args->ar_data = GFS2_DATA_DEFAULT; | ||
98 | } | 90 | } |
91 | spin_unlock(&gfs2_sys_margs_lock); | ||
92 | |||
93 | /* Set some defaults */ | ||
94 | memset(args, 0, sizeof(struct gfs2_args)); | ||
95 | args->ar_num_glockd = GFS2_GLOCKD_DEFAULT; | ||
96 | args->ar_quota = GFS2_QUOTA_DEFAULT; | ||
97 | args->ar_data = GFS2_DATA_DEFAULT; | ||
99 | 98 | ||
100 | /* Split the options into tokens with the "," character and | 99 | /* Split the options into tokens with the "," character and |
101 | process them */ | 100 | process them */ |
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c deleted file mode 100644 index d9ecfd23a49e..000000000000 --- a/fs/gfs2/ondisk.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * This copyrighted material is made available to anyone wishing to use, | ||
6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/completion.h> | ||
13 | #include <linux/buffer_head.h> | ||
14 | |||
15 | #include "gfs2.h" | ||
16 | #include <linux/gfs2_ondisk.h> | ||
17 | #include <linux/lm_interface.h> | ||
18 | #include "incore.h" | ||
19 | |||
20 | #define pv(struct, member, fmt) printk(KERN_INFO " "#member" = "fmt"\n", \ | ||
21 | struct->member); | ||
22 | |||
23 | /* | ||
24 | * gfs2_xxx_in - read in an xxx struct | ||
25 | * first arg: the cpu-order structure | ||
26 | * buf: the disk-order buffer | ||
27 | * | ||
28 | * gfs2_xxx_out - write out an xxx struct | ||
29 | * first arg: the cpu-order structure | ||
30 | * buf: the disk-order buffer | ||
31 | * | ||
32 | * gfs2_xxx_print - print out an xxx struct | ||
33 | * first arg: the cpu-order structure | ||
34 | */ | ||
35 | |||
36 | void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf) | ||
37 | { | ||
38 | const struct gfs2_inum *str = buf; | ||
39 | |||
40 | no->no_formal_ino = be64_to_cpu(str->no_formal_ino); | ||
41 | no->no_addr = be64_to_cpu(str->no_addr); | ||
42 | } | ||
43 | |||
44 | void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf) | ||
45 | { | ||
46 | struct gfs2_inum *str = buf; | ||
47 | |||
48 | str->no_formal_ino = cpu_to_be64(no->no_formal_ino); | ||
49 | str->no_addr = cpu_to_be64(no->no_addr); | ||
50 | } | ||
51 | |||
52 | static void gfs2_inum_print(const struct gfs2_inum_host *no) | ||
53 | { | ||
54 | printk(KERN_INFO " no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino); | ||
55 | printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr); | ||
56 | } | ||
57 | |||
58 | static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf) | ||
59 | { | ||
60 | const struct gfs2_meta_header *str = buf; | ||
61 | |||
62 | mh->mh_magic = be32_to_cpu(str->mh_magic); | ||
63 | mh->mh_type = be32_to_cpu(str->mh_type); | ||
64 | mh->mh_format = be32_to_cpu(str->mh_format); | ||
65 | } | ||
66 | |||
67 | void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) | ||
68 | { | ||
69 | const struct gfs2_sb *str = buf; | ||
70 | |||
71 | gfs2_meta_header_in(&sb->sb_header, buf); | ||
72 | |||
73 | sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); | ||
74 | sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); | ||
75 | sb->sb_bsize = be32_to_cpu(str->sb_bsize); | ||
76 | sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); | ||
77 | |||
78 | gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir); | ||
79 | gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir); | ||
80 | |||
81 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); | ||
82 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); | ||
83 | } | ||
84 | |||
85 | void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf) | ||
86 | { | ||
87 | const struct gfs2_rindex *str = buf; | ||
88 | |||
89 | ri->ri_addr = be64_to_cpu(str->ri_addr); | ||
90 | ri->ri_length = be32_to_cpu(str->ri_length); | ||
91 | ri->ri_data0 = be64_to_cpu(str->ri_data0); | ||
92 | ri->ri_data = be32_to_cpu(str->ri_data); | ||
93 | ri->ri_bitbytes = be32_to_cpu(str->ri_bitbytes); | ||
94 | |||
95 | } | ||
96 | |||
97 | void gfs2_rindex_print(const struct gfs2_rindex_host *ri) | ||
98 | { | ||
99 | printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)ri->ri_addr); | ||
100 | pv(ri, ri_length, "%u"); | ||
101 | |||
102 | printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)ri->ri_data0); | ||
103 | pv(ri, ri_data, "%u"); | ||
104 | |||
105 | pv(ri, ri_bitbytes, "%u"); | ||
106 | } | ||
107 | |||
108 | void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) | ||
109 | { | ||
110 | const struct gfs2_rgrp *str = buf; | ||
111 | |||
112 | rg->rg_flags = be32_to_cpu(str->rg_flags); | ||
113 | rg->rg_free = be32_to_cpu(str->rg_free); | ||
114 | rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); | ||
115 | rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); | ||
116 | } | ||
117 | |||
118 | void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) | ||
119 | { | ||
120 | struct gfs2_rgrp *str = buf; | ||
121 | |||
122 | str->rg_flags = cpu_to_be32(rg->rg_flags); | ||
123 | str->rg_free = cpu_to_be32(rg->rg_free); | ||
124 | str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); | ||
125 | str->__pad = cpu_to_be32(0); | ||
126 | str->rg_igeneration = cpu_to_be64(rg->rg_igeneration); | ||
127 | memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); | ||
128 | } | ||
129 | |||
130 | void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) | ||
131 | { | ||
132 | const struct gfs2_quota *str = buf; | ||
133 | |||
134 | qu->qu_limit = be64_to_cpu(str->qu_limit); | ||
135 | qu->qu_warn = be64_to_cpu(str->qu_warn); | ||
136 | qu->qu_value = be64_to_cpu(str->qu_value); | ||
137 | } | ||
138 | |||
139 | void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | ||
140 | { | ||
141 | const struct gfs2_dinode_host *di = &ip->i_di; | ||
142 | struct gfs2_dinode *str = buf; | ||
143 | |||
144 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
145 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); | ||
146 | str->di_header.__pad0 = 0; | ||
147 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); | ||
148 | str->di_header.__pad1 = 0; | ||
149 | |||
150 | gfs2_inum_out(&ip->i_num, &str->di_num); | ||
151 | |||
152 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); | ||
153 | str->di_uid = cpu_to_be32(ip->i_inode.i_uid); | ||
154 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); | ||
155 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); | ||
156 | str->di_size = cpu_to_be64(di->di_size); | ||
157 | str->di_blocks = cpu_to_be64(di->di_blocks); | ||
158 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | ||
159 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); | ||
160 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); | ||
161 | |||
162 | str->di_goal_meta = cpu_to_be64(di->di_goal_meta); | ||
163 | str->di_goal_data = cpu_to_be64(di->di_goal_data); | ||
164 | str->di_generation = cpu_to_be64(di->di_generation); | ||
165 | |||
166 | str->di_flags = cpu_to_be32(di->di_flags); | ||
167 | str->di_height = cpu_to_be16(di->di_height); | ||
168 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && | ||
169 | !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? | ||
170 | GFS2_FORMAT_DE : 0); | ||
171 | str->di_depth = cpu_to_be16(di->di_depth); | ||
172 | str->di_entries = cpu_to_be32(di->di_entries); | ||
173 | |||
174 | str->di_eattr = cpu_to_be64(di->di_eattr); | ||
175 | } | ||
176 | |||
177 | void gfs2_dinode_print(const struct gfs2_inode *ip) | ||
178 | { | ||
179 | const struct gfs2_dinode_host *di = &ip->i_di; | ||
180 | |||
181 | gfs2_inum_print(&ip->i_num); | ||
182 | |||
183 | printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); | ||
184 | printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks); | ||
185 | printk(KERN_INFO " di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta); | ||
186 | printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data); | ||
187 | |||
188 | pv(di, di_flags, "0x%.8X"); | ||
189 | pv(di, di_height, "%u"); | ||
190 | |||
191 | pv(di, di_depth, "%u"); | ||
192 | pv(di, di_entries, "%u"); | ||
193 | |||
194 | printk(KERN_INFO " di_eattr = %llu\n", (unsigned long long)di->di_eattr); | ||
195 | } | ||
196 | |||
197 | void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf) | ||
198 | { | ||
199 | const struct gfs2_log_header *str = buf; | ||
200 | |||
201 | gfs2_meta_header_in(&lh->lh_header, buf); | ||
202 | lh->lh_sequence = be64_to_cpu(str->lh_sequence); | ||
203 | lh->lh_flags = be32_to_cpu(str->lh_flags); | ||
204 | lh->lh_tail = be32_to_cpu(str->lh_tail); | ||
205 | lh->lh_blkno = be32_to_cpu(str->lh_blkno); | ||
206 | lh->lh_hash = be32_to_cpu(str->lh_hash); | ||
207 | } | ||
208 | |||
209 | void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf) | ||
210 | { | ||
211 | const struct gfs2_inum_range *str = buf; | ||
212 | |||
213 | ir->ir_start = be64_to_cpu(str->ir_start); | ||
214 | ir->ir_length = be64_to_cpu(str->ir_length); | ||
215 | } | ||
216 | |||
217 | void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf) | ||
218 | { | ||
219 | struct gfs2_inum_range *str = buf; | ||
220 | |||
221 | str->ir_start = cpu_to_be64(ir->ir_start); | ||
222 | str->ir_length = cpu_to_be64(ir->ir_length); | ||
223 | } | ||
224 | |||
225 | void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | ||
226 | { | ||
227 | const struct gfs2_statfs_change *str = buf; | ||
228 | |||
229 | sc->sc_total = be64_to_cpu(str->sc_total); | ||
230 | sc->sc_free = be64_to_cpu(str->sc_free); | ||
231 | sc->sc_dinodes = be64_to_cpu(str->sc_dinodes); | ||
232 | } | ||
233 | |||
234 | void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf) | ||
235 | { | ||
236 | struct gfs2_statfs_change *str = buf; | ||
237 | |||
238 | str->sc_total = cpu_to_be64(sc->sc_total); | ||
239 | str->sc_free = cpu_to_be64(sc->sc_free); | ||
240 | str->sc_dinodes = cpu_to_be64(sc->sc_dinodes); | ||
241 | } | ||
242 | |||
243 | void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf) | ||
244 | { | ||
245 | const struct gfs2_quota_change *str = buf; | ||
246 | |||
247 | qc->qc_change = be64_to_cpu(str->qc_change); | ||
248 | qc->qc_flags = be32_to_cpu(str->qc_flags); | ||
249 | qc->qc_id = be32_to_cpu(str->qc_id); | ||
250 | } | ||
251 | |||
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 30c15622174f..26c888890c24 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -32,6 +32,7 @@ | |||
32 | #include "trans.h" | 32 | #include "trans.h" |
33 | #include "rgrp.h" | 33 | #include "rgrp.h" |
34 | #include "ops_file.h" | 34 | #include "ops_file.h" |
35 | #include "super.h" | ||
35 | #include "util.h" | 36 | #include "util.h" |
36 | #include "glops.h" | 37 | #include "glops.h" |
37 | 38 | ||
@@ -49,6 +50,8 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, | |||
49 | end = start + bsize; | 50 | end = start + bsize; |
50 | if (end <= from || start >= to) | 51 | if (end <= from || start >= to) |
51 | continue; | 52 | continue; |
53 | if (gfs2_is_jdata(ip)) | ||
54 | set_buffer_uptodate(bh); | ||
52 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | 55 | gfs2_trans_add_bh(ip->i_gl, bh, 0); |
53 | } | 56 | } |
54 | } | 57 | } |
@@ -134,7 +137,9 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc) | |||
134 | return 0; /* don't care */ | 137 | return 0; /* don't care */ |
135 | } | 138 | } |
136 | 139 | ||
137 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) { | 140 | if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) && |
141 | PageChecked(page)) { | ||
142 | ClearPageChecked(page); | ||
138 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); | 143 | error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); |
139 | if (error) | 144 | if (error) |
140 | goto out_ignore; | 145 | goto out_ignore; |
@@ -203,11 +208,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) | |||
203 | * so we need to supply one here. It doesn't happen often. | 208 | * so we need to supply one here. It doesn't happen often. |
204 | */ | 209 | */ |
205 | if (unlikely(page->index)) { | 210 | if (unlikely(page->index)) { |
206 | kaddr = kmap_atomic(page, KM_USER0); | 211 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); |
207 | memset(kaddr, 0, PAGE_CACHE_SIZE); | ||
208 | kunmap_atomic(kaddr, KM_USER0); | ||
209 | flush_dcache_page(page); | ||
210 | SetPageUptodate(page); | ||
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
@@ -450,6 +451,31 @@ out_uninit: | |||
450 | } | 451 | } |
451 | 452 | ||
452 | /** | 453 | /** |
454 | * adjust_fs_space - Adjusts the free space available due to gfs2_grow | ||
455 | * @inode: the rindex inode | ||
456 | */ | ||
457 | static void adjust_fs_space(struct inode *inode) | ||
458 | { | ||
459 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
460 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
461 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
462 | u64 fs_total, new_free; | ||
463 | |||
464 | /* Total up the file system space, according to the latest rindex. */ | ||
465 | fs_total = gfs2_ri_total(sdp); | ||
466 | |||
467 | spin_lock(&sdp->sd_statfs_spin); | ||
468 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | ||
469 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | ||
470 | else | ||
471 | new_free = 0; | ||
472 | spin_unlock(&sdp->sd_statfs_spin); | ||
473 | fs_warn(sdp, "File system extended by %llu blocks.\n", | ||
474 | (unsigned long long)new_free); | ||
475 | gfs2_statfs_change(sdp, new_free, new_free, 0); | ||
476 | } | ||
477 | |||
478 | /** | ||
453 | * gfs2_commit_write - Commit write to a file | 479 | * gfs2_commit_write - Commit write to a file |
454 | * @file: The file to write to | 480 | * @file: The file to write to |
455 | * @page: The page containing the data | 481 | * @page: The page containing the data |
@@ -511,6 +537,9 @@ static int gfs2_commit_write(struct file *file, struct page *page, | |||
511 | di->di_size = cpu_to_be64(inode->i_size); | 537 | di->di_size = cpu_to_be64(inode->i_size); |
512 | } | 538 | } |
513 | 539 | ||
540 | if (inode == sdp->sd_rindex) | ||
541 | adjust_fs_space(inode); | ||
542 | |||
514 | brelse(dibh); | 543 | brelse(dibh); |
515 | gfs2_trans_end(sdp); | 544 | gfs2_trans_end(sdp); |
516 | if (al->al_requested) { | 545 | if (al->al_requested) { |
@@ -543,6 +572,23 @@ fail_nounlock: | |||
543 | } | 572 | } |
544 | 573 | ||
545 | /** | 574 | /** |
575 | * gfs2_set_page_dirty - Page dirtying function | ||
576 | * @page: The page to dirty | ||
577 | * | ||
578 | * Returns: 1 if it dirtyed the page, or 0 otherwise | ||
579 | */ | ||
580 | |||
581 | static int gfs2_set_page_dirty(struct page *page) | ||
582 | { | ||
583 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | ||
584 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); | ||
585 | |||
586 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) | ||
587 | SetPageChecked(page); | ||
588 | return __set_page_dirty_buffers(page); | ||
589 | } | ||
590 | |||
591 | /** | ||
546 | * gfs2_bmap - Block map function | 592 | * gfs2_bmap - Block map function |
547 | * @mapping: Address space info | 593 | * @mapping: Address space info |
548 | * @lblock: The block to map | 594 | * @lblock: The block to map |
@@ -578,6 +624,8 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh) | |||
578 | if (bd) { | 624 | if (bd) { |
579 | bd->bd_bh = NULL; | 625 | bd->bd_bh = NULL; |
580 | bh->b_private = NULL; | 626 | bh->b_private = NULL; |
627 | if (!bd->bd_ail && list_empty(&bd->bd_le.le_list)) | ||
628 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
581 | } | 629 | } |
582 | gfs2_log_unlock(sdp); | 630 | gfs2_log_unlock(sdp); |
583 | 631 | ||
@@ -598,6 +646,8 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset) | |||
598 | unsigned int curr_off = 0; | 646 | unsigned int curr_off = 0; |
599 | 647 | ||
600 | BUG_ON(!PageLocked(page)); | 648 | BUG_ON(!PageLocked(page)); |
649 | if (offset == 0) | ||
650 | ClearPageChecked(page); | ||
601 | if (!page_has_buffers(page)) | 651 | if (!page_has_buffers(page)) |
602 | return; | 652 | return; |
603 | 653 | ||
@@ -728,8 +778,8 @@ static unsigned limit = 0; | |||
728 | return; | 778 | return; |
729 | 779 | ||
730 | fs_warn(sdp, "ip = %llu %llu\n", | 780 | fs_warn(sdp, "ip = %llu %llu\n", |
731 | (unsigned long long)ip->i_num.no_formal_ino, | 781 | (unsigned long long)ip->i_no_formal_ino, |
732 | (unsigned long long)ip->i_num.no_addr); | 782 | (unsigned long long)ip->i_no_addr); |
733 | 783 | ||
734 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) | 784 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) |
735 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", | 785 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", |
@@ -810,6 +860,7 @@ const struct address_space_operations gfs2_file_aops = { | |||
810 | .sync_page = block_sync_page, | 860 | .sync_page = block_sync_page, |
811 | .prepare_write = gfs2_prepare_write, | 861 | .prepare_write = gfs2_prepare_write, |
812 | .commit_write = gfs2_commit_write, | 862 | .commit_write = gfs2_commit_write, |
863 | .set_page_dirty = gfs2_set_page_dirty, | ||
813 | .bmap = gfs2_bmap, | 864 | .bmap = gfs2_bmap, |
814 | .invalidatepage = gfs2_invalidatepage, | 865 | .invalidatepage = gfs2_invalidatepage, |
815 | .releasepage = gfs2_releasepage, | 866 | .releasepage = gfs2_releasepage, |
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h index 35aaee4aa7e1..fa1b5b3d28b9 100644 --- a/fs/gfs2/ops_address.h +++ b/fs/gfs2/ops_address.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index a6fdc52f554a..793e334d098e 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "glock.h" | 21 | #include "glock.h" |
22 | #include "ops_dentry.h" | 22 | #include "ops_dentry.h" |
23 | #include "util.h" | 23 | #include "util.h" |
24 | #include "inode.h" | ||
24 | 25 | ||
25 | /** | 26 | /** |
26 | * gfs2_drevalidate - Check directory lookup consistency | 27 | * gfs2_drevalidate - Check directory lookup consistency |
@@ -40,14 +41,15 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
40 | struct gfs2_inode *dip = GFS2_I(parent->d_inode); | 41 | struct gfs2_inode *dip = GFS2_I(parent->d_inode); |
41 | struct inode *inode = dentry->d_inode; | 42 | struct inode *inode = dentry->d_inode; |
42 | struct gfs2_holder d_gh; | 43 | struct gfs2_holder d_gh; |
43 | struct gfs2_inode *ip; | 44 | struct gfs2_inode *ip = NULL; |
44 | struct gfs2_inum_host inum; | ||
45 | unsigned int type; | ||
46 | int error; | 45 | int error; |
47 | int had_lock=0; | 46 | int had_lock=0; |
48 | 47 | ||
49 | if (inode && is_bad_inode(inode)) | 48 | if (inode) { |
50 | goto invalid; | 49 | if (is_bad_inode(inode)) |
50 | goto invalid; | ||
51 | ip = GFS2_I(inode); | ||
52 | } | ||
51 | 53 | ||
52 | if (sdp->sd_args.ar_localcaching) | 54 | if (sdp->sd_args.ar_localcaching) |
53 | goto valid; | 55 | goto valid; |
@@ -59,7 +61,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
59 | goto fail; | 61 | goto fail; |
60 | } | 62 | } |
61 | 63 | ||
62 | error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type); | 64 | error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip); |
63 | switch (error) { | 65 | switch (error) { |
64 | case 0: | 66 | case 0: |
65 | if (!inode) | 67 | if (!inode) |
@@ -73,16 +75,6 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
73 | goto fail_gunlock; | 75 | goto fail_gunlock; |
74 | } | 76 | } |
75 | 77 | ||
76 | ip = GFS2_I(inode); | ||
77 | |||
78 | if (!gfs2_inum_equal(&ip->i_num, &inum)) | ||
79 | goto invalid_gunlock; | ||
80 | |||
81 | if (IF2DT(ip->i_inode.i_mode) != type) { | ||
82 | gfs2_consist_inode(dip); | ||
83 | goto fail_gunlock; | ||
84 | } | ||
85 | |||
86 | valid_gunlock: | 78 | valid_gunlock: |
87 | if (!had_lock) | 79 | if (!had_lock) |
88 | gfs2_glock_dq_uninit(&d_gh); | 80 | gfs2_glock_dq_uninit(&d_gh); |
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index aad918337a46..99ea5659bc2c 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
@@ -22,10 +22,14 @@ | |||
22 | #include "glops.h" | 22 | #include "glops.h" |
23 | #include "inode.h" | 23 | #include "inode.h" |
24 | #include "ops_dentry.h" | 24 | #include "ops_dentry.h" |
25 | #include "ops_export.h" | 25 | #include "ops_fstype.h" |
26 | #include "rgrp.h" | 26 | #include "rgrp.h" |
27 | #include "util.h" | 27 | #include "util.h" |
28 | 28 | ||
29 | #define GFS2_SMALL_FH_SIZE 4 | ||
30 | #define GFS2_LARGE_FH_SIZE 8 | ||
31 | #define GFS2_OLD_FH_SIZE 10 | ||
32 | |||
29 | static struct dentry *gfs2_decode_fh(struct super_block *sb, | 33 | static struct dentry *gfs2_decode_fh(struct super_block *sb, |
30 | __u32 *p, | 34 | __u32 *p, |
31 | int fh_len, | 35 | int fh_len, |
@@ -35,31 +39,28 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb, | |||
35 | void *context) | 39 | void *context) |
36 | { | 40 | { |
37 | __be32 *fh = (__force __be32 *)p; | 41 | __be32 *fh = (__force __be32 *)p; |
38 | struct gfs2_fh_obj fh_obj; | 42 | struct gfs2_inum_host inum, parent; |
39 | struct gfs2_inum_host *this, parent; | ||
40 | 43 | ||
41 | this = &fh_obj.this; | ||
42 | fh_obj.imode = DT_UNKNOWN; | ||
43 | memset(&parent, 0, sizeof(struct gfs2_inum)); | 44 | memset(&parent, 0, sizeof(struct gfs2_inum)); |
44 | 45 | ||
45 | switch (fh_len) { | 46 | switch (fh_len) { |
46 | case GFS2_LARGE_FH_SIZE: | 47 | case GFS2_LARGE_FH_SIZE: |
48 | case GFS2_OLD_FH_SIZE: | ||
47 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; | 49 | parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; |
48 | parent.no_formal_ino |= be32_to_cpu(fh[5]); | 50 | parent.no_formal_ino |= be32_to_cpu(fh[5]); |
49 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; | 51 | parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; |
50 | parent.no_addr |= be32_to_cpu(fh[7]); | 52 | parent.no_addr |= be32_to_cpu(fh[7]); |
51 | fh_obj.imode = be32_to_cpu(fh[8]); | ||
52 | case GFS2_SMALL_FH_SIZE: | 53 | case GFS2_SMALL_FH_SIZE: |
53 | this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; | 54 | inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; |
54 | this->no_formal_ino |= be32_to_cpu(fh[1]); | 55 | inum.no_formal_ino |= be32_to_cpu(fh[1]); |
55 | this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32; | 56 | inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; |
56 | this->no_addr |= be32_to_cpu(fh[3]); | 57 | inum.no_addr |= be32_to_cpu(fh[3]); |
57 | break; | 58 | break; |
58 | default: | 59 | default: |
59 | return NULL; | 60 | return NULL; |
60 | } | 61 | } |
61 | 62 | ||
62 | return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent, | 63 | return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent, |
63 | acceptable, context); | 64 | acceptable, context); |
64 | } | 65 | } |
65 | 66 | ||
@@ -75,10 +76,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | |||
75 | (connectable && *len < GFS2_LARGE_FH_SIZE)) | 76 | (connectable && *len < GFS2_LARGE_FH_SIZE)) |
76 | return 255; | 77 | return 255; |
77 | 78 | ||
78 | fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32); | 79 | fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32); |
79 | fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF); | 80 | fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); |
80 | fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32); | 81 | fh[2] = cpu_to_be32(ip->i_no_addr >> 32); |
81 | fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF); | 82 | fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); |
82 | *len = GFS2_SMALL_FH_SIZE; | 83 | *len = GFS2_SMALL_FH_SIZE; |
83 | 84 | ||
84 | if (!connectable || inode == sb->s_root->d_inode) | 85 | if (!connectable || inode == sb->s_root->d_inode) |
@@ -90,13 +91,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | |||
90 | igrab(inode); | 91 | igrab(inode); |
91 | spin_unlock(&dentry->d_lock); | 92 | spin_unlock(&dentry->d_lock); |
92 | 93 | ||
93 | fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32); | 94 | fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32); |
94 | fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF); | 95 | fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); |
95 | fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32); | 96 | fh[6] = cpu_to_be32(ip->i_no_addr >> 32); |
96 | fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF); | 97 | fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); |
97 | |||
98 | fh[8] = cpu_to_be32(inode->i_mode); | ||
99 | fh[9] = 0; /* pad to double word */ | ||
100 | *len = GFS2_LARGE_FH_SIZE; | 98 | *len = GFS2_LARGE_FH_SIZE; |
101 | 99 | ||
102 | iput(inode); | 100 | iput(inode); |
@@ -144,7 +142,8 @@ static int gfs2_get_name(struct dentry *parent, char *name, | |||
144 | ip = GFS2_I(inode); | 142 | ip = GFS2_I(inode); |
145 | 143 | ||
146 | *name = 0; | 144 | *name = 0; |
147 | gnfd.inum = ip->i_num; | 145 | gnfd.inum.no_addr = ip->i_no_addr; |
146 | gnfd.inum.no_formal_ino = ip->i_no_formal_ino; | ||
148 | gnfd.name = name; | 147 | gnfd.name = name; |
149 | 148 | ||
150 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); | 149 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); |
@@ -192,8 +191,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child) | |||
192 | static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | 191 | static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) |
193 | { | 192 | { |
194 | struct gfs2_sbd *sdp = sb->s_fs_info; | 193 | struct gfs2_sbd *sdp = sb->s_fs_info; |
195 | struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj; | 194 | struct gfs2_inum_host *inum = inum_obj; |
196 | struct gfs2_inum_host *inum = &fh_obj->this; | ||
197 | struct gfs2_holder i_gh, ri_gh, rgd_gh; | 195 | struct gfs2_holder i_gh, ri_gh, rgd_gh; |
198 | struct gfs2_rgrpd *rgd; | 196 | struct gfs2_rgrpd *rgd; |
199 | struct inode *inode; | 197 | struct inode *inode; |
@@ -202,9 +200,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | |||
202 | 200 | ||
203 | /* System files? */ | 201 | /* System files? */ |
204 | 202 | ||
205 | inode = gfs2_ilookup(sb, inum); | 203 | inode = gfs2_ilookup(sb, inum->no_addr); |
206 | if (inode) { | 204 | if (inode) { |
207 | if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) { | 205 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { |
208 | iput(inode); | 206 | iput(inode); |
209 | return ERR_PTR(-ESTALE); | 207 | return ERR_PTR(-ESTALE); |
210 | } | 208 | } |
@@ -236,7 +234,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | |||
236 | gfs2_glock_dq_uninit(&rgd_gh); | 234 | gfs2_glock_dq_uninit(&rgd_gh); |
237 | gfs2_glock_dq_uninit(&ri_gh); | 235 | gfs2_glock_dq_uninit(&ri_gh); |
238 | 236 | ||
239 | inode = gfs2_inode_lookup(sb, inum, fh_obj->imode); | 237 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, |
238 | inum->no_addr, | ||
239 | 0); | ||
240 | if (!inode) | 240 | if (!inode) |
241 | goto fail; | 241 | goto fail; |
242 | if (IS_ERR(inode)) { | 242 | if (IS_ERR(inode)) { |
@@ -250,6 +250,15 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | |||
250 | goto fail; | 250 | goto fail; |
251 | } | 251 | } |
252 | 252 | ||
253 | /* Pick up the works we bypass in gfs2_inode_lookup */ | ||
254 | if (inode->i_state & I_NEW) | ||
255 | gfs2_set_iop(inode); | ||
256 | |||
257 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { | ||
258 | iput(inode); | ||
259 | goto fail; | ||
260 | } | ||
261 | |||
253 | error = -EIO; | 262 | error = -EIO; |
254 | if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) { | 263 | if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) { |
255 | iput(inode); | 264 | iput(inode); |
diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h deleted file mode 100644 index f925a955b3b8..000000000000 --- a/fs/gfs2/ops_export.h +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * This copyrighted material is made available to anyone wishing to use, | ||
6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #ifndef __OPS_EXPORT_DOT_H__ | ||
11 | #define __OPS_EXPORT_DOT_H__ | ||
12 | |||
13 | #define GFS2_SMALL_FH_SIZE 4 | ||
14 | #define GFS2_LARGE_FH_SIZE 10 | ||
15 | |||
16 | extern struct export_operations gfs2_export_ops; | ||
17 | struct gfs2_fh_obj { | ||
18 | struct gfs2_inum_host this; | ||
19 | __u32 imode; | ||
20 | }; | ||
21 | |||
22 | #endif /* __OPS_EXPORT_DOT_H__ */ | ||
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 7dc3be108204..196d83266e34 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -502,7 +502,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) | |||
502 | struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); | 502 | struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); |
503 | struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); | 503 | struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); |
504 | struct lm_lockname name = | 504 | struct lm_lockname name = |
505 | { .ln_number = ip->i_num.no_addr, | 505 | { .ln_number = ip->i_no_addr, |
506 | .ln_type = LM_TYPE_PLOCK }; | 506 | .ln_type = LM_TYPE_PLOCK }; |
507 | 507 | ||
508 | if (!(fl->fl_flags & FL_POSIX)) | 508 | if (!(fl->fl_flags & FL_POSIX)) |
@@ -557,7 +557,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) | |||
557 | gfs2_glock_dq_uninit(fl_gh); | 557 | gfs2_glock_dq_uninit(fl_gh); |
558 | } else { | 558 | } else { |
559 | error = gfs2_glock_get(GFS2_SB(&ip->i_inode), | 559 | error = gfs2_glock_get(GFS2_SB(&ip->i_inode), |
560 | ip->i_num.no_addr, &gfs2_flock_glops, | 560 | ip->i_no_addr, &gfs2_flock_glops, |
561 | CREATE, &gl); | 561 | CREATE, &gl); |
562 | if (error) | 562 | if (error) |
563 | goto out; | 563 | goto out; |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 2c5f8e7def0d..cf5aa5050548 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "inode.h" | 27 | #include "inode.h" |
28 | #include "lm.h" | 28 | #include "lm.h" |
29 | #include "mount.h" | 29 | #include "mount.h" |
30 | #include "ops_export.h" | ||
31 | #include "ops_fstype.h" | 30 | #include "ops_fstype.h" |
32 | #include "ops_super.h" | 31 | #include "ops_super.h" |
33 | #include "recovery.h" | 32 | #include "recovery.h" |
@@ -105,6 +104,7 @@ static void init_vfs(struct super_block *sb, unsigned noatime) | |||
105 | sb->s_magic = GFS2_MAGIC; | 104 | sb->s_magic = GFS2_MAGIC; |
106 | sb->s_op = &gfs2_super_ops; | 105 | sb->s_op = &gfs2_super_ops; |
107 | sb->s_export_op = &gfs2_export_ops; | 106 | sb->s_export_op = &gfs2_export_ops; |
107 | sb->s_time_gran = 1; | ||
108 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 108 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
109 | 109 | ||
110 | if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME)) | 110 | if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME)) |
@@ -116,7 +116,6 @@ static void init_vfs(struct super_block *sb, unsigned noatime) | |||
116 | 116 | ||
117 | static int init_names(struct gfs2_sbd *sdp, int silent) | 117 | static int init_names(struct gfs2_sbd *sdp, int silent) |
118 | { | 118 | { |
119 | struct page *page; | ||
120 | char *proto, *table; | 119 | char *proto, *table; |
121 | int error = 0; | 120 | int error = 0; |
122 | 121 | ||
@@ -126,14 +125,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent) | |||
126 | /* Try to autodetect */ | 125 | /* Try to autodetect */ |
127 | 126 | ||
128 | if (!proto[0] || !table[0]) { | 127 | if (!proto[0] || !table[0]) { |
129 | struct gfs2_sb *sb; | 128 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); |
130 | page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); | 129 | if (error) |
131 | if (!page) | 130 | return error; |
132 | return -ENOBUFS; | ||
133 | sb = kmap(page); | ||
134 | gfs2_sb_in(&sdp->sd_sb, sb); | ||
135 | kunmap(page); | ||
136 | __free_page(page); | ||
137 | 131 | ||
138 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); | 132 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); |
139 | if (error) | 133 | if (error) |
@@ -151,6 +145,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent) | |||
151 | snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); | 145 | snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); |
152 | snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); | 146 | snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); |
153 | 147 | ||
148 | while ((table = strchr(sdp->sd_table_name, '/'))) | ||
149 | *table = '_'; | ||
150 | |||
154 | out: | 151 | out: |
155 | return error; | 152 | return error; |
156 | } | 153 | } |
@@ -236,17 +233,17 @@ fail: | |||
236 | return error; | 233 | return error; |
237 | } | 234 | } |
238 | 235 | ||
239 | static struct inode *gfs2_lookup_root(struct super_block *sb, | 236 | static inline struct inode *gfs2_lookup_root(struct super_block *sb, |
240 | struct gfs2_inum_host *inum) | 237 | u64 no_addr) |
241 | { | 238 | { |
242 | return gfs2_inode_lookup(sb, inum, DT_DIR); | 239 | return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); |
243 | } | 240 | } |
244 | 241 | ||
245 | static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) | 242 | static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) |
246 | { | 243 | { |
247 | struct super_block *sb = sdp->sd_vfs; | 244 | struct super_block *sb = sdp->sd_vfs; |
248 | struct gfs2_holder sb_gh; | 245 | struct gfs2_holder sb_gh; |
249 | struct gfs2_inum_host *inum; | 246 | u64 no_addr; |
250 | struct inode *inode; | 247 | struct inode *inode; |
251 | int error = 0; | 248 | int error = 0; |
252 | 249 | ||
@@ -289,10 +286,10 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) | |||
289 | sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); | 286 | sb_set_blocksize(sb, sdp->sd_sb.sb_bsize); |
290 | 287 | ||
291 | /* Get the root inode */ | 288 | /* Get the root inode */ |
292 | inum = &sdp->sd_sb.sb_root_dir; | 289 | no_addr = sdp->sd_sb.sb_root_dir.no_addr; |
293 | if (sb->s_type == &gfs2meta_fs_type) | 290 | if (sb->s_type == &gfs2meta_fs_type) |
294 | inum = &sdp->sd_sb.sb_master_dir; | 291 | no_addr = sdp->sd_sb.sb_master_dir.no_addr; |
295 | inode = gfs2_lookup_root(sb, inum); | 292 | inode = gfs2_lookup_root(sb, no_addr); |
296 | if (IS_ERR(inode)) { | 293 | if (IS_ERR(inode)) { |
297 | error = PTR_ERR(inode); | 294 | error = PTR_ERR(inode); |
298 | fs_err(sdp, "can't read in root inode: %d\n", error); | 295 | fs_err(sdp, "can't read in root inode: %d\n", error); |
@@ -449,7 +446,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) | |||
449 | if (undo) | 446 | if (undo) |
450 | goto fail_qinode; | 447 | goto fail_qinode; |
451 | 448 | ||
452 | inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir); | 449 | inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr); |
453 | if (IS_ERR(inode)) { | 450 | if (IS_ERR(inode)) { |
454 | error = PTR_ERR(inode); | 451 | error = PTR_ERR(inode); |
455 | fs_err(sdp, "can't read in master directory: %d\n", error); | 452 | fs_err(sdp, "can't read in master directory: %d\n", error); |
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h index 7cc2c296271b..407029b3b2b3 100644 --- a/fs/gfs2/ops_fstype.h +++ b/fs/gfs2/ops_fstype.h | |||
@@ -14,5 +14,6 @@ | |||
14 | 14 | ||
15 | extern struct file_system_type gfs2_fs_type; | 15 | extern struct file_system_type gfs2_fs_type; |
16 | extern struct file_system_type gfs2meta_fs_type; | 16 | extern struct file_system_type gfs2meta_fs_type; |
17 | extern struct export_operations gfs2_export_ops; | ||
17 | 18 | ||
18 | #endif /* __OPS_FSTYPE_DOT_H__ */ | 19 | #endif /* __OPS_FSTYPE_DOT_H__ */ |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index d85f6e05cb95..911c115b5c6c 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -157,7 +157,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
157 | if (error) | 157 | if (error) |
158 | goto out_gunlock; | 158 | goto out_gunlock; |
159 | 159 | ||
160 | error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL); | 160 | error = gfs2_dir_check(dir, &dentry->d_name, NULL); |
161 | switch (error) { | 161 | switch (error) { |
162 | case -ENOENT: | 162 | case -ENOENT: |
163 | break; | 163 | break; |
@@ -206,7 +206,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
206 | goto out_gunlock_q; | 206 | goto out_gunlock_q; |
207 | 207 | ||
208 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 208 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
209 | al->al_rgd->rd_ri.ri_length + | 209 | al->al_rgd->rd_length + |
210 | 2 * RES_DINODE + RES_STATFS + | 210 | 2 * RES_DINODE + RES_STATFS + |
211 | RES_QUOTA, 0); | 211 | RES_QUOTA, 0); |
212 | if (error) | 212 | if (error) |
@@ -217,8 +217,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
217 | goto out_ipres; | 217 | goto out_ipres; |
218 | } | 218 | } |
219 | 219 | ||
220 | error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num, | 220 | error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode)); |
221 | IF2DT(inode->i_mode)); | ||
222 | if (error) | 221 | if (error) |
223 | goto out_end_trans; | 222 | goto out_end_trans; |
224 | 223 | ||
@@ -275,7 +274,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
275 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 274 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
276 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 275 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
277 | 276 | ||
278 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | 277 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); |
279 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | 278 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); |
280 | 279 | ||
281 | 280 | ||
@@ -420,7 +419,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
420 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); | 419 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); |
421 | gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); | 420 | gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); |
422 | 421 | ||
423 | gfs2_inum_out(&dip->i_num, &dent->de_inum); | 422 | gfs2_inum_out(dip, dent); |
424 | dent->de_type = cpu_to_be16(DT_DIR); | 423 | dent->de_type = cpu_to_be16(DT_DIR); |
425 | 424 | ||
426 | gfs2_dinode_out(ip, di); | 425 | gfs2_dinode_out(ip, di); |
@@ -472,7 +471,7 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
472 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 471 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
473 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 472 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
474 | 473 | ||
475 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | 474 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); |
476 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | 475 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); |
477 | 476 | ||
478 | error = gfs2_glock_nq_m(3, ghs); | 477 | error = gfs2_glock_nq_m(3, ghs); |
@@ -614,7 +613,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
614 | * this is the case of the target file already existing | 613 | * this is the case of the target file already existing |
615 | * so we unlink before doing the rename | 614 | * so we unlink before doing the rename |
616 | */ | 615 | */ |
617 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); | 616 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr); |
618 | if (nrgd) | 617 | if (nrgd) |
619 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); | 618 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); |
620 | } | 619 | } |
@@ -653,7 +652,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
653 | if (error) | 652 | if (error) |
654 | goto out_gunlock; | 653 | goto out_gunlock; |
655 | 654 | ||
656 | error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL); | 655 | error = gfs2_dir_check(ndir, &ndentry->d_name, NULL); |
657 | switch (error) { | 656 | switch (error) { |
658 | case -ENOENT: | 657 | case -ENOENT: |
659 | error = 0; | 658 | error = 0; |
@@ -712,7 +711,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
712 | goto out_gunlock_q; | 711 | goto out_gunlock_q; |
713 | 712 | ||
714 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 713 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
715 | al->al_rgd->rd_ri.ri_length + | 714 | al->al_rgd->rd_length + |
716 | 4 * RES_DINODE + 4 * RES_LEAF + | 715 | 4 * RES_DINODE + 4 * RES_LEAF + |
717 | RES_STATFS + RES_QUOTA + 4, 0); | 716 | RES_STATFS + RES_QUOTA + 4, 0); |
718 | if (error) | 717 | if (error) |
@@ -750,7 +749,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
750 | if (error) | 749 | if (error) |
751 | goto out_end_trans; | 750 | goto out_end_trans; |
752 | 751 | ||
753 | error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR); | 752 | error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR); |
754 | if (error) | 753 | if (error) |
755 | goto out_end_trans; | 754 | goto out_end_trans; |
756 | } else { | 755 | } else { |
@@ -758,7 +757,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
758 | error = gfs2_meta_inode_buffer(ip, &dibh); | 757 | error = gfs2_meta_inode_buffer(ip, &dibh); |
759 | if (error) | 758 | if (error) |
760 | goto out_end_trans; | 759 | goto out_end_trans; |
761 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; | 760 | ip->i_inode.i_ctime = CURRENT_TIME; |
762 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 761 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
763 | gfs2_dinode_out(ip, dibh->b_data); | 762 | gfs2_dinode_out(ip, dibh->b_data); |
764 | brelse(dibh); | 763 | brelse(dibh); |
@@ -768,8 +767,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
768 | if (error) | 767 | if (error) |
769 | goto out_end_trans; | 768 | goto out_end_trans; |
770 | 769 | ||
771 | error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num, | 770 | error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode)); |
772 | IF2DT(ip->i_inode.i_mode)); | ||
773 | if (error) | 771 | if (error) |
774 | goto out_end_trans; | 772 | goto out_end_trans; |
775 | 773 | ||
@@ -905,8 +903,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr) | |||
905 | } | 903 | } |
906 | 904 | ||
907 | error = gfs2_truncatei(ip, attr->ia_size); | 905 | error = gfs2_truncatei(ip, attr->ia_size); |
908 | if (error) | 906 | if (error && (inode->i_size != ip->i_di.di_size)) |
909 | return error; | 907 | i_size_write(inode, ip->i_di.di_size); |
910 | 908 | ||
911 | return error; | 909 | return error; |
912 | } | 910 | } |
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 485ce3d49923..603d940f1159 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -326,8 +326,10 @@ static void gfs2_clear_inode(struct inode *inode) | |||
326 | gfs2_glock_schedule_for_reclaim(ip->i_gl); | 326 | gfs2_glock_schedule_for_reclaim(ip->i_gl); |
327 | gfs2_glock_put(ip->i_gl); | 327 | gfs2_glock_put(ip->i_gl); |
328 | ip->i_gl = NULL; | 328 | ip->i_gl = NULL; |
329 | if (ip->i_iopen_gh.gh_gl) | 329 | if (ip->i_iopen_gh.gh_gl) { |
330 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
330 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 331 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
332 | } | ||
331 | } | 333 | } |
332 | } | 334 | } |
333 | 335 | ||
@@ -422,13 +424,13 @@ static void gfs2_delete_inode(struct inode *inode) | |||
422 | if (!inode->i_private) | 424 | if (!inode->i_private) |
423 | goto out; | 425 | goto out; |
424 | 426 | ||
425 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh); | 427 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
426 | if (unlikely(error)) { | 428 | if (unlikely(error)) { |
427 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 429 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
428 | goto out; | 430 | goto out; |
429 | } | 431 | } |
430 | 432 | ||
431 | gfs2_glock_dq(&ip->i_iopen_gh); | 433 | gfs2_glock_dq_wait(&ip->i_iopen_gh); |
432 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 434 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
433 | error = gfs2_glock_nq(&ip->i_iopen_gh); | 435 | error = gfs2_glock_nq(&ip->i_iopen_gh); |
434 | if (error) | 436 | if (error) |
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index aa0dbd2aac1b..404b7cc9f8c4 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c | |||
@@ -66,7 +66,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) | |||
66 | if (error) | 66 | if (error) |
67 | goto out_gunlock_q; | 67 | goto out_gunlock_q; |
68 | 68 | ||
69 | error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length + | 69 | error = gfs2_trans_begin(sdp, al->al_rgd->rd_length + |
70 | ind_blocks + RES_DINODE + | 70 | ind_blocks + RES_DINODE + |
71 | RES_STATFS + RES_QUOTA, 0); | 71 | RES_STATFS + RES_QUOTA, 0); |
72 | if (error) | 72 | if (error) |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index c186857e48a8..6e546ee8f3d4 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -66,6 +66,18 @@ | |||
66 | #define QUOTA_USER 1 | 66 | #define QUOTA_USER 1 |
67 | #define QUOTA_GROUP 0 | 67 | #define QUOTA_GROUP 0 |
68 | 68 | ||
69 | struct gfs2_quota_host { | ||
70 | u64 qu_limit; | ||
71 | u64 qu_warn; | ||
72 | s64 qu_value; | ||
73 | }; | ||
74 | |||
75 | struct gfs2_quota_change_host { | ||
76 | u64 qc_change; | ||
77 | u32 qc_flags; /* GFS2_QCF_... */ | ||
78 | u32 qc_id; | ||
79 | }; | ||
80 | |||
69 | static u64 qd2offset(struct gfs2_quota_data *qd) | 81 | static u64 qd2offset(struct gfs2_quota_data *qd) |
70 | { | 82 | { |
71 | u64 offset; | 83 | u64 offset; |
@@ -561,6 +573,25 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) | |||
561 | mutex_unlock(&sdp->sd_quota_mutex); | 573 | mutex_unlock(&sdp->sd_quota_mutex); |
562 | } | 574 | } |
563 | 575 | ||
576 | static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) | ||
577 | { | ||
578 | const struct gfs2_quota *str = buf; | ||
579 | |||
580 | qu->qu_limit = be64_to_cpu(str->qu_limit); | ||
581 | qu->qu_warn = be64_to_cpu(str->qu_warn); | ||
582 | qu->qu_value = be64_to_cpu(str->qu_value); | ||
583 | } | ||
584 | |||
585 | static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) | ||
586 | { | ||
587 | struct gfs2_quota *str = buf; | ||
588 | |||
589 | str->qu_limit = cpu_to_be64(qu->qu_limit); | ||
590 | str->qu_warn = cpu_to_be64(qu->qu_warn); | ||
591 | str->qu_value = cpu_to_be64(qu->qu_value); | ||
592 | memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); | ||
593 | } | ||
594 | |||
564 | /** | 595 | /** |
565 | * gfs2_adjust_quota | 596 | * gfs2_adjust_quota |
566 | * | 597 | * |
@@ -573,12 +604,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
573 | struct inode *inode = &ip->i_inode; | 604 | struct inode *inode = &ip->i_inode; |
574 | struct address_space *mapping = inode->i_mapping; | 605 | struct address_space *mapping = inode->i_mapping; |
575 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | 606 | unsigned long index = loc >> PAGE_CACHE_SHIFT; |
576 | unsigned offset = loc & (PAGE_CACHE_SHIFT - 1); | 607 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); |
577 | unsigned blocksize, iblock, pos; | 608 | unsigned blocksize, iblock, pos; |
578 | struct buffer_head *bh; | 609 | struct buffer_head *bh; |
579 | struct page *page; | 610 | struct page *page; |
580 | void *kaddr; | 611 | void *kaddr; |
581 | __be64 *ptr; | 612 | char *ptr; |
613 | struct gfs2_quota_host qp; | ||
582 | s64 value; | 614 | s64 value; |
583 | int err = -EIO; | 615 | int err = -EIO; |
584 | 616 | ||
@@ -620,13 +652,17 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
620 | 652 | ||
621 | kaddr = kmap_atomic(page, KM_USER0); | 653 | kaddr = kmap_atomic(page, KM_USER0); |
622 | ptr = kaddr + offset; | 654 | ptr = kaddr + offset; |
623 | value = (s64)be64_to_cpu(*ptr) + change; | 655 | gfs2_quota_in(&qp, ptr); |
624 | *ptr = cpu_to_be64(value); | 656 | qp.qu_value += change; |
657 | value = qp.qu_value; | ||
658 | gfs2_quota_out(&qp, ptr); | ||
625 | flush_dcache_page(page); | 659 | flush_dcache_page(page); |
626 | kunmap_atomic(kaddr, KM_USER0); | 660 | kunmap_atomic(kaddr, KM_USER0); |
627 | err = 0; | 661 | err = 0; |
628 | qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); | 662 | qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); |
629 | qd->qd_qb.qb_value = cpu_to_be64(value); | 663 | qd->qd_qb.qb_value = cpu_to_be64(value); |
664 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC); | ||
665 | ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value); | ||
630 | unlock: | 666 | unlock: |
631 | unlock_page(page); | 667 | unlock_page(page); |
632 | page_cache_release(page); | 668 | page_cache_release(page); |
@@ -689,7 +725,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
689 | goto out_alloc; | 725 | goto out_alloc; |
690 | 726 | ||
691 | error = gfs2_trans_begin(sdp, | 727 | error = gfs2_trans_begin(sdp, |
692 | al->al_rgd->rd_ri.ri_length + | 728 | al->al_rgd->rd_length + |
693 | num_qd * data_blocks + | 729 | num_qd * data_blocks + |
694 | nalloc * ind_blocks + | 730 | nalloc * ind_blocks + |
695 | RES_DINODE + num_qd + | 731 | RES_DINODE + num_qd + |
@@ -709,7 +745,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
709 | offset = qd2offset(qd); | 745 | offset = qd2offset(qd); |
710 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, | 746 | error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, |
711 | (struct gfs2_quota_data *) | 747 | (struct gfs2_quota_data *) |
712 | qd->qd_gl->gl_lvb); | 748 | qd); |
713 | if (error) | 749 | if (error) |
714 | goto out_end_trans; | 750 | goto out_end_trans; |
715 | 751 | ||
@@ -1050,6 +1086,15 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) | |||
1050 | return error; | 1086 | return error; |
1051 | } | 1087 | } |
1052 | 1088 | ||
1089 | static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf) | ||
1090 | { | ||
1091 | const struct gfs2_quota_change *str = buf; | ||
1092 | |||
1093 | qc->qc_change = be64_to_cpu(str->qc_change); | ||
1094 | qc->qc_flags = be32_to_cpu(str->qc_flags); | ||
1095 | qc->qc_id = be32_to_cpu(str->qc_id); | ||
1096 | } | ||
1097 | |||
1053 | int gfs2_quota_init(struct gfs2_sbd *sdp) | 1098 | int gfs2_quota_init(struct gfs2_sbd *sdp) |
1054 | { | 1099 | { |
1055 | struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); | 1100 | struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 8bc182c7e2ef..5ada38c99a2c 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -116,6 +116,22 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp) | |||
116 | } | 116 | } |
117 | } | 117 | } |
118 | 118 | ||
119 | static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf) | ||
120 | { | ||
121 | const struct gfs2_log_header *str = buf; | ||
122 | |||
123 | if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) || | ||
124 | str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH)) | ||
125 | return 1; | ||
126 | |||
127 | lh->lh_sequence = be64_to_cpu(str->lh_sequence); | ||
128 | lh->lh_flags = be32_to_cpu(str->lh_flags); | ||
129 | lh->lh_tail = be32_to_cpu(str->lh_tail); | ||
130 | lh->lh_blkno = be32_to_cpu(str->lh_blkno); | ||
131 | lh->lh_hash = be32_to_cpu(str->lh_hash); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
119 | /** | 135 | /** |
120 | * get_log_header - read the log header for a given segment | 136 | * get_log_header - read the log header for a given segment |
121 | * @jd: the journal | 137 | * @jd: the journal |
@@ -147,12 +163,10 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, | |||
147 | sizeof(u32)); | 163 | sizeof(u32)); |
148 | hash = crc32_le(hash, (unsigned char const *)¬hing, sizeof(nothing)); | 164 | hash = crc32_le(hash, (unsigned char const *)¬hing, sizeof(nothing)); |
149 | hash ^= (u32)~0; | 165 | hash ^= (u32)~0; |
150 | gfs2_log_header_in(&lh, bh->b_data); | 166 | error = gfs2_log_header_in(&lh, bh->b_data); |
151 | brelse(bh); | 167 | brelse(bh); |
152 | 168 | ||
153 | if (lh.lh_header.mh_magic != GFS2_MAGIC || | 169 | if (error || lh.lh_blkno != blk || lh.lh_hash != hash) |
154 | lh.lh_header.mh_type != GFS2_METATYPE_LH || | ||
155 | lh.lh_blkno != blk || lh.lh_hash != hash) | ||
156 | return 1; | 170 | return 1; |
157 | 171 | ||
158 | *head = lh; | 172 | *head = lh; |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 1727f5012efe..e4e040625153 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -28,6 +28,7 @@ | |||
28 | #include "ops_file.h" | 28 | #include "ops_file.h" |
29 | #include "util.h" | 29 | #include "util.h" |
30 | #include "log.h" | 30 | #include "log.h" |
31 | #include "inode.h" | ||
31 | 32 | ||
32 | #define BFITNOENT ((u32)~0) | 33 | #define BFITNOENT ((u32)~0) |
33 | 34 | ||
@@ -50,6 +51,9 @@ static const char valid_change[16] = { | |||
50 | 1, 0, 0, 0 | 51 | 1, 0, 0, 0 |
51 | }; | 52 | }; |
52 | 53 | ||
54 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | ||
55 | unsigned char old_state, unsigned char new_state); | ||
56 | |||
53 | /** | 57 | /** |
54 | * gfs2_setbit - Set a bit in the bitmaps | 58 | * gfs2_setbit - Set a bit in the bitmaps |
55 | * @buffer: the buffer that holds the bitmaps | 59 | * @buffer: the buffer that holds the bitmaps |
@@ -204,7 +208,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
204 | { | 208 | { |
205 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 209 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
206 | struct gfs2_bitmap *bi = NULL; | 210 | struct gfs2_bitmap *bi = NULL; |
207 | u32 length = rgd->rd_ri.ri_length; | 211 | u32 length = rgd->rd_length; |
208 | u32 count[4], tmp; | 212 | u32 count[4], tmp; |
209 | int buf, x; | 213 | int buf, x; |
210 | 214 | ||
@@ -227,7 +231,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
227 | return; | 231 | return; |
228 | } | 232 | } |
229 | 233 | ||
230 | tmp = rgd->rd_ri.ri_data - | 234 | tmp = rgd->rd_data - |
231 | rgd->rd_rg.rg_free - | 235 | rgd->rd_rg.rg_free - |
232 | rgd->rd_rg.rg_dinodes; | 236 | rgd->rd_rg.rg_dinodes; |
233 | if (count[1] + count[2] != tmp) { | 237 | if (count[1] + count[2] != tmp) { |
@@ -253,10 +257,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
253 | 257 | ||
254 | } | 258 | } |
255 | 259 | ||
256 | static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block) | 260 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) |
257 | { | 261 | { |
258 | u64 first = ri->ri_data0; | 262 | u64 first = rgd->rd_data0; |
259 | u64 last = first + ri->ri_data; | 263 | u64 last = first + rgd->rd_data; |
260 | return first <= block && block < last; | 264 | return first <= block && block < last; |
261 | } | 265 | } |
262 | 266 | ||
@@ -275,7 +279,7 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk) | |||
275 | spin_lock(&sdp->sd_rindex_spin); | 279 | spin_lock(&sdp->sd_rindex_spin); |
276 | 280 | ||
277 | list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) { | 281 | list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) { |
278 | if (rgrp_contains_block(&rgd->rd_ri, blk)) { | 282 | if (rgrp_contains_block(rgd, blk)) { |
279 | list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | 283 | list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); |
280 | spin_unlock(&sdp->sd_rindex_spin); | 284 | spin_unlock(&sdp->sd_rindex_spin); |
281 | return rgd; | 285 | return rgd; |
@@ -354,6 +358,15 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) | |||
354 | mutex_unlock(&sdp->sd_rindex_mutex); | 358 | mutex_unlock(&sdp->sd_rindex_mutex); |
355 | } | 359 | } |
356 | 360 | ||
361 | static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd) | ||
362 | { | ||
363 | printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr); | ||
364 | printk(KERN_INFO " ri_length = %u\n", rgd->rd_length); | ||
365 | printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0); | ||
366 | printk(KERN_INFO " ri_data = %u\n", rgd->rd_data); | ||
367 | printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes); | ||
368 | } | ||
369 | |||
357 | /** | 370 | /** |
358 | * gfs2_compute_bitstructs - Compute the bitmap sizes | 371 | * gfs2_compute_bitstructs - Compute the bitmap sizes |
359 | * @rgd: The resource group descriptor | 372 | * @rgd: The resource group descriptor |
@@ -367,7 +380,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
367 | { | 380 | { |
368 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 381 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
369 | struct gfs2_bitmap *bi; | 382 | struct gfs2_bitmap *bi; |
370 | u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */ | 383 | u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */ |
371 | u32 bytes_left, bytes; | 384 | u32 bytes_left, bytes; |
372 | int x; | 385 | int x; |
373 | 386 | ||
@@ -378,7 +391,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
378 | if (!rgd->rd_bits) | 391 | if (!rgd->rd_bits) |
379 | return -ENOMEM; | 392 | return -ENOMEM; |
380 | 393 | ||
381 | bytes_left = rgd->rd_ri.ri_bitbytes; | 394 | bytes_left = rgd->rd_bitbytes; |
382 | 395 | ||
383 | for (x = 0; x < length; x++) { | 396 | for (x = 0; x < length; x++) { |
384 | bi = rgd->rd_bits + x; | 397 | bi = rgd->rd_bits + x; |
@@ -399,14 +412,14 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
399 | } else if (x + 1 == length) { | 412 | } else if (x + 1 == length) { |
400 | bytes = bytes_left; | 413 | bytes = bytes_left; |
401 | bi->bi_offset = sizeof(struct gfs2_meta_header); | 414 | bi->bi_offset = sizeof(struct gfs2_meta_header); |
402 | bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; | 415 | bi->bi_start = rgd->rd_bitbytes - bytes_left; |
403 | bi->bi_len = bytes; | 416 | bi->bi_len = bytes; |
404 | /* other blocks */ | 417 | /* other blocks */ |
405 | } else { | 418 | } else { |
406 | bytes = sdp->sd_sb.sb_bsize - | 419 | bytes = sdp->sd_sb.sb_bsize - |
407 | sizeof(struct gfs2_meta_header); | 420 | sizeof(struct gfs2_meta_header); |
408 | bi->bi_offset = sizeof(struct gfs2_meta_header); | 421 | bi->bi_offset = sizeof(struct gfs2_meta_header); |
409 | bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; | 422 | bi->bi_start = rgd->rd_bitbytes - bytes_left; |
410 | bi->bi_len = bytes; | 423 | bi->bi_len = bytes; |
411 | } | 424 | } |
412 | 425 | ||
@@ -418,9 +431,9 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
418 | return -EIO; | 431 | return -EIO; |
419 | } | 432 | } |
420 | bi = rgd->rd_bits + (length - 1); | 433 | bi = rgd->rd_bits + (length - 1); |
421 | if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) { | 434 | if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) { |
422 | if (gfs2_consist_rgrpd(rgd)) { | 435 | if (gfs2_consist_rgrpd(rgd)) { |
423 | gfs2_rindex_print(&rgd->rd_ri); | 436 | gfs2_rindex_print(rgd); |
424 | fs_err(sdp, "start=%u len=%u offset=%u\n", | 437 | fs_err(sdp, "start=%u len=%u offset=%u\n", |
425 | bi->bi_start, bi->bi_len, bi->bi_offset); | 438 | bi->bi_start, bi->bi_len, bi->bi_offset); |
426 | } | 439 | } |
@@ -431,9 +444,104 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
431 | } | 444 | } |
432 | 445 | ||
433 | /** | 446 | /** |
434 | * gfs2_ri_update - Pull in a new resource index from the disk | 447 | * gfs2_ri_total - Total up the file system space, according to the rindex. |
448 | * | ||
449 | */ | ||
450 | u64 gfs2_ri_total(struct gfs2_sbd *sdp) | ||
451 | { | ||
452 | u64 total_data = 0; | ||
453 | struct inode *inode = sdp->sd_rindex; | ||
454 | struct gfs2_inode *ip = GFS2_I(inode); | ||
455 | char buf[sizeof(struct gfs2_rindex)]; | ||
456 | struct file_ra_state ra_state; | ||
457 | int error, rgrps; | ||
458 | |||
459 | mutex_lock(&sdp->sd_rindex_mutex); | ||
460 | file_ra_state_init(&ra_state, inode->i_mapping); | ||
461 | for (rgrps = 0;; rgrps++) { | ||
462 | loff_t pos = rgrps * sizeof(struct gfs2_rindex); | ||
463 | |||
464 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size) | ||
465 | break; | ||
466 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | ||
467 | sizeof(struct gfs2_rindex)); | ||
468 | if (error != sizeof(struct gfs2_rindex)) | ||
469 | break; | ||
470 | total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data); | ||
471 | } | ||
472 | mutex_unlock(&sdp->sd_rindex_mutex); | ||
473 | return total_data; | ||
474 | } | ||
475 | |||
476 | static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf) | ||
477 | { | ||
478 | const struct gfs2_rindex *str = buf; | ||
479 | |||
480 | rgd->rd_addr = be64_to_cpu(str->ri_addr); | ||
481 | rgd->rd_length = be32_to_cpu(str->ri_length); | ||
482 | rgd->rd_data0 = be64_to_cpu(str->ri_data0); | ||
483 | rgd->rd_data = be32_to_cpu(str->ri_data); | ||
484 | rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * read_rindex_entry - Pull in a new resource index entry from the disk | ||
435 | * @gl: The glock covering the rindex inode | 489 | * @gl: The glock covering the rindex inode |
436 | * | 490 | * |
491 | * Returns: 0 on success, error code otherwise | ||
492 | */ | ||
493 | |||
494 | static int read_rindex_entry(struct gfs2_inode *ip, | ||
495 | struct file_ra_state *ra_state) | ||
496 | { | ||
497 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
498 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | ||
499 | char buf[sizeof(struct gfs2_rindex)]; | ||
500 | int error; | ||
501 | struct gfs2_rgrpd *rgd; | ||
502 | |||
503 | error = gfs2_internal_read(ip, ra_state, buf, &pos, | ||
504 | sizeof(struct gfs2_rindex)); | ||
505 | if (!error) | ||
506 | return 0; | ||
507 | if (error != sizeof(struct gfs2_rindex)) { | ||
508 | if (error > 0) | ||
509 | error = -EIO; | ||
510 | return error; | ||
511 | } | ||
512 | |||
513 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | ||
514 | error = -ENOMEM; | ||
515 | if (!rgd) | ||
516 | return error; | ||
517 | |||
518 | mutex_init(&rgd->rd_mutex); | ||
519 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
520 | rgd->rd_sbd = sdp; | ||
521 | |||
522 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
523 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
524 | |||
525 | gfs2_rindex_in(rgd, buf); | ||
526 | error = compute_bitstructs(rgd); | ||
527 | if (error) | ||
528 | return error; | ||
529 | |||
530 | error = gfs2_glock_get(sdp, rgd->rd_addr, | ||
531 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | ||
532 | if (error) | ||
533 | return error; | ||
534 | |||
535 | rgd->rd_gl->gl_object = rgd; | ||
536 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | ||
537 | rgd->rd_flags |= GFS2_RDF_CHECK; | ||
538 | return error; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * gfs2_ri_update - Pull in a new resource index from the disk | ||
543 | * @ip: pointer to the rindex inode | ||
544 | * | ||
437 | * Returns: 0 on successful update, error code otherwise | 545 | * Returns: 0 on successful update, error code otherwise |
438 | */ | 546 | */ |
439 | 547 | ||
@@ -441,13 +549,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
441 | { | 549 | { |
442 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 550 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
443 | struct inode *inode = &ip->i_inode; | 551 | struct inode *inode = &ip->i_inode; |
444 | struct gfs2_rgrpd *rgd; | ||
445 | char buf[sizeof(struct gfs2_rindex)]; | ||
446 | struct file_ra_state ra_state; | 552 | struct file_ra_state ra_state; |
447 | u64 junk = ip->i_di.di_size; | 553 | u64 rgrp_count = ip->i_di.di_size; |
448 | int error; | 554 | int error; |
449 | 555 | ||
450 | if (do_div(junk, sizeof(struct gfs2_rindex))) { | 556 | if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) { |
451 | gfs2_consist_inode(ip); | 557 | gfs2_consist_inode(ip); |
452 | return -EIO; | 558 | return -EIO; |
453 | } | 559 | } |
@@ -455,50 +561,50 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
455 | clear_rgrpdi(sdp); | 561 | clear_rgrpdi(sdp); |
456 | 562 | ||
457 | file_ra_state_init(&ra_state, inode->i_mapping); | 563 | file_ra_state_init(&ra_state, inode->i_mapping); |
458 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { | 564 | for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) { |
459 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | 565 | error = read_rindex_entry(ip, &ra_state); |
460 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | 566 | if (error) { |
461 | sizeof(struct gfs2_rindex)); | 567 | clear_rgrpdi(sdp); |
462 | if (!error) | 568 | return error; |
463 | break; | ||
464 | if (error != sizeof(struct gfs2_rindex)) { | ||
465 | if (error > 0) | ||
466 | error = -EIO; | ||
467 | goto fail; | ||
468 | } | 569 | } |
570 | } | ||
469 | 571 | ||
470 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | 572 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
471 | error = -ENOMEM; | 573 | return 0; |
472 | if (!rgd) | 574 | } |
473 | goto fail; | ||
474 | |||
475 | mutex_init(&rgd->rd_mutex); | ||
476 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
477 | rgd->rd_sbd = sdp; | ||
478 | |||
479 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
480 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
481 | |||
482 | gfs2_rindex_in(&rgd->rd_ri, buf); | ||
483 | error = compute_bitstructs(rgd); | ||
484 | if (error) | ||
485 | goto fail; | ||
486 | 575 | ||
487 | error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr, | 576 | /** |
488 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | 577 | * gfs2_ri_update_special - Pull in a new resource index from the disk |
489 | if (error) | 578 | * |
490 | goto fail; | 579 | * This is a special version that's safe to call from gfs2_inplace_reserve_i. |
580 | * In this case we know that we don't have any resource groups in memory yet. | ||
581 | * | ||
582 | * @ip: pointer to the rindex inode | ||
583 | * | ||
584 | * Returns: 0 on successful update, error code otherwise | ||
585 | */ | ||
586 | static int gfs2_ri_update_special(struct gfs2_inode *ip) | ||
587 | { | ||
588 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
589 | struct inode *inode = &ip->i_inode; | ||
590 | struct file_ra_state ra_state; | ||
591 | int error; | ||
491 | 592 | ||
492 | rgd->rd_gl->gl_object = rgd; | 593 | file_ra_state_init(&ra_state, inode->i_mapping); |
493 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | 594 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
595 | /* Ignore partials */ | ||
596 | if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > | ||
597 | ip->i_di.di_size) | ||
598 | break; | ||
599 | error = read_rindex_entry(ip, &ra_state); | ||
600 | if (error) { | ||
601 | clear_rgrpdi(sdp); | ||
602 | return error; | ||
603 | } | ||
494 | } | 604 | } |
495 | 605 | ||
496 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; | 606 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
497 | return 0; | 607 | return 0; |
498 | |||
499 | fail: | ||
500 | clear_rgrpdi(sdp); | ||
501 | return error; | ||
502 | } | 608 | } |
503 | 609 | ||
504 | /** | 610 | /** |
@@ -543,6 +649,28 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) | |||
543 | return error; | 649 | return error; |
544 | } | 650 | } |
545 | 651 | ||
652 | static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) | ||
653 | { | ||
654 | const struct gfs2_rgrp *str = buf; | ||
655 | |||
656 | rg->rg_flags = be32_to_cpu(str->rg_flags); | ||
657 | rg->rg_free = be32_to_cpu(str->rg_free); | ||
658 | rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); | ||
659 | rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); | ||
660 | } | ||
661 | |||
662 | static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) | ||
663 | { | ||
664 | struct gfs2_rgrp *str = buf; | ||
665 | |||
666 | str->rg_flags = cpu_to_be32(rg->rg_flags); | ||
667 | str->rg_free = cpu_to_be32(rg->rg_free); | ||
668 | str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); | ||
669 | str->__pad = cpu_to_be32(0); | ||
670 | str->rg_igeneration = cpu_to_be64(rg->rg_igeneration); | ||
671 | memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); | ||
672 | } | ||
673 | |||
546 | /** | 674 | /** |
547 | * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps | 675 | * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps |
548 | * @rgd: the struct gfs2_rgrpd describing the RG to read in | 676 | * @rgd: the struct gfs2_rgrpd describing the RG to read in |
@@ -557,7 +685,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
557 | { | 685 | { |
558 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 686 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
559 | struct gfs2_glock *gl = rgd->rd_gl; | 687 | struct gfs2_glock *gl = rgd->rd_gl; |
560 | unsigned int length = rgd->rd_ri.ri_length; | 688 | unsigned int length = rgd->rd_length; |
561 | struct gfs2_bitmap *bi; | 689 | struct gfs2_bitmap *bi; |
562 | unsigned int x, y; | 690 | unsigned int x, y; |
563 | int error; | 691 | int error; |
@@ -575,7 +703,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
575 | 703 | ||
576 | for (x = 0; x < length; x++) { | 704 | for (x = 0; x < length; x++) { |
577 | bi = rgd->rd_bits + x; | 705 | bi = rgd->rd_bits + x; |
578 | error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh); | 706 | error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh); |
579 | if (error) | 707 | if (error) |
580 | goto fail; | 708 | goto fail; |
581 | } | 709 | } |
@@ -637,7 +765,7 @@ void gfs2_rgrp_bh_hold(struct gfs2_rgrpd *rgd) | |||
637 | void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) | 765 | void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) |
638 | { | 766 | { |
639 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 767 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
640 | int x, length = rgd->rd_ri.ri_length; | 768 | int x, length = rgd->rd_length; |
641 | 769 | ||
642 | spin_lock(&sdp->sd_rindex_spin); | 770 | spin_lock(&sdp->sd_rindex_spin); |
643 | gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count); | 771 | gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count); |
@@ -660,7 +788,7 @@ void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) | |||
660 | void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | 788 | void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) |
661 | { | 789 | { |
662 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 790 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
663 | unsigned int length = rgd->rd_ri.ri_length; | 791 | unsigned int length = rgd->rd_length; |
664 | unsigned int x; | 792 | unsigned int x; |
665 | 793 | ||
666 | for (x = 0; x < length; x++) { | 794 | for (x = 0; x < length; x++) { |
@@ -722,6 +850,38 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
722 | } | 850 | } |
723 | 851 | ||
724 | /** | 852 | /** |
853 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes | ||
854 | * @rgd: The rgrp | ||
855 | * | ||
856 | * Returns: The inode, if one has been found | ||
857 | */ | ||
858 | |||
859 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | ||
860 | { | ||
861 | struct inode *inode; | ||
862 | u32 goal = 0; | ||
863 | u64 no_addr; | ||
864 | |||
865 | for(;;) { | ||
866 | goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, | ||
867 | GFS2_BLKST_UNLINKED); | ||
868 | if (goal == 0) | ||
869 | return 0; | ||
870 | no_addr = goal + rgd->rd_data0; | ||
871 | if (no_addr <= *last_unlinked) | ||
872 | continue; | ||
873 | *last_unlinked = no_addr; | ||
874 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | ||
875 | no_addr, -1); | ||
876 | if (!IS_ERR(inode)) | ||
877 | return inode; | ||
878 | } | ||
879 | |||
880 | rgd->rd_flags &= ~GFS2_RDF_CHECK; | ||
881 | return NULL; | ||
882 | } | ||
883 | |||
884 | /** | ||
725 | * recent_rgrp_first - get first RG from "recent" list | 885 | * recent_rgrp_first - get first RG from "recent" list |
726 | * @sdp: The GFS2 superblock | 886 | * @sdp: The GFS2 superblock |
727 | * @rglast: address of the rgrp used last | 887 | * @rglast: address of the rgrp used last |
@@ -743,7 +903,7 @@ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp, | |||
743 | goto first; | 903 | goto first; |
744 | 904 | ||
745 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { | 905 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { |
746 | if (rgd->rd_ri.ri_addr == rglast) | 906 | if (rgd->rd_addr == rglast) |
747 | goto out; | 907 | goto out; |
748 | } | 908 | } |
749 | 909 | ||
@@ -882,8 +1042,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) | |||
882 | * Returns: errno | 1042 | * Returns: errno |
883 | */ | 1043 | */ |
884 | 1044 | ||
885 | static int get_local_rgrp(struct gfs2_inode *ip) | 1045 | static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) |
886 | { | 1046 | { |
1047 | struct inode *inode = NULL; | ||
887 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1048 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
888 | struct gfs2_rgrpd *rgd, *begin = NULL; | 1049 | struct gfs2_rgrpd *rgd, *begin = NULL; |
889 | struct gfs2_alloc *al = &ip->i_alloc; | 1050 | struct gfs2_alloc *al = &ip->i_alloc; |
@@ -903,7 +1064,11 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
903 | case 0: | 1064 | case 0: |
904 | if (try_rgrp_fit(rgd, al)) | 1065 | if (try_rgrp_fit(rgd, al)) |
905 | goto out; | 1066 | goto out; |
1067 | if (rgd->rd_flags & GFS2_RDF_CHECK) | ||
1068 | inode = try_rgrp_unlink(rgd, last_unlinked); | ||
906 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1069 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1070 | if (inode) | ||
1071 | return inode; | ||
907 | rgd = recent_rgrp_next(rgd, 1); | 1072 | rgd = recent_rgrp_next(rgd, 1); |
908 | break; | 1073 | break; |
909 | 1074 | ||
@@ -912,7 +1077,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
912 | break; | 1077 | break; |
913 | 1078 | ||
914 | default: | 1079 | default: |
915 | return error; | 1080 | return ERR_PTR(error); |
916 | } | 1081 | } |
917 | } | 1082 | } |
918 | 1083 | ||
@@ -927,7 +1092,11 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
927 | case 0: | 1092 | case 0: |
928 | if (try_rgrp_fit(rgd, al)) | 1093 | if (try_rgrp_fit(rgd, al)) |
929 | goto out; | 1094 | goto out; |
1095 | if (rgd->rd_flags & GFS2_RDF_CHECK) | ||
1096 | inode = try_rgrp_unlink(rgd, last_unlinked); | ||
930 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1097 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1098 | if (inode) | ||
1099 | return inode; | ||
931 | break; | 1100 | break; |
932 | 1101 | ||
933 | case GLR_TRYFAILED: | 1102 | case GLR_TRYFAILED: |
@@ -935,7 +1104,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
935 | break; | 1104 | break; |
936 | 1105 | ||
937 | default: | 1106 | default: |
938 | return error; | 1107 | return ERR_PTR(error); |
939 | } | 1108 | } |
940 | 1109 | ||
941 | rgd = gfs2_rgrpd_get_next(rgd); | 1110 | rgd = gfs2_rgrpd_get_next(rgd); |
@@ -944,7 +1113,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
944 | 1113 | ||
945 | if (rgd == begin) { | 1114 | if (rgd == begin) { |
946 | if (++loops >= 3) | 1115 | if (++loops >= 3) |
947 | return -ENOSPC; | 1116 | return ERR_PTR(-ENOSPC); |
948 | if (!skipped) | 1117 | if (!skipped) |
949 | loops++; | 1118 | loops++; |
950 | flags = 0; | 1119 | flags = 0; |
@@ -954,7 +1123,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
954 | } | 1123 | } |
955 | 1124 | ||
956 | out: | 1125 | out: |
957 | ip->i_last_rg_alloc = rgd->rd_ri.ri_addr; | 1126 | ip->i_last_rg_alloc = rgd->rd_addr; |
958 | 1127 | ||
959 | if (begin) { | 1128 | if (begin) { |
960 | recent_rgrp_add(rgd); | 1129 | recent_rgrp_add(rgd); |
@@ -964,7 +1133,7 @@ out: | |||
964 | forward_rgrp_set(sdp, rgd); | 1133 | forward_rgrp_set(sdp, rgd); |
965 | } | 1134 | } |
966 | 1135 | ||
967 | return 0; | 1136 | return NULL; |
968 | } | 1137 | } |
969 | 1138 | ||
970 | /** | 1139 | /** |
@@ -978,19 +1147,33 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
978 | { | 1147 | { |
979 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1148 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
980 | struct gfs2_alloc *al = &ip->i_alloc; | 1149 | struct gfs2_alloc *al = &ip->i_alloc; |
981 | int error; | 1150 | struct inode *inode; |
1151 | int error = 0; | ||
1152 | u64 last_unlinked = 0; | ||
982 | 1153 | ||
983 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1154 | if (gfs2_assert_warn(sdp, al->al_requested)) |
984 | return -EINVAL; | 1155 | return -EINVAL; |
985 | 1156 | ||
986 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1157 | try_again: |
1158 | /* We need to hold the rindex unless the inode we're using is | ||
1159 | the rindex itself, in which case it's already held. */ | ||
1160 | if (ip != GFS2_I(sdp->sd_rindex)) | ||
1161 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1162 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | ||
1163 | error = gfs2_ri_update_special(ip); | ||
1164 | |||
987 | if (error) | 1165 | if (error) |
988 | return error; | 1166 | return error; |
989 | 1167 | ||
990 | error = get_local_rgrp(ip); | 1168 | inode = get_local_rgrp(ip, &last_unlinked); |
991 | if (error) { | 1169 | if (inode) { |
992 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1170 | if (ip != GFS2_I(sdp->sd_rindex)) |
993 | return error; | 1171 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1172 | if (IS_ERR(inode)) | ||
1173 | return PTR_ERR(inode); | ||
1174 | iput(inode); | ||
1175 | gfs2_log_flush(sdp, NULL); | ||
1176 | goto try_again; | ||
994 | } | 1177 | } |
995 | 1178 | ||
996 | al->al_file = file; | 1179 | al->al_file = file; |
@@ -1019,7 +1202,8 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1019 | 1202 | ||
1020 | al->al_rgd = NULL; | 1203 | al->al_rgd = NULL; |
1021 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1204 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1022 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1205 | if (ip != GFS2_I(sdp->sd_rindex)) |
1206 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1023 | } | 1207 | } |
1024 | 1208 | ||
1025 | /** | 1209 | /** |
@@ -1037,8 +1221,8 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1037 | unsigned int buf; | 1221 | unsigned int buf; |
1038 | unsigned char type; | 1222 | unsigned char type; |
1039 | 1223 | ||
1040 | length = rgd->rd_ri.ri_length; | 1224 | length = rgd->rd_length; |
1041 | rgrp_block = block - rgd->rd_ri.ri_data0; | 1225 | rgrp_block = block - rgd->rd_data0; |
1042 | 1226 | ||
1043 | for (buf = 0; buf < length; buf++) { | 1227 | for (buf = 0; buf < length; buf++) { |
1044 | bi = rgd->rd_bits + buf; | 1228 | bi = rgd->rd_bits + buf; |
@@ -1077,10 +1261,10 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1077 | */ | 1261 | */ |
1078 | 1262 | ||
1079 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 1263 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
1080 | unsigned char old_state, unsigned char new_state) | 1264 | unsigned char old_state, unsigned char new_state) |
1081 | { | 1265 | { |
1082 | struct gfs2_bitmap *bi = NULL; | 1266 | struct gfs2_bitmap *bi = NULL; |
1083 | u32 length = rgd->rd_ri.ri_length; | 1267 | u32 length = rgd->rd_length; |
1084 | u32 blk = 0; | 1268 | u32 blk = 0; |
1085 | unsigned int buf, x; | 1269 | unsigned int buf, x; |
1086 | 1270 | ||
@@ -1118,17 +1302,18 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1118 | goal = 0; | 1302 | goal = 0; |
1119 | } | 1303 | } |
1120 | 1304 | ||
1121 | if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length)) | 1305 | if (old_state != new_state) { |
1122 | blk = 0; | 1306 | gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT); |
1123 | 1307 | ||
1124 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1308 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1125 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, | 1309 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, |
1126 | bi->bi_len, blk, new_state); | ||
1127 | if (bi->bi_clone) | ||
1128 | gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, | ||
1129 | bi->bi_len, blk, new_state); | 1310 | bi->bi_len, blk, new_state); |
1311 | if (bi->bi_clone) | ||
1312 | gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, | ||
1313 | bi->bi_len, blk, new_state); | ||
1314 | } | ||
1130 | 1315 | ||
1131 | return bi->bi_start * GFS2_NBBY + blk; | 1316 | return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk; |
1132 | } | 1317 | } |
1133 | 1318 | ||
1134 | /** | 1319 | /** |
@@ -1156,9 +1341,9 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
1156 | return NULL; | 1341 | return NULL; |
1157 | } | 1342 | } |
1158 | 1343 | ||
1159 | length = rgd->rd_ri.ri_length; | 1344 | length = rgd->rd_length; |
1160 | 1345 | ||
1161 | rgrp_blk = bstart - rgd->rd_ri.ri_data0; | 1346 | rgrp_blk = bstart - rgd->rd_data0; |
1162 | 1347 | ||
1163 | while (blen--) { | 1348 | while (blen--) { |
1164 | for (buf = 0; buf < length; buf++) { | 1349 | for (buf = 0; buf < length; buf++) { |
@@ -1202,15 +1387,15 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) | |||
1202 | u32 goal, blk; | 1387 | u32 goal, blk; |
1203 | u64 block; | 1388 | u64 block; |
1204 | 1389 | ||
1205 | if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data)) | 1390 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_data)) |
1206 | goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0; | 1391 | goal = ip->i_di.di_goal_data - rgd->rd_data0; |
1207 | else | 1392 | else |
1208 | goal = rgd->rd_last_alloc_data; | 1393 | goal = rgd->rd_last_alloc_data; |
1209 | 1394 | ||
1210 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | 1395 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); |
1211 | rgd->rd_last_alloc_data = blk; | 1396 | rgd->rd_last_alloc_data = blk; |
1212 | 1397 | ||
1213 | block = rgd->rd_ri.ri_data0 + blk; | 1398 | block = rgd->rd_data0 + blk; |
1214 | ip->i_di.di_goal_data = block; | 1399 | ip->i_di.di_goal_data = block; |
1215 | 1400 | ||
1216 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1401 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
@@ -1246,15 +1431,15 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip) | |||
1246 | u32 goal, blk; | 1431 | u32 goal, blk; |
1247 | u64 block; | 1432 | u64 block; |
1248 | 1433 | ||
1249 | if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta)) | 1434 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta)) |
1250 | goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0; | 1435 | goal = ip->i_di.di_goal_meta - rgd->rd_data0; |
1251 | else | 1436 | else |
1252 | goal = rgd->rd_last_alloc_meta; | 1437 | goal = rgd->rd_last_alloc_meta; |
1253 | 1438 | ||
1254 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | 1439 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); |
1255 | rgd->rd_last_alloc_meta = blk; | 1440 | rgd->rd_last_alloc_meta = blk; |
1256 | 1441 | ||
1257 | block = rgd->rd_ri.ri_data0 + blk; | 1442 | block = rgd->rd_data0 + blk; |
1258 | ip->i_di.di_goal_meta = block; | 1443 | ip->i_di.di_goal_meta = block; |
1259 | 1444 | ||
1260 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1445 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
@@ -1296,7 +1481,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
1296 | 1481 | ||
1297 | rgd->rd_last_alloc_meta = blk; | 1482 | rgd->rd_last_alloc_meta = blk; |
1298 | 1483 | ||
1299 | block = rgd->rd_ri.ri_data0 + blk; | 1484 | block = rgd->rd_data0 + blk; |
1300 | 1485 | ||
1301 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1486 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
1302 | rgd->rd_rg.rg_free--; | 1487 | rgd->rd_rg.rg_free--; |
@@ -1379,7 +1564,7 @@ void gfs2_unlink_di(struct inode *inode) | |||
1379 | struct gfs2_inode *ip = GFS2_I(inode); | 1564 | struct gfs2_inode *ip = GFS2_I(inode); |
1380 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 1565 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
1381 | struct gfs2_rgrpd *rgd; | 1566 | struct gfs2_rgrpd *rgd; |
1382 | u64 blkno = ip->i_num.no_addr; | 1567 | u64 blkno = ip->i_no_addr; |
1383 | 1568 | ||
1384 | rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); | 1569 | rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); |
1385 | if (!rgd) | 1570 | if (!rgd) |
@@ -1414,9 +1599,9 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) | |||
1414 | 1599 | ||
1415 | void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) | 1600 | void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) |
1416 | { | 1601 | { |
1417 | gfs2_free_uninit_di(rgd, ip->i_num.no_addr); | 1602 | gfs2_free_uninit_di(rgd, ip->i_no_addr); |
1418 | gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); | 1603 | gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); |
1419 | gfs2_meta_wipe(ip, ip->i_num.no_addr, 1); | 1604 | gfs2_meta_wipe(ip, ip->i_no_addr, 1); |
1420 | } | 1605 | } |
1421 | 1606 | ||
1422 | /** | 1607 | /** |
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index b01e0cfc99b5..b4c6adfc6f2e 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
@@ -65,5 +65,6 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist, | |||
65 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, | 65 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, |
66 | int flags); | 66 | int flags); |
67 | void gfs2_rlist_free(struct gfs2_rgrp_list *rlist); | 67 | void gfs2_rlist_free(struct gfs2_rgrp_list *rlist); |
68 | u64 gfs2_ri_total(struct gfs2_sbd *sdp); | ||
68 | 69 | ||
69 | #endif /* __RGRP_DOT_H__ */ | 70 | #endif /* __RGRP_DOT_H__ */ |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 4fdda974dc83..f916b9740c75 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -95,8 +95,8 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) | |||
95 | { | 95 | { |
96 | unsigned int x; | 96 | unsigned int x; |
97 | 97 | ||
98 | if (sb->sb_header.mh_magic != GFS2_MAGIC || | 98 | if (sb->sb_magic != GFS2_MAGIC || |
99 | sb->sb_header.mh_type != GFS2_METATYPE_SB) { | 99 | sb->sb_type != GFS2_METATYPE_SB) { |
100 | if (!silent) | 100 | if (!silent) |
101 | printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); | 101 | printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); |
102 | return -EINVAL; | 102 | return -EINVAL; |
@@ -174,10 +174,31 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) | ||
178 | { | ||
179 | const struct gfs2_sb *str = buf; | ||
180 | |||
181 | sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); | ||
182 | sb->sb_type = be32_to_cpu(str->sb_header.mh_type); | ||
183 | sb->sb_format = be32_to_cpu(str->sb_header.mh_format); | ||
184 | sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); | ||
185 | sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); | ||
186 | sb->sb_bsize = be32_to_cpu(str->sb_bsize); | ||
187 | sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); | ||
188 | sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr); | ||
189 | sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino); | ||
190 | sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr); | ||
191 | sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino); | ||
192 | |||
193 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); | ||
194 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); | ||
195 | } | ||
196 | |||
177 | /** | 197 | /** |
178 | * gfs2_read_super - Read the gfs2 super block from disk | 198 | * gfs2_read_super - Read the gfs2 super block from disk |
179 | * @sb: The VFS super block | 199 | * @sdp: The GFS2 super block |
180 | * @sector: The location of the super block | 200 | * @sector: The location of the super block |
201 | * @error: The error code to return | ||
181 | * | 202 | * |
182 | * This uses the bio functions to read the super block from disk | 203 | * This uses the bio functions to read the super block from disk |
183 | * because we want to be 100% sure that we never read cached data. | 204 | * because we want to be 100% sure that we never read cached data. |
@@ -189,17 +210,19 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) | |||
189 | * the master directory (contains pointers to journals etc) and the | 210 | * the master directory (contains pointers to journals etc) and the |
190 | * root directory. | 211 | * root directory. |
191 | * | 212 | * |
192 | * Returns: A page containing the sb or NULL | 213 | * Returns: 0 on success or error |
193 | */ | 214 | */ |
194 | 215 | ||
195 | struct page *gfs2_read_super(struct super_block *sb, sector_t sector) | 216 | int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) |
196 | { | 217 | { |
218 | struct super_block *sb = sdp->sd_vfs; | ||
219 | struct gfs2_sb *p; | ||
197 | struct page *page; | 220 | struct page *page; |
198 | struct bio *bio; | 221 | struct bio *bio; |
199 | 222 | ||
200 | page = alloc_page(GFP_KERNEL); | 223 | page = alloc_page(GFP_KERNEL); |
201 | if (unlikely(!page)) | 224 | if (unlikely(!page)) |
202 | return NULL; | 225 | return -ENOBUFS; |
203 | 226 | ||
204 | ClearPageUptodate(page); | 227 | ClearPageUptodate(page); |
205 | ClearPageDirty(page); | 228 | ClearPageDirty(page); |
@@ -208,7 +231,7 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector) | |||
208 | bio = bio_alloc(GFP_KERNEL, 1); | 231 | bio = bio_alloc(GFP_KERNEL, 1); |
209 | if (unlikely(!bio)) { | 232 | if (unlikely(!bio)) { |
210 | __free_page(page); | 233 | __free_page(page); |
211 | return NULL; | 234 | return -ENOBUFS; |
212 | } | 235 | } |
213 | 236 | ||
214 | bio->bi_sector = sector * (sb->s_blocksize >> 9); | 237 | bio->bi_sector = sector * (sb->s_blocksize >> 9); |
@@ -222,9 +245,13 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector) | |||
222 | bio_put(bio); | 245 | bio_put(bio); |
223 | if (!PageUptodate(page)) { | 246 | if (!PageUptodate(page)) { |
224 | __free_page(page); | 247 | __free_page(page); |
225 | return NULL; | 248 | return -EIO; |
226 | } | 249 | } |
227 | return page; | 250 | p = kmap(page); |
251 | gfs2_sb_in(&sdp->sd_sb, p); | ||
252 | kunmap(page); | ||
253 | __free_page(page); | ||
254 | return 0; | ||
228 | } | 255 | } |
229 | 256 | ||
230 | /** | 257 | /** |
@@ -241,19 +268,13 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) | |||
241 | u32 tmp_blocks; | 268 | u32 tmp_blocks; |
242 | unsigned int x; | 269 | unsigned int x; |
243 | int error; | 270 | int error; |
244 | struct page *page; | ||
245 | char *sb; | ||
246 | 271 | ||
247 | page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); | 272 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); |
248 | if (!page) { | 273 | if (error) { |
249 | if (!silent) | 274 | if (!silent) |
250 | fs_err(sdp, "can't read superblock\n"); | 275 | fs_err(sdp, "can't read superblock\n"); |
251 | return -EIO; | 276 | return error; |
252 | } | 277 | } |
253 | sb = kmap(page); | ||
254 | gfs2_sb_in(&sdp->sd_sb, sb); | ||
255 | kunmap(page); | ||
256 | __free_page(page); | ||
257 | 278 | ||
258 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); | 279 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); |
259 | if (error) | 280 | if (error) |
@@ -360,7 +381,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) | |||
360 | name.len = sprintf(buf, "journal%u", sdp->sd_journals); | 381 | name.len = sprintf(buf, "journal%u", sdp->sd_journals); |
361 | name.hash = gfs2_disk_hash(name.name, name.len); | 382 | name.hash = gfs2_disk_hash(name.name, name.len); |
362 | 383 | ||
363 | error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL); | 384 | error = gfs2_dir_check(sdp->sd_jindex, &name, NULL); |
364 | if (error == -ENOENT) { | 385 | if (error == -ENOENT) { |
365 | error = 0; | 386 | error = 0; |
366 | break; | 387 | break; |
@@ -593,6 +614,24 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
593 | return error; | 614 | return error; |
594 | } | 615 | } |
595 | 616 | ||
617 | static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | ||
618 | { | ||
619 | const struct gfs2_statfs_change *str = buf; | ||
620 | |||
621 | sc->sc_total = be64_to_cpu(str->sc_total); | ||
622 | sc->sc_free = be64_to_cpu(str->sc_free); | ||
623 | sc->sc_dinodes = be64_to_cpu(str->sc_dinodes); | ||
624 | } | ||
625 | |||
626 | static void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf) | ||
627 | { | ||
628 | struct gfs2_statfs_change *str = buf; | ||
629 | |||
630 | str->sc_total = cpu_to_be64(sc->sc_total); | ||
631 | str->sc_free = cpu_to_be64(sc->sc_free); | ||
632 | str->sc_dinodes = cpu_to_be64(sc->sc_dinodes); | ||
633 | } | ||
634 | |||
596 | int gfs2_statfs_init(struct gfs2_sbd *sdp) | 635 | int gfs2_statfs_init(struct gfs2_sbd *sdp) |
597 | { | 636 | { |
598 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 637 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
@@ -772,7 +811,7 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd, | |||
772 | struct gfs2_statfs_change_host *sc) | 811 | struct gfs2_statfs_change_host *sc) |
773 | { | 812 | { |
774 | gfs2_rgrp_verify(rgd); | 813 | gfs2_rgrp_verify(rgd); |
775 | sc->sc_total += rgd->rd_ri.ri_data; | 814 | sc->sc_total += rgd->rd_data; |
776 | sc->sc_free += rgd->rd_rg.rg_free; | 815 | sc->sc_free += rgd->rd_rg.rg_free; |
777 | sc->sc_dinodes += rgd->rd_rg.rg_dinodes; | 816 | sc->sc_dinodes += rgd->rd_rg.rg_dinodes; |
778 | return 0; | 817 | return 0; |
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index e590b2df11dc..60a870e430be 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
@@ -16,7 +16,7 @@ void gfs2_tune_init(struct gfs2_tune *gt); | |||
16 | 16 | ||
17 | int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); | 17 | int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); |
18 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); | 18 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); |
19 | struct page *gfs2_read_super(struct super_block *sb, sector_t sector); | 19 | int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); |
20 | 20 | ||
21 | static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) | 21 | static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) |
22 | { | 22 | { |
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 601eaa1b9ed6..424a0774eda8 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
@@ -115,8 +115,8 @@ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide, | |||
115 | "GFS2: fsid=%s: inode = %llu %llu\n" | 115 | "GFS2: fsid=%s: inode = %llu %llu\n" |
116 | "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", | 116 | "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", |
117 | sdp->sd_fsname, | 117 | sdp->sd_fsname, |
118 | sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino, | 118 | sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino, |
119 | (unsigned long long)ip->i_num.no_addr, | 119 | (unsigned long long)ip->i_no_addr, |
120 | sdp->sd_fsname, function, file, line); | 120 | sdp->sd_fsname, function, file, line); |
121 | return rv; | 121 | return rv; |
122 | } | 122 | } |
@@ -137,7 +137,7 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide, | |||
137 | "GFS2: fsid=%s: RG = %llu\n" | 137 | "GFS2: fsid=%s: RG = %llu\n" |
138 | "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", | 138 | "GFS2: fsid=%s: function = %s, file = %s, line = %u\n", |
139 | sdp->sd_fsname, | 139 | sdp->sd_fsname, |
140 | sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr, | 140 | sdp->sd_fsname, (unsigned long long)rgd->rd_addr, |
141 | sdp->sd_fsname, function, file, line); | 141 | sdp->sd_fsname, function, file, line); |
142 | return rv; | 142 | return rv; |
143 | } | 143 | } |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index f317c270d4bf..afae306b177c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -49,6 +49,7 @@ header-y += consolemap.h | |||
49 | header-y += const.h | 49 | header-y += const.h |
50 | header-y += cycx_cfm.h | 50 | header-y += cycx_cfm.h |
51 | header-y += dlm_device.h | 51 | header-y += dlm_device.h |
52 | header-y += dlm_netlink.h | ||
52 | header-y += dm-ioctl.h | 53 | header-y += dm-ioctl.h |
53 | header-y += dn.h | 54 | header-y += dn.h |
54 | header-y += dqblk_v1.h | 55 | header-y += dqblk_v1.h |
diff --git a/include/linux/dlm.h b/include/linux/dlm.h index 1b1dcb9a40bb..be9d278761e0 100644 --- a/include/linux/dlm.h +++ b/include/linux/dlm.h | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -85,7 +85,11 @@ | |||
85 | * Only relevant to locks originating in userspace. A persistent lock will not | 85 | * Only relevant to locks originating in userspace. A persistent lock will not |
86 | * be removed if the process holding the lock exits. | 86 | * be removed if the process holding the lock exits. |
87 | * | 87 | * |
88 | * DLM_LKF_NODLKWT | 88 | * DLM_LKF_NODLCKWT |
89 | * | ||
90 | * Do not cancel the lock if it gets into conversion deadlock. | ||
91 | * Exclude this lock from being monitored due to DLM_LSFL_TIMEWARN. | ||
92 | * | ||
89 | * DLM_LKF_NODLCKBLK | 93 | * DLM_LKF_NODLCKBLK |
90 | * | 94 | * |
91 | * net yet implemented | 95 | * net yet implemented |
@@ -149,6 +153,7 @@ | |||
149 | #define DLM_LKF_ALTPR 0x00008000 | 153 | #define DLM_LKF_ALTPR 0x00008000 |
150 | #define DLM_LKF_ALTCW 0x00010000 | 154 | #define DLM_LKF_ALTCW 0x00010000 |
151 | #define DLM_LKF_FORCEUNLOCK 0x00020000 | 155 | #define DLM_LKF_FORCEUNLOCK 0x00020000 |
156 | #define DLM_LKF_TIMEOUT 0x00040000 | ||
152 | 157 | ||
153 | /* | 158 | /* |
154 | * Some return codes that are not in errno.h | 159 | * Some return codes that are not in errno.h |
@@ -199,11 +204,12 @@ struct dlm_lksb { | |||
199 | char * sb_lvbptr; | 204 | char * sb_lvbptr; |
200 | }; | 205 | }; |
201 | 206 | ||
207 | #define DLM_LSFL_NODIR 0x00000001 | ||
208 | #define DLM_LSFL_TIMEWARN 0x00000002 | ||
209 | #define DLM_LSFL_FS 0x00000004 | ||
202 | 210 | ||
203 | #ifdef __KERNEL__ | 211 | #ifdef __KERNEL__ |
204 | 212 | ||
205 | #define DLM_LSFL_NODIR 0x00000001 | ||
206 | |||
207 | /* | 213 | /* |
208 | * dlm_new_lockspace | 214 | * dlm_new_lockspace |
209 | * | 215 | * |
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h index c2735cab2ebf..9642277a152a 100644 --- a/include/linux/dlm_device.h +++ b/include/linux/dlm_device.h | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -18,21 +18,24 @@ | |||
18 | #define DLM_USER_LVB_LEN 32 | 18 | #define DLM_USER_LVB_LEN 32 |
19 | 19 | ||
20 | /* Version of the device interface */ | 20 | /* Version of the device interface */ |
21 | #define DLM_DEVICE_VERSION_MAJOR 5 | 21 | #define DLM_DEVICE_VERSION_MAJOR 6 |
22 | #define DLM_DEVICE_VERSION_MINOR 1 | 22 | #define DLM_DEVICE_VERSION_MINOR 0 |
23 | #define DLM_DEVICE_VERSION_PATCH 0 | 23 | #define DLM_DEVICE_VERSION_PATCH 0 |
24 | 24 | ||
25 | /* struct passed to the lock write */ | 25 | /* struct passed to the lock write */ |
26 | struct dlm_lock_params { | 26 | struct dlm_lock_params { |
27 | __u8 mode; | 27 | __u8 mode; |
28 | __u8 namelen; | 28 | __u8 namelen; |
29 | __u16 flags; | 29 | __u16 unused; |
30 | __u32 flags; | ||
30 | __u32 lkid; | 31 | __u32 lkid; |
31 | __u32 parent; | 32 | __u32 parent; |
32 | void __user *castparam; | 33 | __u64 xid; |
34 | __u64 timeout; | ||
35 | void __user *castparam; | ||
33 | void __user *castaddr; | 36 | void __user *castaddr; |
34 | void __user *bastparam; | 37 | void __user *bastparam; |
35 | void __user *bastaddr; | 38 | void __user *bastaddr; |
36 | struct dlm_lksb __user *lksb; | 39 | struct dlm_lksb __user *lksb; |
37 | char lvb[DLM_USER_LVB_LEN]; | 40 | char lvb[DLM_USER_LVB_LEN]; |
38 | char name[0]; | 41 | char name[0]; |
@@ -62,9 +65,15 @@ struct dlm_write_request { | |||
62 | } i; | 65 | } i; |
63 | }; | 66 | }; |
64 | 67 | ||
68 | struct dlm_device_version { | ||
69 | __u32 version[3]; | ||
70 | }; | ||
71 | |||
65 | /* struct read from the "device" fd, | 72 | /* struct read from the "device" fd, |
66 | consists mainly of userspace pointers for the library to use */ | 73 | consists mainly of userspace pointers for the library to use */ |
74 | |||
67 | struct dlm_lock_result { | 75 | struct dlm_lock_result { |
76 | __u32 version[3]; | ||
68 | __u32 length; | 77 | __u32 length; |
69 | void __user * user_astaddr; | 78 | void __user * user_astaddr; |
70 | void __user * user_astparam; | 79 | void __user * user_astparam; |
@@ -83,6 +92,7 @@ struct dlm_lock_result { | |||
83 | #define DLM_USER_CREATE_LOCKSPACE 4 | 92 | #define DLM_USER_CREATE_LOCKSPACE 4 |
84 | #define DLM_USER_REMOVE_LOCKSPACE 5 | 93 | #define DLM_USER_REMOVE_LOCKSPACE 5 |
85 | #define DLM_USER_PURGE 6 | 94 | #define DLM_USER_PURGE 6 |
95 | #define DLM_USER_DEADLOCK 7 | ||
86 | 96 | ||
87 | /* Arbitrary length restriction */ | 97 | /* Arbitrary length restriction */ |
88 | #define MAX_LS_NAME_LEN 64 | 98 | #define MAX_LS_NAME_LEN 64 |
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h new file mode 100644 index 000000000000..19276332707a --- /dev/null +++ b/include/linux/dlm_netlink.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||
3 | * | ||
4 | * This copyrighted material is made available to anyone wishing to use, | ||
5 | * modify, copy, or redistribute it subject to the terms and conditions | ||
6 | * of the GNU General Public License v.2. | ||
7 | */ | ||
8 | |||
9 | #ifndef _DLM_NETLINK_H | ||
10 | #define _DLM_NETLINK_H | ||
11 | |||
12 | enum { | ||
13 | DLM_STATUS_WAITING = 1, | ||
14 | DLM_STATUS_GRANTED = 2, | ||
15 | DLM_STATUS_CONVERT = 3, | ||
16 | }; | ||
17 | |||
18 | #define DLM_LOCK_DATA_VERSION 1 | ||
19 | |||
20 | struct dlm_lock_data { | ||
21 | uint16_t version; | ||
22 | uint32_t lockspace_id; | ||
23 | int nodeid; | ||
24 | int ownpid; | ||
25 | uint32_t id; | ||
26 | uint32_t remid; | ||
27 | uint64_t xid; | ||
28 | int8_t status; | ||
29 | int8_t grmode; | ||
30 | int8_t rqmode; | ||
31 | unsigned long timestamp; | ||
32 | int resource_namelen; | ||
33 | char resource_name[DLM_RESNAME_MAXLEN]; | ||
34 | }; | ||
35 | |||
36 | enum { | ||
37 | DLM_CMD_UNSPEC = 0, | ||
38 | DLM_CMD_HELLO, /* user->kernel */ | ||
39 | DLM_CMD_TIMEOUT, /* kernel->user */ | ||
40 | __DLM_CMD_MAX, | ||
41 | }; | ||
42 | |||
43 | #define DLM_CMD_MAX (__DLM_CMD_MAX - 1) | ||
44 | |||
45 | enum { | ||
46 | DLM_TYPE_UNSPEC = 0, | ||
47 | DLM_TYPE_LOCK, | ||
48 | __DLM_TYPE_MAX, | ||
49 | }; | ||
50 | |||
51 | #define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1) | ||
52 | |||
53 | #define DLM_GENL_VERSION 0x1 | ||
54 | #define DLM_GENL_NAME "DLM" | ||
55 | |||
56 | #endif /* _DLM_NETLINK_H */ | ||
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 8b7e4c1e32ae..a44a6a078f0a 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h | |||
@@ -54,18 +54,6 @@ struct gfs2_inum { | |||
54 | __be64 no_addr; | 54 | __be64 no_addr; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | struct gfs2_inum_host { | ||
58 | __u64 no_formal_ino; | ||
59 | __u64 no_addr; | ||
60 | }; | ||
61 | |||
62 | static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1, | ||
63 | const struct gfs2_inum_host *ino2) | ||
64 | { | ||
65 | return ino1->no_formal_ino == ino2->no_formal_ino && | ||
66 | ino1->no_addr == ino2->no_addr; | ||
67 | } | ||
68 | |||
69 | /* | 57 | /* |
70 | * Generic metadata head structure | 58 | * Generic metadata head structure |
71 | * Every inplace buffer logged in the journal must start with this. | 59 | * Every inplace buffer logged in the journal must start with this. |
@@ -94,12 +82,6 @@ struct gfs2_meta_header { | |||
94 | __be32 __pad1; /* Was incarnation number in gfs1 */ | 82 | __be32 __pad1; /* Was incarnation number in gfs1 */ |
95 | }; | 83 | }; |
96 | 84 | ||
97 | struct gfs2_meta_header_host { | ||
98 | __u32 mh_magic; | ||
99 | __u32 mh_type; | ||
100 | __u32 mh_format; | ||
101 | }; | ||
102 | |||
103 | /* | 85 | /* |
104 | * super-block structure | 86 | * super-block structure |
105 | * | 87 | * |
@@ -139,23 +121,6 @@ struct gfs2_sb { | |||
139 | /* In gfs1, quota and license dinodes followed */ | 121 | /* In gfs1, quota and license dinodes followed */ |
140 | }; | 122 | }; |
141 | 123 | ||
142 | struct gfs2_sb_host { | ||
143 | struct gfs2_meta_header_host sb_header; | ||
144 | |||
145 | __u32 sb_fs_format; | ||
146 | __u32 sb_multihost_format; | ||
147 | |||
148 | __u32 sb_bsize; | ||
149 | __u32 sb_bsize_shift; | ||
150 | |||
151 | struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */ | ||
152 | struct gfs2_inum_host sb_root_dir; | ||
153 | |||
154 | char sb_lockproto[GFS2_LOCKNAME_LEN]; | ||
155 | char sb_locktable[GFS2_LOCKNAME_LEN]; | ||
156 | /* In gfs1, quota and license dinodes followed */ | ||
157 | }; | ||
158 | |||
159 | /* | 124 | /* |
160 | * resource index structure | 125 | * resource index structure |
161 | */ | 126 | */ |
@@ -173,14 +138,6 @@ struct gfs2_rindex { | |||
173 | __u8 ri_reserved[64]; | 138 | __u8 ri_reserved[64]; |
174 | }; | 139 | }; |
175 | 140 | ||
176 | struct gfs2_rindex_host { | ||
177 | __u64 ri_addr; /* grp block disk address */ | ||
178 | __u64 ri_data0; /* first data location */ | ||
179 | __u32 ri_length; /* length of rgrp header in fs blocks */ | ||
180 | __u32 ri_data; /* num of data blocks in rgrp */ | ||
181 | __u32 ri_bitbytes; /* number of bytes in data bitmaps */ | ||
182 | }; | ||
183 | |||
184 | /* | 141 | /* |
185 | * resource group header structure | 142 | * resource group header structure |
186 | */ | 143 | */ |
@@ -212,13 +169,6 @@ struct gfs2_rgrp { | |||
212 | __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */ | 169 | __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */ |
213 | }; | 170 | }; |
214 | 171 | ||
215 | struct gfs2_rgrp_host { | ||
216 | __u32 rg_flags; | ||
217 | __u32 rg_free; | ||
218 | __u32 rg_dinodes; | ||
219 | __u64 rg_igeneration; | ||
220 | }; | ||
221 | |||
222 | /* | 172 | /* |
223 | * quota structure | 173 | * quota structure |
224 | */ | 174 | */ |
@@ -230,12 +180,6 @@ struct gfs2_quota { | |||
230 | __u8 qu_reserved[64]; | 180 | __u8 qu_reserved[64]; |
231 | }; | 181 | }; |
232 | 182 | ||
233 | struct gfs2_quota_host { | ||
234 | __u64 qu_limit; | ||
235 | __u64 qu_warn; | ||
236 | __u64 qu_value; | ||
237 | }; | ||
238 | |||
239 | /* | 183 | /* |
240 | * dinode structure | 184 | * dinode structure |
241 | */ | 185 | */ |
@@ -315,29 +259,11 @@ struct gfs2_dinode { | |||
315 | struct gfs2_inum __pad4; /* Unused even in current gfs1 */ | 259 | struct gfs2_inum __pad4; /* Unused even in current gfs1 */ |
316 | 260 | ||
317 | __be64 di_eattr; /* extended attribute block number */ | 261 | __be64 di_eattr; /* extended attribute block number */ |
262 | __be32 di_atime_nsec; /* nsec portion of atime */ | ||
263 | __be32 di_mtime_nsec; /* nsec portion of mtime */ | ||
264 | __be32 di_ctime_nsec; /* nsec portion of ctime */ | ||
318 | 265 | ||
319 | __u8 di_reserved[56]; | 266 | __u8 di_reserved[44]; |
320 | }; | ||
321 | |||
322 | struct gfs2_dinode_host { | ||
323 | __u64 di_size; /* number of bytes in file */ | ||
324 | __u64 di_blocks; /* number of blocks in file */ | ||
325 | |||
326 | /* This section varies from gfs1. Padding added to align with | ||
327 | * remainder of dinode | ||
328 | */ | ||
329 | __u64 di_goal_meta; /* rgrp to alloc from next */ | ||
330 | __u64 di_goal_data; /* data block goal */ | ||
331 | __u64 di_generation; /* generation number for NFS */ | ||
332 | |||
333 | __u32 di_flags; /* GFS2_DIF_... */ | ||
334 | __u16 di_height; /* height of metadata */ | ||
335 | |||
336 | /* These only apply to directories */ | ||
337 | __u16 di_depth; /* Number of bits in the table */ | ||
338 | __u32 di_entries; /* The number of entries in the directory */ | ||
339 | |||
340 | __u64 di_eattr; /* extended attribute block number */ | ||
341 | }; | 267 | }; |
342 | 268 | ||
343 | /* | 269 | /* |
@@ -414,16 +340,6 @@ struct gfs2_log_header { | |||
414 | __be32 lh_hash; | 340 | __be32 lh_hash; |
415 | }; | 341 | }; |
416 | 342 | ||
417 | struct gfs2_log_header_host { | ||
418 | struct gfs2_meta_header_host lh_header; | ||
419 | |||
420 | __u64 lh_sequence; /* Sequence number of this transaction */ | ||
421 | __u32 lh_flags; /* GFS2_LOG_HEAD_... */ | ||
422 | __u32 lh_tail; /* Block number of log tail */ | ||
423 | __u32 lh_blkno; | ||
424 | __u32 lh_hash; | ||
425 | }; | ||
426 | |||
427 | /* | 343 | /* |
428 | * Log type descriptor | 344 | * Log type descriptor |
429 | */ | 345 | */ |
@@ -464,11 +380,6 @@ struct gfs2_inum_range { | |||
464 | __be64 ir_length; | 380 | __be64 ir_length; |
465 | }; | 381 | }; |
466 | 382 | ||
467 | struct gfs2_inum_range_host { | ||
468 | __u64 ir_start; | ||
469 | __u64 ir_length; | ||
470 | }; | ||
471 | |||
472 | /* | 383 | /* |
473 | * Statfs change | 384 | * Statfs change |
474 | * Describes an change to the pool of free and allocated | 385 | * Describes an change to the pool of free and allocated |
@@ -481,12 +392,6 @@ struct gfs2_statfs_change { | |||
481 | __be64 sc_dinodes; | 392 | __be64 sc_dinodes; |
482 | }; | 393 | }; |
483 | 394 | ||
484 | struct gfs2_statfs_change_host { | ||
485 | __u64 sc_total; | ||
486 | __u64 sc_free; | ||
487 | __u64 sc_dinodes; | ||
488 | }; | ||
489 | |||
490 | /* | 395 | /* |
491 | * Quota change | 396 | * Quota change |
492 | * Describes an allocation change for a particular | 397 | * Describes an allocation change for a particular |
@@ -501,39 +406,12 @@ struct gfs2_quota_change { | |||
501 | __be32 qc_id; | 406 | __be32 qc_id; |
502 | }; | 407 | }; |
503 | 408 | ||
504 | struct gfs2_quota_change_host { | 409 | struct gfs2_quota_lvb { |
505 | __u64 qc_change; | 410 | __be32 qb_magic; |
506 | __u32 qc_flags; /* GFS2_QCF_... */ | 411 | __u32 __pad; |
507 | __u32 qc_id; | 412 | __be64 qb_limit; /* Hard limit of # blocks to alloc */ |
413 | __be64 qb_warn; /* Warn user when alloc is above this # */ | ||
414 | __be64 qb_value; /* Current # blocks allocated */ | ||
508 | }; | 415 | }; |
509 | 416 | ||
510 | #ifdef __KERNEL__ | ||
511 | /* Translation functions */ | ||
512 | |||
513 | extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf); | ||
514 | extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf); | ||
515 | extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf); | ||
516 | extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf); | ||
517 | extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf); | ||
518 | extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf); | ||
519 | extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf); | ||
520 | extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf); | ||
521 | struct gfs2_inode; | ||
522 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | ||
523 | extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); | ||
524 | extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); | ||
525 | extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf); | ||
526 | extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf); | ||
527 | extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf); | ||
528 | extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf); | ||
529 | extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf); | ||
530 | extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf); | ||
531 | |||
532 | /* Printing functions */ | ||
533 | |||
534 | extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri); | ||
535 | extern void gfs2_dinode_print(const struct gfs2_inode *ip); | ||
536 | |||
537 | #endif /* __KERNEL__ */ | ||
538 | |||
539 | #endif /* __GFS2_ONDISK_DOT_H__ */ | 417 | #endif /* __GFS2_ONDISK_DOT_H__ */ |