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__ */ |
