diff --git a/[refs] b/[refs] index ecbc5323b3af..1c4e3b5047b3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9ea319b61613085f501a79cf8d405cb221d084f3 +refs/heads/master: f3c85bc1bc72b4cc8d58664a490a9d42bdb6565a diff --git a/trunk/Makefile b/trunk/Makefile index 53bf6ec1af9d..fd3ca6e8188a 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc2 NAME = Rotary Wombat # *DOCUMENTATION* diff --git a/trunk/drivers/crypto/talitos.c b/trunk/drivers/crypto/talitos.c index 681c15f42083..ee827a7f7c6a 100644 --- a/trunk/drivers/crypto/talitos.c +++ b/trunk/drivers/crypto/talitos.c @@ -96,6 +96,9 @@ struct talitos_private { unsigned int exec_units; unsigned int desc_types; + /* SEC Compatibility info */ + unsigned long features; + /* next channel to be assigned next incoming descriptor */ atomic_t last_chan; @@ -133,6 +136,9 @@ struct talitos_private { struct hwrng rng; }; +/* .features flag */ +#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 + /* * map virtual single (contiguous) pointer to h/w descriptor pointer */ @@ -785,7 +791,7 @@ static void ipsec_esp_encrypt_done(struct device *dev, /* copy the generated ICV to dst */ if (edesc->dma_len) { icvdata = &edesc->link_tbl[edesc->src_nents + - edesc->dst_nents + 1]; + edesc->dst_nents + 2]; sg = sg_last(areq->dst, edesc->dst_nents); memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize, icvdata, ctx->authsize); @@ -814,7 +820,7 @@ static void ipsec_esp_decrypt_done(struct device *dev, /* auth check */ if (edesc->dma_len) icvdata = &edesc->link_tbl[edesc->src_nents + - edesc->dst_nents + 1]; + edesc->dst_nents + 2]; else icvdata = &edesc->link_tbl[0]; @@ -921,10 +927,30 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen, &edesc->link_tbl[0]); if (sg_count > 1) { + struct talitos_ptr *link_tbl_ptr = + &edesc->link_tbl[sg_count-1]; + struct scatterlist *sg; + struct talitos_private *priv = dev_get_drvdata(dev); + desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP; desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl); dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); + /* If necessary for this SEC revision, + * add a link table entry for ICV. + */ + if ((priv->features & + TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT) && + (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) { + link_tbl_ptr->j_extent = 0; + link_tbl_ptr++; + link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; + link_tbl_ptr->len = cpu_to_be16(authsize); + sg = sg_last(areq->src, edesc->src_nents ? : 1); + link_tbl_ptr->ptr = cpu_to_be32( + (char *)sg_dma_address(sg) + + sg->length - authsize); + } } else { /* Only one segment now, so no link tbl needed */ desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); @@ -944,12 +970,11 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst)); } else { struct talitos_ptr *link_tbl_ptr = - &edesc->link_tbl[edesc->src_nents]; - struct scatterlist *sg; + &edesc->link_tbl[edesc->src_nents + 1]; desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *) edesc->dma_link_tbl + - edesc->src_nents); + edesc->src_nents + 1); if (areq->src == areq->dst) { memcpy(link_tbl_ptr, &edesc->link_tbl[0], edesc->src_nents * sizeof(struct talitos_ptr)); @@ -957,14 +982,10 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen, link_tbl_ptr); } + /* Add an entry to the link table for ICV data */ link_tbl_ptr += sg_count - 1; - - /* handle case where sg_last contains the ICV exclusively */ - sg = sg_last(areq->dst, edesc->dst_nents); - if (sg->length == ctx->authsize) - link_tbl_ptr--; - link_tbl_ptr->j_extent = 0; + sg_count++; link_tbl_ptr++; link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; link_tbl_ptr->len = cpu_to_be16(authsize); @@ -973,7 +994,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, link_tbl_ptr->ptr = cpu_to_be32((struct talitos_ptr *) edesc->dma_link_tbl + edesc->src_nents + - edesc->dst_nents + 1); + edesc->dst_nents + 2); desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP; dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, @@ -1040,12 +1061,12 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq, /* * allocate space for base edesc plus the link tables, - * allowing for a separate entry for the generated ICV (+ 1), + * allowing for two separate entries for ICV and generated ICV (+ 2), * and the ICV data itself */ alloc_len = sizeof(struct ipsec_esp_edesc); if (src_nents || dst_nents) { - dma_len = (src_nents + dst_nents + 1) * + dma_len = (src_nents + dst_nents + 2) * sizeof(struct talitos_ptr) + ctx->authsize; alloc_len += dma_len; } else { @@ -1104,7 +1125,7 @@ static int aead_authenc_decrypt(struct aead_request *req) /* stash incoming ICV for later cmp with ICV generated by the h/w */ if (edesc->dma_len) icvdata = &edesc->link_tbl[edesc->src_nents + - edesc->dst_nents + 1]; + edesc->dst_nents + 2]; else icvdata = &edesc->link_tbl[0]; @@ -1480,6 +1501,9 @@ static int talitos_probe(struct of_device *ofdev, goto err_out; } + if (of_device_is_compatible(np, "fsl,sec3.0")) + priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; + priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, GFP_KERNEL); priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, diff --git a/trunk/fs/dlm/config.c b/trunk/fs/dlm/config.c index 89d2fb7b991a..c4e7d721bd8d 100644 --- a/trunk/fs/dlm/config.c +++ b/trunk/fs/dlm/config.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -30,16 +30,16 @@ static struct config_group *space_list; static struct config_group *comm_list; -static struct dlm_comm *local_comm; +static struct comm *local_comm; -struct dlm_clusters; -struct dlm_cluster; -struct dlm_spaces; -struct dlm_space; -struct dlm_comms; -struct dlm_comm; -struct dlm_nodes; -struct dlm_node; +struct clusters; +struct cluster; +struct spaces; +struct space; +struct comms; +struct comm; +struct nodes; +struct node; static struct config_group *make_cluster(struct config_group *, const char *); static void drop_cluster(struct config_group *, struct config_item *); @@ -68,22 +68,17 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len); -static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf); -static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf, - size_t len); -static ssize_t comm_local_read(struct dlm_comm *cm, char *buf); -static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, - size_t len); -static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, - size_t len); -static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf); -static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, - size_t len); -static ssize_t node_weight_read(struct dlm_node *nd, char *buf); -static ssize_t node_weight_write(struct dlm_node *nd, const char *buf, - size_t len); - -struct dlm_cluster { +static ssize_t comm_nodeid_read(struct comm *cm, char *buf); +static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len); +static ssize_t comm_local_read(struct comm *cm, char *buf); +static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len); +static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len); +static ssize_t node_nodeid_read(struct node *nd, char *buf); +static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len); +static ssize_t node_weight_read(struct node *nd, char *buf); +static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len); + +struct cluster { struct config_group group; unsigned int cl_tcp_port; unsigned int cl_buffer_size; @@ -114,11 +109,11 @@ enum { struct cluster_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct dlm_cluster *, char *); - ssize_t (*store)(struct dlm_cluster *, const char *, size_t); + ssize_t (*show)(struct cluster *, char *); + ssize_t (*store)(struct cluster *, const char *, size_t); }; -static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, +static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field, int *info_field, int check_zero, const char *buf, size_t len) { @@ -139,12 +134,12 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, } #define CLUSTER_ATTR(name, check_zero) \ -static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \ +static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len) \ { \ return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name, \ check_zero, buf, len); \ } \ -static ssize_t name##_read(struct dlm_cluster *cl, char *buf) \ +static ssize_t name##_read(struct cluster *cl, char *buf) \ { \ return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name); \ } \ @@ -186,8 +181,8 @@ enum { struct comm_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct dlm_comm *, char *); - ssize_t (*store)(struct dlm_comm *, const char *, size_t); + ssize_t (*show)(struct comm *, char *); + ssize_t (*store)(struct comm *, const char *, size_t); }; static struct comm_attribute comm_attr_nodeid = { @@ -227,8 +222,8 @@ enum { struct node_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct dlm_node *, char *); - ssize_t (*store)(struct dlm_node *, const char *, size_t); + ssize_t (*show)(struct node *, char *); + ssize_t (*store)(struct node *, const char *, size_t); }; static struct node_attribute node_attr_nodeid = { @@ -253,26 +248,26 @@ static struct configfs_attribute *node_attrs[] = { NULL, }; -struct dlm_clusters { +struct clusters { struct configfs_subsystem subsys; }; -struct dlm_spaces { +struct spaces { struct config_group ss_group; }; -struct dlm_space { +struct space { struct config_group group; struct list_head members; struct mutex members_lock; int members_count; }; -struct dlm_comms { +struct comms { struct config_group cs_group; }; -struct dlm_comm { +struct comm { struct config_item item; int nodeid; int local; @@ -280,11 +275,11 @@ struct dlm_comm { struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; }; -struct dlm_nodes { +struct nodes { struct config_group ns_group; }; -struct dlm_node { +struct node { struct config_item item; struct list_head list; /* space->members */ int nodeid; @@ -377,40 +372,38 @@ static struct config_item_type node_type = { .ct_owner = THIS_MODULE, }; -static struct dlm_cluster *to_cluster(struct config_item *i) +static struct cluster *to_cluster(struct config_item *i) { - return i ? container_of(to_config_group(i), struct dlm_cluster, group) : - NULL; + return i ? container_of(to_config_group(i), struct cluster, group):NULL; } -static struct dlm_space *to_space(struct config_item *i) +static struct space *to_space(struct config_item *i) { - return i ? container_of(to_config_group(i), struct dlm_space, group) : - NULL; + return i ? container_of(to_config_group(i), struct space, group) : NULL; } -static struct dlm_comm *to_comm(struct config_item *i) +static struct comm *to_comm(struct config_item *i) { - return i ? container_of(i, struct dlm_comm, item) : NULL; + return i ? container_of(i, struct comm, item) : NULL; } -static struct dlm_node *to_node(struct config_item *i) +static struct node *to_node(struct config_item *i) { - return i ? container_of(i, struct dlm_node, item) : NULL; + return i ? container_of(i, struct node, item) : NULL; } static struct config_group *make_cluster(struct config_group *g, const char *name) { - struct dlm_cluster *cl = NULL; - struct dlm_spaces *sps = NULL; - struct dlm_comms *cms = NULL; + struct cluster *cl = NULL; + struct spaces *sps = NULL; + struct comms *cms = NULL; void *gps = NULL; - cl = kzalloc(sizeof(struct dlm_cluster), GFP_KERNEL); + cl = kzalloc(sizeof(struct cluster), GFP_KERNEL); gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); - sps = kzalloc(sizeof(struct dlm_spaces), GFP_KERNEL); - cms = kzalloc(sizeof(struct dlm_comms), GFP_KERNEL); + sps = kzalloc(sizeof(struct spaces), GFP_KERNEL); + cms = kzalloc(sizeof(struct comms), GFP_KERNEL); if (!cl || !gps || !sps || !cms) goto fail; @@ -450,7 +443,7 @@ static struct config_group *make_cluster(struct config_group *g, static void drop_cluster(struct config_group *g, struct config_item *i) { - struct dlm_cluster *cl = to_cluster(i); + struct cluster *cl = to_cluster(i); struct config_item *tmp; int j; @@ -468,20 +461,20 @@ static void drop_cluster(struct config_group *g, struct config_item *i) static void release_cluster(struct config_item *i) { - struct dlm_cluster *cl = to_cluster(i); + struct cluster *cl = to_cluster(i); kfree(cl->group.default_groups); kfree(cl); } static struct config_group *make_space(struct config_group *g, const char *name) { - struct dlm_space *sp = NULL; - struct dlm_nodes *nds = NULL; + struct space *sp = NULL; + struct nodes *nds = NULL; void *gps = NULL; - sp = kzalloc(sizeof(struct dlm_space), GFP_KERNEL); + sp = kzalloc(sizeof(struct space), GFP_KERNEL); gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL); - nds = kzalloc(sizeof(struct dlm_nodes), GFP_KERNEL); + nds = kzalloc(sizeof(struct nodes), GFP_KERNEL); if (!sp || !gps || !nds) goto fail; @@ -507,7 +500,7 @@ static struct config_group *make_space(struct config_group *g, const char *name) static void drop_space(struct config_group *g, struct config_item *i) { - struct dlm_space *sp = to_space(i); + struct space *sp = to_space(i); struct config_item *tmp; int j; @@ -524,16 +517,16 @@ static void drop_space(struct config_group *g, struct config_item *i) static void release_space(struct config_item *i) { - struct dlm_space *sp = to_space(i); + struct space *sp = to_space(i); kfree(sp->group.default_groups); kfree(sp); } static struct config_item *make_comm(struct config_group *g, const char *name) { - struct dlm_comm *cm; + struct comm *cm; - cm = kzalloc(sizeof(struct dlm_comm), GFP_KERNEL); + cm = kzalloc(sizeof(struct comm), GFP_KERNEL); if (!cm) return ERR_PTR(-ENOMEM); @@ -546,7 +539,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name) static void drop_comm(struct config_group *g, struct config_item *i) { - struct dlm_comm *cm = to_comm(i); + struct comm *cm = to_comm(i); if (local_comm == cm) local_comm = NULL; dlm_lowcomms_close(cm->nodeid); @@ -557,16 +550,16 @@ static void drop_comm(struct config_group *g, struct config_item *i) static void release_comm(struct config_item *i) { - struct dlm_comm *cm = to_comm(i); + struct comm *cm = to_comm(i); kfree(cm); } static struct config_item *make_node(struct config_group *g, const char *name) { - struct dlm_space *sp = to_space(g->cg_item.ci_parent); - struct dlm_node *nd; + struct space *sp = to_space(g->cg_item.ci_parent); + struct node *nd; - nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL); + nd = kzalloc(sizeof(struct node), GFP_KERNEL); if (!nd) return ERR_PTR(-ENOMEM); @@ -585,8 +578,8 @@ static struct config_item *make_node(struct config_group *g, const char *name) static void drop_node(struct config_group *g, struct config_item *i) { - struct dlm_space *sp = to_space(g->cg_item.ci_parent); - struct dlm_node *nd = to_node(i); + struct space *sp = to_space(g->cg_item.ci_parent); + struct node *nd = to_node(i); mutex_lock(&sp->members_lock); list_del(&nd->list); @@ -598,11 +591,11 @@ static void drop_node(struct config_group *g, struct config_item *i) static void release_node(struct config_item *i) { - struct dlm_node *nd = to_node(i); + struct node *nd = to_node(i); kfree(nd); } -static struct dlm_clusters clusters_root = { +static struct clusters clusters_root = { .subsys = { .su_group = { .cg_item = { @@ -632,7 +625,7 @@ void dlm_config_exit(void) static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_cluster *cl = to_cluster(i); + struct cluster *cl = to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->show ? cla->show(cl, buf) : 0; @@ -642,7 +635,7 @@ static ssize_t store_cluster(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_cluster *cl = to_cluster(i); + struct cluster *cl = to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->store ? cla->store(cl, buf, len) : -EINVAL; @@ -651,7 +644,7 @@ static ssize_t store_cluster(struct config_item *i, static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_comm *cm = to_comm(i); + struct comm *cm = to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->show ? cma->show(cm, buf) : 0; @@ -660,31 +653,29 @@ static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_comm *cm = to_comm(i); + struct comm *cm = to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->store ? cma->store(cm, buf, len) : -EINVAL; } -static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf) +static ssize_t comm_nodeid_read(struct comm *cm, char *buf) { return sprintf(buf, "%d\n", cm->nodeid); } -static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf, - size_t len) +static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len) { cm->nodeid = simple_strtol(buf, NULL, 0); return len; } -static ssize_t comm_local_read(struct dlm_comm *cm, char *buf) +static ssize_t comm_local_read(struct comm *cm, char *buf) { return sprintf(buf, "%d\n", cm->local); } -static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, - size_t len) +static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len) { cm->local= simple_strtol(buf, NULL, 0); if (cm->local && !local_comm) @@ -692,7 +683,7 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, return len; } -static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) +static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len) { struct sockaddr_storage *addr; @@ -714,7 +705,7 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_node *nd = to_node(i); + struct node *nd = to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->show ? nda->show(nd, buf) : 0; @@ -723,31 +714,29 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_node *nd = to_node(i); + struct node *nd = to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->store ? nda->store(nd, buf, len) : -EINVAL; } -static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf) +static ssize_t node_nodeid_read(struct node *nd, char *buf) { return sprintf(buf, "%d\n", nd->nodeid); } -static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, - size_t len) +static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len) { nd->nodeid = simple_strtol(buf, NULL, 0); return len; } -static ssize_t node_weight_read(struct dlm_node *nd, char *buf) +static ssize_t node_weight_read(struct node *nd, char *buf) { return sprintf(buf, "%d\n", nd->weight); } -static ssize_t node_weight_write(struct dlm_node *nd, const char *buf, - size_t len) +static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) { nd->weight = simple_strtol(buf, NULL, 0); return len; @@ -757,7 +746,7 @@ static ssize_t node_weight_write(struct dlm_node *nd, const char *buf, * Functions for the dlm to get the info that's been configured */ -static struct dlm_space *get_space(char *name) +static struct space *get_space(char *name) { struct config_item *i; @@ -771,15 +760,15 @@ static struct dlm_space *get_space(char *name) return to_space(i); } -static void put_space(struct dlm_space *sp) +static void put_space(struct space *sp) { config_item_put(&sp->group.cg_item); } -static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) +static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) { struct config_item *i; - struct dlm_comm *cm = NULL; + struct comm *cm = NULL; int found = 0; if (!comm_list) @@ -812,7 +801,7 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) return cm; } -static void put_comm(struct dlm_comm *cm) +static void put_comm(struct comm *cm) { config_item_put(&cm->item); } @@ -821,8 +810,8 @@ static void put_comm(struct dlm_comm *cm) int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, int **new_out, int *new_count_out) { - struct dlm_space *sp; - struct dlm_node *nd; + struct space *sp; + struct node *nd; int i = 0, rv = 0, ids_count = 0, new_count = 0; int *ids, *new; @@ -885,8 +874,8 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, int dlm_node_weight(char *lsname, int nodeid) { - struct dlm_space *sp; - struct dlm_node *nd; + struct space *sp; + struct node *nd; int w = -EEXIST; sp = get_space(lsname); @@ -908,7 +897,7 @@ int dlm_node_weight(char *lsname, int nodeid) int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) { - struct dlm_comm *cm = get_comm(nodeid, NULL); + struct comm *cm = get_comm(nodeid, NULL); if (!cm) return -EEXIST; if (!cm->addr_count) @@ -920,7 +909,7 @@ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) { - struct dlm_comm *cm = get_comm(0, addr); + struct comm *cm = get_comm(0, addr); if (!cm) return -EEXIST; *nodeid = cm->nodeid; diff --git a/trunk/fs/dlm/user.c b/trunk/fs/dlm/user.c index 34f14a14fb4e..929e48ae7591 100644 --- a/trunk/fs/dlm/user.c +++ b/trunk/fs/dlm/user.c @@ -527,10 +527,8 @@ static ssize_t device_write(struct file *file, const char __user *buf, k32buf = (struct dlm_write_request32 *)kbuf; kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) - sizeof(struct dlm_write_request32)), GFP_KERNEL); - if (!kbuf) { - kfree(k32buf); + if (!kbuf) return -ENOMEM; - } if (proc) set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); @@ -541,10 +539,8 @@ static ssize_t device_write(struct file *file, const char __user *buf, /* do we really need this? can a write happen after a close? */ if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) && - (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) { - error = -EINVAL; - goto out_free; - } + (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) + return -EINVAL; sigfillset(&allsigs); sigprocmask(SIG_BLOCK, &allsigs, &tmpsig); diff --git a/trunk/fs/xfs/linux-2.6/sema.h b/trunk/fs/xfs/linux-2.6/sema.h new file mode 100644 index 000000000000..3abe7e9ceb33 --- /dev/null +++ b/trunk/fs/xfs/linux-2.6/sema.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __XFS_SUPPORT_SEMA_H__ +#define __XFS_SUPPORT_SEMA_H__ + +#include +#include +#include +#include + +/* + * sema_t structure just maps to struct semaphore in Linux kernel. + */ + +typedef struct semaphore sema_t; + +#define initnsema(sp, val, name) sema_init(sp, val) +#define psema(sp, b) down(sp) +#define vsema(sp) up(sp) +#define freesema(sema) do { } while (0) + +static inline int issemalocked(sema_t *sp) +{ + return down_trylock(sp) || (up(sp), 0); +} + +/* + * Map cpsema (try to get the sema) to down_trylock. We need to switch + * the return values since cpsema returns 1 (acquired) 0 (failed) and + * down_trylock returns the reverse 0 (acquired) 1 (failed). + */ +static inline int cpsema(sema_t *sp) +{ + return down_trylock(sp) ? 0 : 1; +} + +#endif /* __XFS_SUPPORT_SEMA_H__ */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.c b/trunk/fs/xfs/linux-2.6/xfs_aops.c index f42f80a3b1fa..fa47e43b8b41 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.c @@ -73,6 +73,7 @@ xfs_page_trace( unsigned long pgoff) { xfs_inode_t *ip; + bhv_vnode_t *vp = vn_from_inode(inode); loff_t isize = i_size_read(inode); loff_t offset = page_offset(page); int delalloc = -1, unmapped = -1, unwritten = -1; @@ -80,7 +81,7 @@ xfs_page_trace( if (page_has_buffers(page)) xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); - ip = XFS_I(inode); + ip = xfs_vtoi(vp); if (!ip->i_rwtrace) return; diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.c b/trunk/fs/xfs/linux-2.6/xfs_buf.c index 986061ae1b9b..9cc8f0213095 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.c +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.c @@ -58,7 +58,7 @@ xfs_buf_trace( bp, id, (void *)(unsigned long)bp->b_flags, (void *)(unsigned long)bp->b_hold.counter, - (void *)(unsigned long)bp->b_sema.count, + (void *)(unsigned long)bp->b_sema.count.counter, (void *)current, data, ra, (void *)(unsigned long)((bp->b_file_offset>>32) & 0xffffffff), @@ -253,7 +253,7 @@ _xfs_buf_initialize( memset(bp, 0, sizeof(xfs_buf_t)); atomic_set(&bp->b_hold, 1); - init_completion(&bp->b_iowait); + init_MUTEX_LOCKED(&bp->b_iodonesema); INIT_LIST_HEAD(&bp->b_list); INIT_LIST_HEAD(&bp->b_hash_list); init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */ @@ -838,7 +838,6 @@ xfs_buf_rele( return; } - ASSERT(atomic_read(&bp->b_hold) > 0); if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) { if (bp->b_relse) { atomic_inc(&bp->b_hold); @@ -852,6 +851,11 @@ xfs_buf_rele( spin_unlock(&hash->bh_lock); xfs_buf_free(bp); } + } else { + /* + * Catch reference count leaks + */ + ASSERT(atomic_read(&bp->b_hold) >= 0); } } @@ -1033,7 +1037,7 @@ xfs_buf_ioend( xfs_buf_iodone_work(&bp->b_iodone_work); } } else { - complete(&bp->b_iowait); + up(&bp->b_iodonesema); } } @@ -1271,7 +1275,7 @@ xfs_buf_iowait( XB_TRACE(bp, "iowait", 0); if (atomic_read(&bp->b_io_remaining)) blk_run_address_space(bp->b_target->bt_mapping); - wait_for_completion(&bp->b_iowait); + down(&bp->b_iodonesema); XB_TRACE(bp, "iowaited", (long)bp->b_error); return bp->b_error; } @@ -1795,7 +1799,7 @@ int __init xfs_buf_init(void) { #ifdef XFS_BUF_TRACE - xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_NOFS); + xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP); #endif xfs_buf_zone = kmem_zone_init_flags(sizeof(xfs_buf_t), "xfs_buf", diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.h b/trunk/fs/xfs/linux-2.6/xfs_buf.h index fe0109956656..29d1d4adc078 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.h +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.h @@ -157,7 +157,7 @@ typedef struct xfs_buf { xfs_buf_iodone_t b_iodone; /* I/O completion function */ xfs_buf_relse_t b_relse; /* releasing function */ xfs_buf_bdstrat_t b_strat; /* pre-write function */ - struct completion b_iowait; /* queue for I/O waiters */ + struct semaphore b_iodonesema; /* Semaphore for I/O waiters */ void *b_fspriv; void *b_fspriv2; void *b_fspriv3; @@ -352,7 +352,7 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); #define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0) #define XFS_BUF_VSEMA(bp) xfs_buf_unlock(bp) #define XFS_BUF_PSEMA(bp,x) xfs_buf_lock(bp) -#define XFS_BUF_FINISH_IOWAIT(bp) complete(&bp->b_iowait); +#define XFS_BUF_V_IODONESEMA(bp) up(&bp->b_iodonesema); #define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target)) #define XFS_BUF_TARGET(bp) ((bp)->b_target) diff --git a/trunk/fs/xfs/linux-2.6/xfs_export.c b/trunk/fs/xfs/linux-2.6/xfs_export.c index 24fd598af846..987fe84f7b13 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_export.c +++ b/trunk/fs/xfs/linux-2.6/xfs_export.c @@ -139,7 +139,7 @@ xfs_nfs_get_inode( } xfs_iunlock(ip, XFS_ILOCK_SHARED); - return VFS_I(ip); + return ip->i_vnode; } STATIC struct dentry * @@ -167,7 +167,7 @@ xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, if (!inode) return NULL; if (IS_ERR(inode)) - return ERR_CAST(inode); + return ERR_PTR(PTR_ERR(inode)); result = d_alloc_anon(inode); if (!result) { iput(inode); @@ -198,7 +198,7 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, if (!inode) return NULL; if (IS_ERR(inode)) - return ERR_CAST(inode); + return ERR_PTR(PTR_ERR(inode)); result = d_alloc_anon(inode); if (!result) { iput(inode); @@ -219,9 +219,9 @@ xfs_fs_get_parent( if (unlikely(error)) return ERR_PTR(-error); - parent = d_alloc_anon(VFS_I(cip)); + parent = d_alloc_anon(cip->i_vnode); if (unlikely(!parent)) { - iput(VFS_I(cip)); + iput(cip->i_vnode); return ERR_PTR(-ENOMEM); } return parent; diff --git a/trunk/fs/xfs/linux-2.6/xfs_fs_subr.c b/trunk/fs/xfs/linux-2.6/xfs_fs_subr.c index 36caa6d957df..1eefe61f0e10 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/trunk/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -31,7 +31,7 @@ xfs_tosspages( xfs_off_t last, int fiopt) { - struct address_space *mapping = VFS_I(ip)->i_mapping; + struct address_space *mapping = ip->i_vnode->i_mapping; if (mapping->nrpages) truncate_inode_pages(mapping, first); @@ -44,7 +44,7 @@ xfs_flushinval_pages( xfs_off_t last, int fiopt) { - struct address_space *mapping = VFS_I(ip)->i_mapping; + struct address_space *mapping = ip->i_vnode->i_mapping; int ret = 0; if (mapping->nrpages) { @@ -64,7 +64,7 @@ xfs_flush_pages( uint64_t flags, int fiopt) { - struct address_space *mapping = VFS_I(ip)->i_mapping; + struct address_space *mapping = ip->i_vnode->i_mapping; int ret = 0; int ret2; diff --git a/trunk/fs/xfs/linux-2.6/xfs_ioctl.c b/trunk/fs/xfs/linux-2.6/xfs_ioctl.c index 48799ba7e3e6..acb978d9d085 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/trunk/fs/xfs/linux-2.6/xfs_ioctl.c @@ -245,7 +245,7 @@ xfs_vget_fsop_handlereq( xfs_iunlock(ip, XFS_ILOCK_SHARED); - *inode = VFS_I(ip); + *inode = XFS_ITOV(ip); return 0; } @@ -927,7 +927,7 @@ STATIC void xfs_diflags_to_linux( struct xfs_inode *ip) { - struct inode *inode = VFS_I(ip); + struct inode *inode = XFS_ITOV(ip); unsigned int xflags = xfs_ip2xflags(ip); if (xflags & XFS_XFLAG_IMMUTABLE) diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.c b/trunk/fs/xfs/linux-2.6/xfs_iops.c index 91bcd979242c..e88f51028086 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.c @@ -62,7 +62,7 @@ void xfs_synchronize_atime( xfs_inode_t *ip) { - struct inode *inode = VFS_I(ip); + struct inode *inode = ip->i_vnode; if (inode) { ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; @@ -79,7 +79,7 @@ void xfs_mark_inode_dirty_sync( xfs_inode_t *ip) { - struct inode *inode = VFS_I(ip); + struct inode *inode = ip->i_vnode; if (inode) mark_inode_dirty_sync(inode); @@ -89,31 +89,36 @@ xfs_mark_inode_dirty_sync( * Change the requested timestamp in the given inode. * We don't lock across timestamp updates, and we don't log them but * we do record the fact that there is dirty information in core. + * + * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG + * with XFS_ICHGTIME_ACC to be sure that access time + * update will take. Calling first with XFS_ICHGTIME_ACC + * and then XFS_ICHGTIME_MOD may fail to modify the access + * timestamp if the filesystem is mounted noacctm. */ void xfs_ichgtime( xfs_inode_t *ip, int flags) { - struct inode *inode = VFS_I(ip); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); timespec_t tv; - int sync_it = 0; - - tv = current_fs_time(inode->i_sb); - if ((flags & XFS_ICHGTIME_MOD) && - !timespec_equal(&inode->i_mtime, &tv)) { + nanotime(&tv); + if (flags & XFS_ICHGTIME_MOD) { inode->i_mtime = tv; ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; - sync_it = 1; } - if ((flags & XFS_ICHGTIME_CHG) && - !timespec_equal(&inode->i_ctime, &tv)) { + if (flags & XFS_ICHGTIME_ACC) { + inode->i_atime = tv; + ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; + ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; + } + if (flags & XFS_ICHGTIME_CHG) { inode->i_ctime = tv; ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; - sync_it = 1; } /* @@ -125,11 +130,55 @@ xfs_ichgtime( * ensure that the compiler does not reorder the update * of i_update_core above the timestamp updates above. */ - if (sync_it) { - SYNCHRONIZE(); - ip->i_update_core = 1; + SYNCHRONIZE(); + ip->i_update_core = 1; + if (!(inode->i_state & I_NEW)) mark_inode_dirty_sync(inode); +} + +/* + * Variant on the above which avoids querying the system clock + * in situations where we know the Linux inode timestamps have + * just been updated (and so we can update our inode cheaply). + */ +void +xfs_ichgtime_fast( + xfs_inode_t *ip, + struct inode *inode, + int flags) +{ + timespec_t *tvp; + + /* + * Atime updates for read() & friends are handled lazily now, and + * explicit updates must go through xfs_ichgtime() + */ + ASSERT((flags & XFS_ICHGTIME_ACC) == 0); + + if (flags & XFS_ICHGTIME_MOD) { + tvp = &inode->i_mtime; + ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; + ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; } + if (flags & XFS_ICHGTIME_CHG) { + tvp = &inode->i_ctime; + ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; + ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec; + } + + /* + * We update the i_update_core field _after_ changing + * the timestamps in order to coordinate properly with + * xfs_iflush() so that we don't lose timestamp updates. + * This keeps us from having to hold the inode lock + * while doing this. We use the SYNCHRONIZE macro to + * ensure that the compiler does not reorder the update + * of i_update_core above the timestamp updates above. + */ + SYNCHRONIZE(); + ip->i_update_core = 1; + if (!(inode->i_state & I_NEW)) + mark_inode_dirty_sync(inode); } /* @@ -250,7 +299,7 @@ xfs_vn_mknod( if (unlikely(error)) goto out_free_acl; - inode = VFS_I(ip); + inode = ip->i_vnode; error = xfs_init_security(inode, dir); if (unlikely(error)) @@ -317,7 +366,7 @@ xfs_vn_lookup( return NULL; } - return d_splice_alias(VFS_I(cip), dentry); + return d_splice_alias(cip->i_vnode, dentry); } STATIC struct dentry * @@ -350,12 +399,12 @@ xfs_vn_ci_lookup( /* if exact match, just splice and exit */ if (!ci_name.name) - return d_splice_alias(VFS_I(ip), dentry); + return d_splice_alias(ip->i_vnode, dentry); /* else case-insensitive match... */ dname.name = ci_name.name; dname.len = ci_name.len; - dentry = d_add_ci(VFS_I(ip), dentry, &dname); + dentry = d_add_ci(ip->i_vnode, dentry, &dname); kmem_free(ci_name.name); return dentry; } @@ -429,7 +478,7 @@ xfs_vn_symlink( if (unlikely(error)) goto out; - inode = VFS_I(cip); + inode = cip->i_vnode; error = xfs_init_security(inode, dir); if (unlikely(error)) @@ -661,7 +710,7 @@ xfs_vn_fallocate( return error; } -static const struct inode_operations xfs_inode_operations = { +const struct inode_operations xfs_inode_operations = { .permission = xfs_vn_permission, .truncate = xfs_vn_truncate, .getattr = xfs_vn_getattr, @@ -673,7 +722,7 @@ static const struct inode_operations xfs_inode_operations = { .fallocate = xfs_vn_fallocate, }; -static const struct inode_operations xfs_dir_inode_operations = { +const struct inode_operations xfs_dir_inode_operations = { .create = xfs_vn_create, .lookup = xfs_vn_lookup, .link = xfs_vn_link, @@ -698,7 +747,7 @@ static const struct inode_operations xfs_dir_inode_operations = { .listxattr = xfs_vn_listxattr, }; -static const struct inode_operations xfs_dir_ci_inode_operations = { +const struct inode_operations xfs_dir_ci_inode_operations = { .create = xfs_vn_create, .lookup = xfs_vn_ci_lookup, .link = xfs_vn_link, @@ -723,7 +772,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { .listxattr = xfs_vn_listxattr, }; -static const struct inode_operations xfs_symlink_inode_operations = { +const struct inode_operations xfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = xfs_vn_follow_link, .put_link = xfs_vn_put_link, @@ -735,98 +784,3 @@ static const struct inode_operations xfs_symlink_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, }; - -STATIC void -xfs_diflags_to_iflags( - struct inode *inode, - struct xfs_inode *ip) -{ - if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; - if (ip->i_d.di_flags & XFS_DIFLAG_SYNC) - inode->i_flags |= S_SYNC; - else - inode->i_flags &= ~S_SYNC; - if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME) - inode->i_flags |= S_NOATIME; - else - inode->i_flags &= ~S_NOATIME; -} - -/* - * Initialize the Linux inode, set up the operation vectors and - * unlock the inode. - * - * When reading existing inodes from disk this is called directly - * from xfs_iget, when creating a new inode it is called from - * xfs_ialloc after setting up the inode. - */ -void -xfs_setup_inode( - struct xfs_inode *ip) -{ - struct inode *inode = ip->i_vnode; - - inode->i_mode = ip->i_d.di_mode; - inode->i_nlink = ip->i_d.di_nlink; - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; - - switch (inode->i_mode & S_IFMT) { - case S_IFBLK: - case S_IFCHR: - inode->i_rdev = - MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, - sysv_minor(ip->i_df.if_u2.if_rdev)); - break; - default: - inode->i_rdev = 0; - break; - } - - inode->i_generation = ip->i_d.di_gen; - i_size_write(inode, ip->i_d.di_size); - inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec; - inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec; - inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec; - inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; - inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; - inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; - xfs_diflags_to_iflags(inode, ip); - xfs_iflags_clear(ip, XFS_IMODIFIED); - - switch (inode->i_mode & S_IFMT) { - case S_IFREG: - inode->i_op = &xfs_inode_operations; - inode->i_fop = &xfs_file_operations; - inode->i_mapping->a_ops = &xfs_address_space_operations; - break; - case S_IFDIR: - if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) - inode->i_op = &xfs_dir_ci_inode_operations; - else - inode->i_op = &xfs_dir_inode_operations; - inode->i_fop = &xfs_dir_file_operations; - break; - case S_IFLNK: - inode->i_op = &xfs_symlink_inode_operations; - if (!(ip->i_df.if_flags & XFS_IFINLINE)) - inode->i_mapping->a_ops = &xfs_address_space_operations; - break; - default: - inode->i_op = &xfs_inode_operations; - init_special_inode(inode, inode->i_mode, inode->i_rdev); - break; - } - - xfs_iflags_clear(ip, XFS_INEW); - barrier(); - - unlock_new_inode(inode); -} diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.h b/trunk/fs/xfs/linux-2.6/xfs_iops.h index 8b1a1e31dc21..d97ba934a2ac 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.h +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.h @@ -18,7 +18,10 @@ #ifndef __XFS_IOPS_H__ #define __XFS_IOPS_H__ -struct xfs_inode; +extern const struct inode_operations xfs_inode_operations; +extern const struct inode_operations xfs_dir_inode_operations; +extern const struct inode_operations xfs_dir_ci_inode_operations; +extern const struct inode_operations xfs_symlink_inode_operations; extern const struct file_operations xfs_file_operations; extern const struct file_operations xfs_dir_file_operations; @@ -26,6 +29,14 @@ extern const struct file_operations xfs_invis_file_operations; extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); -extern void xfs_setup_inode(struct xfs_inode *); +struct xfs_inode; +extern void xfs_ichgtime(struct xfs_inode *, int); +extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int); + +#define xfs_vtoi(vp) \ + ((struct xfs_inode *)vn_to_inode(vp)->i_private) + +#define XFS_I(inode) \ + ((struct xfs_inode *)(inode)->i_private) #endif /* __XFS_IOPS_H__ */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_linux.h b/trunk/fs/xfs/linux-2.6/xfs_linux.h index 3b7c4ff48ba0..4d45d9351a6c 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_linux.h +++ b/trunk/fs/xfs/linux-2.6/xfs_linux.h @@ -45,13 +45,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -180,7 +180,7 @@ #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) #define xfs_stack_trace() dump_stack() #define xfs_itruncate_data(ip, off) \ - (-vmtruncate(VFS_I(ip), (off))) + (-vmtruncate(vn_to_inode(XFS_ITOV(ip)), (off))) /* Move the kernel do_div definition off to one side */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_lrw.c b/trunk/fs/xfs/linux-2.6/xfs_lrw.c index 1957e5357d04..82333b3e118e 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_lrw.c +++ b/trunk/fs/xfs/linux-2.6/xfs_lrw.c @@ -137,7 +137,7 @@ xfs_iozero( struct address_space *mapping; int status; - mapping = VFS_I(ip)->i_mapping; + mapping = ip->i_vnode->i_mapping; do { unsigned offset, bytes; void *fsdata; @@ -674,7 +674,9 @@ xfs_write( */ if (likely(!(ioflags & IO_INVIS) && !mnt_want_write(file->f_path.mnt))) { - xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + file_update_time(file); + xfs_ichgtime_fast(xip, inode, + XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); mnt_drop_write(file->f_path.mnt); } diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 73c65f19e549..30ae96397e31 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -581,6 +581,118 @@ xfs_max_file_offset( return (((__uint64_t)pagefactor) << bitshift) - 1; } +STATIC_INLINE void +xfs_set_inodeops( + struct inode *inode) +{ + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + inode->i_op = &xfs_inode_operations; + inode->i_fop = &xfs_file_operations; + inode->i_mapping->a_ops = &xfs_address_space_operations; + break; + case S_IFDIR: + if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) + inode->i_op = &xfs_dir_ci_inode_operations; + else + inode->i_op = &xfs_dir_inode_operations; + inode->i_fop = &xfs_dir_file_operations; + break; + case S_IFLNK: + inode->i_op = &xfs_symlink_inode_operations; + if (!(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE)) + inode->i_mapping->a_ops = &xfs_address_space_operations; + break; + default: + inode->i_op = &xfs_inode_operations; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + break; + } +} + +STATIC_INLINE void +xfs_revalidate_inode( + xfs_mount_t *mp, + bhv_vnode_t *vp, + xfs_inode_t *ip) +{ + struct inode *inode = vn_to_inode(vp); + + inode->i_mode = ip->i_d.di_mode; + inode->i_nlink = ip->i_d.di_nlink; + inode->i_uid = ip->i_d.di_uid; + inode->i_gid = ip->i_d.di_gid; + + switch (inode->i_mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + inode->i_rdev = + MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, + sysv_minor(ip->i_df.if_u2.if_rdev)); + break; + default: + inode->i_rdev = 0; + break; + } + + inode->i_generation = ip->i_d.di_gen; + i_size_write(inode, ip->i_d.di_size); + inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec; + inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec; + inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec; + inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; + inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; + inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; + if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) + inode->i_flags |= S_IMMUTABLE; + else + inode->i_flags &= ~S_IMMUTABLE; + if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) + inode->i_flags |= S_APPEND; + else + inode->i_flags &= ~S_APPEND; + if (ip->i_d.di_flags & XFS_DIFLAG_SYNC) + inode->i_flags |= S_SYNC; + else + inode->i_flags &= ~S_SYNC; + if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME) + inode->i_flags |= S_NOATIME; + else + inode->i_flags &= ~S_NOATIME; + xfs_iflags_clear(ip, XFS_IMODIFIED); +} + +void +xfs_initialize_vnode( + struct xfs_mount *mp, + bhv_vnode_t *vp, + struct xfs_inode *ip) +{ + struct inode *inode = vn_to_inode(vp); + + if (!ip->i_vnode) { + ip->i_vnode = vp; + inode->i_private = ip; + } + + /* + * We need to set the ops vectors, and unlock the inode, but if + * we have been called during the new inode create process, it is + * too early to fill in the Linux inode. We will get called a + * second time once the inode is properly set up, and then we can + * finish our work. + */ + if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) { + xfs_revalidate_inode(mp, vp, ip); + xfs_set_inodeops(inode); + + xfs_iflags_clear(ip, XFS_INEW); + barrier(); + + unlock_new_inode(inode); + } +} + int xfs_blkdev_get( xfs_mount_t *mp, @@ -870,21 +982,26 @@ STATIC struct inode * xfs_fs_alloc_inode( struct super_block *sb) { - return kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); + bhv_vnode_t *vp; + + vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); + if (unlikely(!vp)) + return NULL; + return vn_to_inode(vp); } STATIC void xfs_fs_destroy_inode( struct inode *inode) { - kmem_zone_free(xfs_vnode_zone, inode); + kmem_zone_free(xfs_vnode_zone, vn_from_inode(inode)); } STATIC void xfs_fs_inode_init_once( void *vnode) { - inode_init_once((struct inode *)vnode); + inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); } /* @@ -989,7 +1106,7 @@ void xfs_flush_inode( xfs_inode_t *ip) { - struct inode *inode = VFS_I(ip); + struct inode *inode = ip->i_vnode; igrab(inode); xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); @@ -1014,7 +1131,7 @@ void xfs_flush_device( xfs_inode_t *ip) { - struct inode *inode = VFS_I(ip); + struct inode *inode = vn_to_inode(XFS_ITOV(ip)); igrab(inode); xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); @@ -1083,15 +1200,6 @@ xfssyncd( return 0; } -STATIC void -xfs_free_fsname( - struct xfs_mount *mp) -{ - kfree(mp->m_fsname); - kfree(mp->m_rtname); - kfree(mp->m_logname); -} - STATIC void xfs_fs_put_super( struct super_block *sb) @@ -1131,6 +1239,8 @@ xfs_fs_put_super( error = xfs_unmount_flush(mp, 0); WARN_ON(error); + IRELE(rip); + /* * If we're forcing a shutdown, typically because of a media error, * we want to make sure we invalidate dirty pages that belong to @@ -1147,12 +1257,10 @@ xfs_fs_put_super( } xfs_unmountfs(mp); - xfs_freesb(mp); xfs_icsb_destroy_counters(mp); xfs_close_devices(mp); xfs_qmops_put(mp); xfs_dmops_put(mp); - xfs_free_fsname(mp); kfree(mp); } @@ -1409,8 +1517,6 @@ xfs_start_flags( struct xfs_mount_args *ap, struct xfs_mount *mp) { - int error; - /* Values are in BBs */ if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) { /* @@ -1443,27 +1549,17 @@ xfs_start_flags( ap->logbufsize); return XFS_ERROR(EINVAL); } - - error = ENOMEM; - mp->m_logbsize = ap->logbufsize; mp->m_fsname_len = strlen(ap->fsname) + 1; - - mp->m_fsname = kstrdup(ap->fsname, GFP_KERNEL); - if (!mp->m_fsname) - goto out; - + mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP); + strcpy(mp->m_fsname, ap->fsname); if (ap->rtname[0]) { - mp->m_rtname = kstrdup(ap->rtname, GFP_KERNEL); - if (!mp->m_rtname) - goto out_free_fsname; - + mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP); + strcpy(mp->m_rtname, ap->rtname); } - if (ap->logname[0]) { - mp->m_logname = kstrdup(ap->logname, GFP_KERNEL); - if (!mp->m_logname) - goto out_free_rtname; + mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP); + strcpy(mp->m_logname, ap->logname); } if (ap->flags & XFSMNT_WSYNC) @@ -1536,14 +1632,6 @@ xfs_start_flags( if (ap->flags & XFSMNT_DMAPI) mp->m_flags |= XFS_MOUNT_DMAPI; return 0; - - - out_free_rtname: - kfree(mp->m_rtname); - out_free_fsname: - kfree(mp->m_fsname); - out: - return error; } /* @@ -1704,10 +1792,10 @@ xfs_fs_fill_super( */ error = xfs_start_flags(args, mp); if (error) - goto out_free_fsname; + goto out_destroy_counters; error = xfs_readsb(mp, flags); if (error) - goto out_free_fsname; + goto out_destroy_counters; error = xfs_finish_flags(args, mp); if (error) goto out_free_sb; @@ -1723,7 +1811,7 @@ xfs_fs_fill_super( if (error) goto out_free_sb; - error = xfs_mountfs(mp); + error = xfs_mountfs(mp, flags); if (error) goto out_filestream_unmount; @@ -1737,7 +1825,7 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); - root = igrab(VFS_I(mp->m_rootip)); + root = igrab(mp->m_rootip->i_vnode); if (!root) { error = ENOENT; goto fail_unmount; @@ -1769,8 +1857,7 @@ xfs_fs_fill_super( xfs_filestream_unmount(mp); out_free_sb: xfs_freesb(mp); - out_free_fsname: - xfs_free_fsname(mp); + out_destroy_counters: xfs_icsb_destroy_counters(mp); xfs_close_devices(mp); out_put_qmops: @@ -1803,8 +1890,10 @@ xfs_fs_fill_super( error = xfs_unmount_flush(mp, 0); WARN_ON(error); + IRELE(mp->m_rootip); + xfs_unmountfs(mp); - goto out_free_sb; + goto out_destroy_counters; } STATIC int @@ -1925,7 +2014,7 @@ xfs_free_trace_bufs(void) STATIC int __init xfs_init_zones(void) { - xfs_vnode_zone = kmem_zone_init_flags(sizeof(struct inode), "xfs_vnode", + xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode", KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, xfs_fs_inode_init_once); diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.h b/trunk/fs/xfs/linux-2.6/xfs_super.h index fe2ef4e6a0f9..b7d13da01bd6 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.h +++ b/trunk/fs/xfs/linux-2.6/xfs_super.h @@ -101,6 +101,9 @@ struct block_device; extern __uint64_t xfs_max_file_offset(unsigned int); +extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp, + struct xfs_inode *ip); + extern void xfs_flush_inode(struct xfs_inode *); extern void xfs_flush_device(struct xfs_inode *); diff --git a/trunk/fs/xfs/linux-2.6/xfs_vnode.c b/trunk/fs/xfs/linux-2.6/xfs_vnode.c index b52528bbbfff..25488b6d9881 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_vnode.c +++ b/trunk/fs/xfs/linux-2.6/xfs_vnode.c @@ -33,7 +33,7 @@ /* - * Dedicated vnode inactive/reclaim sync wait queues. + * Dedicated vnode inactive/reclaim sync semaphores. * Prime number of hash buckets since address is used as the key. */ #define NVSYNC 37 @@ -82,6 +82,24 @@ vn_ioerror( xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l); } + +/* + * Add a reference to a referenced vnode. + */ +bhv_vnode_t * +vn_hold( + bhv_vnode_t *vp) +{ + struct inode *inode; + + XFS_STATS_INC(vn_hold); + + inode = igrab(vn_to_inode(vp)); + ASSERT(inode); + + return vp; +} + #ifdef XFS_INODE_TRACE /* @@ -90,7 +108,7 @@ vn_ioerror( */ static inline int xfs_icount(struct xfs_inode *ip) { - struct inode *vp = VFS_I(ip); + bhv_vnode_t *vp = XFS_ITOV_NULL(ip); if (vp) return vn_count(vp); diff --git a/trunk/fs/xfs/linux-2.6/xfs_vnode.h b/trunk/fs/xfs/linux-2.6/xfs_vnode.h index 683ce16210ff..41ca2cec5d31 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_vnode.h +++ b/trunk/fs/xfs/linux-2.6/xfs_vnode.h @@ -22,6 +22,20 @@ struct file; struct xfs_iomap; struct attrlist_cursor_kern; +typedef struct inode bhv_vnode_t; + +/* + * Vnode to Linux inode mapping. + */ +static inline bhv_vnode_t *vn_from_inode(struct inode *inode) +{ + return inode; +} +static inline struct inode *vn_to_inode(bhv_vnode_t *vnode) +{ + return vnode; +} + /* * Return values for xfs_inactive. A return value of * VN_INACTIVE_NOCACHE implies that the file system behavior @@ -62,52 +76,57 @@ extern void vn_iowait(struct xfs_inode *ip); extern void vn_iowake(struct xfs_inode *ip); extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l); -static inline int vn_count(struct inode *vp) +static inline int vn_count(bhv_vnode_t *vp) { - return atomic_read(&vp->i_count); + return atomic_read(&vn_to_inode(vp)->i_count); } -#define IHOLD(ip) \ -do { \ - ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \ - atomic_inc(&(VFS_I(ip)->i_count)); \ - xfs_itrace_hold((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ -} while (0) +/* + * Vnode reference counting functions (and macros for compatibility). + */ +extern bhv_vnode_t *vn_hold(bhv_vnode_t *); -#define IRELE(ip) \ -do { \ - xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ - iput(VFS_I(ip)); \ -} while (0) +#if defined(XFS_INODE_TRACE) +#define VN_HOLD(vp) \ + ((void)vn_hold(vp), \ + xfs_itrace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address)) +#define VN_RELE(vp) \ + (xfs_itrace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ + iput(vn_to_inode(vp))) +#else +#define VN_HOLD(vp) ((void)vn_hold(vp)) +#define VN_RELE(vp) (iput(vn_to_inode(vp))) +#endif -static inline struct inode *vn_grab(struct inode *vp) +static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) { - return igrab(vp); + struct inode *inode = igrab(vn_to_inode(vp)); + return inode ? vn_from_inode(inode) : NULL; } /* * Dealing with bad inodes */ -static inline int VN_BAD(struct inode *vp) +static inline int VN_BAD(bhv_vnode_t *vp) { - return is_bad_inode(vp); + return is_bad_inode(vn_to_inode(vp)); } /* * Extracting atime values in various formats */ -static inline void vn_atime_to_bstime(struct inode *vp, xfs_bstime_t *bs_atime) +static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime) { bs_atime->tv_sec = vp->i_atime.tv_sec; bs_atime->tv_nsec = vp->i_atime.tv_nsec; } -static inline void vn_atime_to_timespec(struct inode *vp, struct timespec *ts) +static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts) { *ts = vp->i_atime; } -static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt) +static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) { *tt = vp->i_atime.tv_sec; } @@ -115,9 +134,9 @@ static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt) /* * Some useful predicates. */ -#define VN_MAPPED(vp) mapping_mapped(vp->i_mapping) -#define VN_CACHED(vp) (vp->i_mapping->nrpages) -#define VN_DIRTY(vp) mapping_tagged(vp->i_mapping, \ +#define VN_MAPPED(vp) mapping_mapped(vn_to_inode(vp)->i_mapping) +#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) +#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ PAGECACHE_TAG_DIRTY) diff --git a/trunk/fs/xfs/quota/xfs_dquot.c b/trunk/fs/xfs/quota/xfs_dquot.c index f2705f2fd43c..fc9f3fb39b7b 100644 --- a/trunk/fs/xfs/quota/xfs_dquot.c +++ b/trunk/fs/xfs/quota/xfs_dquot.c @@ -101,18 +101,11 @@ xfs_qm_dqinit( if (brandnewdquot) { dqp->dq_flnext = dqp->dq_flprev = dqp; mutex_init(&dqp->q_qlock); + initnsema(&dqp->q_flock, 1, "fdq"); sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); - /* - * Because we want to use a counting completion, complete - * the flush completion once to allow a single access to - * the flush completion without blocking. - */ - init_completion(&dqp->q_flush); - complete(&dqp->q_flush); - #ifdef XFS_DQUOT_TRACE - dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_NOFS); + dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP); xfs_dqtrace_entry(dqp, "DQINIT"); #endif } else { @@ -157,6 +150,7 @@ xfs_qm_dqdestroy( ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp)); mutex_destroy(&dqp->q_qlock); + freesema(&dqp->q_flock); sv_destroy(&dqp->q_pinwait); #ifdef XFS_DQUOT_TRACE @@ -437,7 +431,7 @@ xfs_qm_dqalloc( * when it unlocks the inode. Since we want to keep the quota * inode around, we bump the vnode ref count now. */ - IHOLD(quotip); + VN_HOLD(XFS_ITOV(quotip)); xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); nmaps = 1; @@ -1217,7 +1211,7 @@ xfs_qm_dqflush( int error; ASSERT(XFS_DQ_IS_LOCKED(dqp)); - ASSERT(!completion_done(&dqp->q_flush)); + ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); xfs_dqtrace_entry(dqp, "DQFLUSH"); /* @@ -1354,18 +1348,34 @@ xfs_qm_dqflush_done( xfs_dqfunlock(dqp); } + +int +xfs_qm_dqflock_nowait( + xfs_dquot_t *dqp) +{ + int locked; + + locked = cpsema(&((dqp)->q_flock)); + + /* XXX ifdef these out */ + if (locked) + (dqp)->dq_flags |= XFS_DQ_FLOCKED; + return (locked); +} + + int xfs_qm_dqlock_nowait( xfs_dquot_t *dqp) { - return mutex_trylock(&dqp->q_qlock); + return (mutex_trylock(&((dqp)->q_qlock))); } void xfs_dqlock( xfs_dquot_t *dqp) { - mutex_lock(&dqp->q_qlock); + mutex_lock(&(dqp->q_qlock)); } void @@ -1458,7 +1468,7 @@ xfs_qm_dqpurge( * if we're turning off quotas. Basically, we need this flush * lock, and are willing to block on it. */ - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { /* * Block on the flush lock after nudging dquot buffer, * if it is incore. diff --git a/trunk/fs/xfs/quota/xfs_dquot.h b/trunk/fs/xfs/quota/xfs_dquot.h index 8958d0faf8d3..f7393bba4e95 100644 --- a/trunk/fs/xfs/quota/xfs_dquot.h +++ b/trunk/fs/xfs/quota/xfs_dquot.h @@ -82,7 +82,7 @@ typedef struct xfs_dquot { xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ mutex_t q_qlock; /* quota lock */ - struct completion q_flush; /* flush completion queue */ + sema_t q_flock; /* flush lock */ uint q_pincount; /* pin count for this dquot */ sv_t q_pinwait; /* sync var for pinning */ #ifdef XFS_DQUOT_TRACE @@ -113,25 +113,17 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) /* - * Manage the q_flush completion queue embedded in the dquot. This completion - * queue synchronizes processes attempting to flush the in-core dquot back to - * disk. + * The following three routines simply manage the q_flock + * semaphore embedded in the dquot. This semaphore synchronizes + * processes attempting to flush the in-core dquot back to disk. */ -static inline void xfs_dqflock(xfs_dquot_t *dqp) -{ - wait_for_completion(&dqp->q_flush); -} - -static inline int xfs_dqflock_nowait(xfs_dquot_t *dqp) -{ - return try_wait_for_completion(&dqp->q_flush); -} - -static inline void xfs_dqfunlock(xfs_dquot_t *dqp) -{ - complete(&dqp->q_flush); -} +#define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ + (dqp)->dq_flags |= XFS_DQ_FLOCKED; } +#define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ + vsema(&((dqp)->q_flock)); \ + (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } +#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) @@ -175,6 +167,7 @@ extern int xfs_qm_dqflush(xfs_dquot_t *, uint); extern int xfs_qm_dqpurge(xfs_dquot_t *); extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); +extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, xfs_disk_dquot_t *); diff --git a/trunk/fs/xfs/quota/xfs_dquot_item.c b/trunk/fs/xfs/quota/xfs_dquot_item.c index f028644caa5e..08d2fc89e6a1 100644 --- a/trunk/fs/xfs/quota/xfs_dquot_item.c +++ b/trunk/fs/xfs/quota/xfs_dquot_item.c @@ -151,7 +151,7 @@ xfs_qm_dquot_logitem_push( dqp = logitem->qli_dquot; ASSERT(XFS_DQ_IS_LOCKED(dqp)); - ASSERT(!completion_done(&dqp->q_flush)); + ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); /* * Since we were able to lock the dquot's flush lock and @@ -245,7 +245,7 @@ xfs_qm_dquot_logitem_pushbuf( * inode flush completed and the inode was taken off the AIL. * So, just get out. */ - if (completion_done(&dqp->q_flush) || + if (!issemalocked(&(dqp->q_flock)) || ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); @@ -258,7 +258,7 @@ xfs_qm_dquot_logitem_pushbuf( if (bp != NULL) { if (XFS_BUF_ISDELAYWRITE(bp)) { dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && - !completion_done(&dqp->q_flush)); + issemalocked(&(dqp->q_flock))); qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); @@ -317,7 +317,7 @@ xfs_qm_dquot_logitem_trylock( return (XFS_ITEM_LOCKED); retval = XFS_ITEM_SUCCESS; - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { /* * The dquot is already being flushed. It may have been * flushed delayed write, however, and we don't want to diff --git a/trunk/fs/xfs/quota/xfs_qm.c b/trunk/fs/xfs/quota/xfs_qm.c index df0ffef9775a..021934a3d456 100644 --- a/trunk/fs/xfs/quota/xfs_qm.c +++ b/trunk/fs/xfs/quota/xfs_qm.c @@ -310,7 +310,8 @@ xfs_qm_unmount_quotadestroy( */ void xfs_qm_mount_quotas( - xfs_mount_t *mp) + xfs_mount_t *mp, + int mfsi_flags) { int error = 0; uint sbf; @@ -345,7 +346,8 @@ xfs_qm_mount_quotas( /* * If any of the quotas are not consistent, do a quotacheck. */ - if (XFS_QM_NEED_QUOTACHECK(mp)) { + if (XFS_QM_NEED_QUOTACHECK(mp) && + !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) { error = xfs_qm_quotacheck(mp); if (error) { /* Quotacheck failed and disabled quotas. */ @@ -482,7 +484,7 @@ xfs_qm_dqflush_all( xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY"); /* XXX a sentinel would be better */ recl = XFS_QI_MPLRECLAIMS(mp); - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { /* * If we can't grab the flush lock then check * to see if the dquot has been flushed delayed @@ -1060,7 +1062,7 @@ xfs_qm_sync( /* XXX a sentinel would be better */ recl = XFS_QI_MPLRECLAIMS(mp); - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { if (nowait) { xfs_dqunlock(dqp); continue; @@ -2077,7 +2079,7 @@ xfs_qm_shake_freelist( * Try to grab the flush lock. If this dquot is in the process of * getting flushed to disk, we don't want to reclaim it. */ - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { xfs_dqunlock(dqp); dqp = dqp->dq_flnext; continue; @@ -2255,7 +2257,7 @@ xfs_qm_dqreclaim_one(void) * Try to grab the flush lock. If this dquot is in the process of * getting flushed to disk, we don't want to reclaim it. */ - if (!xfs_dqflock_nowait(dqp)) { + if (! xfs_qm_dqflock_nowait(dqp)) { xfs_dqunlock(dqp); continue; } diff --git a/trunk/fs/xfs/quota/xfs_qm.h b/trunk/fs/xfs/quota/xfs_qm.h index 44f25349e478..cd2300e374af 100644 --- a/trunk/fs/xfs/quota/xfs_qm.h +++ b/trunk/fs/xfs/quota/xfs_qm.h @@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct { #define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--) extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); -extern void xfs_qm_mount_quotas(xfs_mount_t *); +extern void xfs_qm_mount_quotas(xfs_mount_t *, int); extern int xfs_qm_quotacheck(xfs_mount_t *); extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); extern int xfs_qm_unmount_quotas(xfs_mount_t *); diff --git a/trunk/fs/xfs/quota/xfs_qm_bhv.c b/trunk/fs/xfs/quota/xfs_qm_bhv.c index eea2e60b456b..f4f6c4c861d7 100644 --- a/trunk/fs/xfs/quota/xfs_qm_bhv.c +++ b/trunk/fs/xfs/quota/xfs_qm_bhv.c @@ -162,7 +162,7 @@ xfs_qm_newmount( * mounting, and get on with the boring life * without disk quotas. */ - xfs_qm_mount_quotas(mp); + xfs_qm_mount_quotas(mp, 0); } else { /* * Clear the quota flags, but remember them. This @@ -184,12 +184,13 @@ STATIC int xfs_qm_endmount( xfs_mount_t *mp, uint needquotamount, - uint quotaflags) + uint quotaflags, + int mfsi_flags) { if (needquotamount) { ASSERT(mp->m_qflags == 0); mp->m_qflags = quotaflags; - xfs_qm_mount_quotas(mp); + xfs_qm_mount_quotas(mp, mfsi_flags); } #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY) diff --git a/trunk/fs/xfs/quota/xfs_qm_syscalls.c b/trunk/fs/xfs/quota/xfs_qm_syscalls.c index 1a3b803dfa55..adfb8723f65a 100644 --- a/trunk/fs/xfs/quota/xfs_qm_syscalls.c +++ b/trunk/fs/xfs/quota/xfs_qm_syscalls.c @@ -1034,7 +1034,7 @@ xfs_qm_dqrele_all_inodes( { xfs_inode_t *ip, *topino; uint ireclaims; - struct inode *vp; + bhv_vnode_t *vp; boolean_t vnode_refd; ASSERT(mp->m_quotainfo); @@ -1059,7 +1059,7 @@ xfs_qm_dqrele_all_inodes( ip = ip->i_mnext; continue; } - vp = VFS_I(ip); + vp = XFS_ITOV_NULL(ip); if (!vp) { ASSERT(ip->i_udquot == NULL); ASSERT(ip->i_gdquot == NULL); diff --git a/trunk/fs/xfs/xfs_acl.c b/trunk/fs/xfs/xfs_acl.c index b2f639a1416f..3e4648ad9cfc 100644 --- a/trunk/fs/xfs/xfs_acl.c +++ b/trunk/fs/xfs/xfs_acl.c @@ -37,15 +37,15 @@ #include #include -STATIC int xfs_acl_setmode(struct inode *, xfs_acl_t *, int *); +STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *); STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); STATIC void xfs_acl_get_endian(xfs_acl_t *); STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); STATIC int xfs_acl_invalid(xfs_acl_t *); STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); -STATIC void xfs_acl_get_attr(struct inode *, xfs_acl_t *, int, int, int *); -STATIC void xfs_acl_set_attr(struct inode *, xfs_acl_t *, int, int *); -STATIC int xfs_acl_allow_set(struct inode *, int); +STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *); +STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *); +STATIC int xfs_acl_allow_set(bhv_vnode_t *, int); kmem_zone_t *xfs_acl_zone; @@ -55,7 +55,7 @@ kmem_zone_t *xfs_acl_zone; */ int xfs_acl_vhasacl_access( - struct inode *vp) + bhv_vnode_t *vp) { int error; @@ -68,7 +68,7 @@ xfs_acl_vhasacl_access( */ int xfs_acl_vhasacl_default( - struct inode *vp) + bhv_vnode_t *vp) { int error; @@ -207,7 +207,7 @@ posix_acl_xfs_to_xattr( int xfs_acl_vget( - struct inode *vp, + bhv_vnode_t *vp, void *acl, size_t size, int kind) @@ -217,6 +217,7 @@ xfs_acl_vget( posix_acl_xattr_header *ext_acl = acl; int flags = 0; + VN_HOLD(vp); if(size) { if (!(_ACL_ALLOC(xfs_acl))) { error = ENOMEM; @@ -238,10 +239,11 @@ xfs_acl_vget( goto out; } if (kind == _ACL_TYPE_ACCESS) - xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, xfs_acl); + xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, xfs_acl); error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size); } out: + VN_RELE(vp); if(xfs_acl) _ACL_FREE(xfs_acl); return -error; @@ -249,26 +251,28 @@ xfs_acl_vget( int xfs_acl_vremove( - struct inode *vp, + bhv_vnode_t *vp, int kind) { int error; + VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); if (!error) { - error = xfs_attr_remove(XFS_I(vp), + error = xfs_attr_remove(xfs_vtoi(vp), kind == _ACL_TYPE_DEFAULT? SGI_ACL_DEFAULT: SGI_ACL_FILE, ATTR_ROOT); if (error == ENOATTR) error = 0; /* 'scool */ } + VN_RELE(vp); return -error; } int xfs_acl_vset( - struct inode *vp, + bhv_vnode_t *vp, void *acl, size_t size, int kind) @@ -294,6 +298,7 @@ xfs_acl_vset( return 0; } + VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); /* Incoming ACL exists, set file mode based on its value */ @@ -316,6 +321,7 @@ xfs_acl_vset( } out: + VN_RELE(vp); _ACL_FREE(xfs_acl); return -error; } @@ -357,7 +363,7 @@ xfs_acl_iaccess( STATIC int xfs_acl_allow_set( - struct inode *vp, + bhv_vnode_t *vp, int kind) { if (vp->i_flags & (S_IMMUTABLE|S_APPEND)) @@ -366,7 +372,7 @@ xfs_acl_allow_set( return ENOTDIR; if (vp->i_sb->s_flags & MS_RDONLY) return EROFS; - if (XFS_I(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER)) + if (xfs_vtoi(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER)) return EPERM; return 0; } @@ -560,7 +566,7 @@ xfs_acl_get_endian( */ STATIC void xfs_acl_get_attr( - struct inode *vp, + bhv_vnode_t *vp, xfs_acl_t *aclp, int kind, int flags, @@ -570,7 +576,7 @@ xfs_acl_get_attr( ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); flags |= ATTR_ROOT; - *error = xfs_attr_get(XFS_I(vp), + *error = xfs_attr_get(xfs_vtoi(vp), kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT, (char *)aclp, &len, flags); @@ -584,7 +590,7 @@ xfs_acl_get_attr( */ STATIC void xfs_acl_set_attr( - struct inode *vp, + bhv_vnode_t *vp, xfs_acl_t *aclp, int kind, int *error) @@ -609,7 +615,7 @@ xfs_acl_set_attr( INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); } INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); - *error = xfs_attr_set(XFS_I(vp), + *error = xfs_attr_set(xfs_vtoi(vp), kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, (char *)newacl, len, ATTR_ROOT); @@ -618,7 +624,7 @@ xfs_acl_set_attr( int xfs_acl_vtoacl( - struct inode *vp, + bhv_vnode_t *vp, xfs_acl_t *access_acl, xfs_acl_t *default_acl) { @@ -633,7 +639,7 @@ xfs_acl_vtoacl( if (error) access_acl->acl_cnt = XFS_ACL_NOT_PRESENT; else /* We have a good ACL and the file mode, synchronize. */ - xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, access_acl); + xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, access_acl); } if (default_acl) { @@ -650,7 +656,7 @@ xfs_acl_vtoacl( */ int xfs_acl_inherit( - struct inode *vp, + bhv_vnode_t *vp, mode_t mode, xfs_acl_t *pdaclp) { @@ -709,7 +715,7 @@ xfs_acl_inherit( */ STATIC int xfs_acl_setmode( - struct inode *vp, + bhv_vnode_t *vp, xfs_acl_t *acl, int *basicperms) { @@ -728,7 +734,7 @@ xfs_acl_setmode( * mode. The m:: bits take precedence over the g:: bits. */ iattr.ia_valid = ATTR_MODE; - iattr.ia_mode = XFS_I(vp)->i_d.di_mode; + iattr.ia_mode = xfs_vtoi(vp)->i_d.di_mode; iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); ap = acl->acl_entry; for (i = 0; i < acl->acl_cnt; ++i) { @@ -758,7 +764,7 @@ xfs_acl_setmode( if (gap && nomask) iattr.ia_mode |= gap->ae_perm << 3; - return xfs_setattr(XFS_I(vp), &iattr, 0, sys_cred); + return xfs_setattr(xfs_vtoi(vp), &iattr, 0, sys_cred); } /* diff --git a/trunk/fs/xfs/xfs_acl.h b/trunk/fs/xfs/xfs_acl.h index a4e293b93efa..323ee94cf831 100644 --- a/trunk/fs/xfs/xfs_acl.h +++ b/trunk/fs/xfs/xfs_acl.h @@ -59,14 +59,14 @@ extern struct kmem_zone *xfs_acl_zone; (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) -extern int xfs_acl_inherit(struct inode *, mode_t mode, xfs_acl_t *); +extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *); extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); -extern int xfs_acl_vtoacl(struct inode *, xfs_acl_t *, xfs_acl_t *); -extern int xfs_acl_vhasacl_access(struct inode *); -extern int xfs_acl_vhasacl_default(struct inode *); -extern int xfs_acl_vset(struct inode *, void *, size_t, int); -extern int xfs_acl_vget(struct inode *, void *, size_t, int); -extern int xfs_acl_vremove(struct inode *, int); +extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *); +extern int xfs_acl_vhasacl_access(bhv_vnode_t *); +extern int xfs_acl_vhasacl_default(bhv_vnode_t *); +extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int); +extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int); +extern int xfs_acl_vremove(bhv_vnode_t *, int); #define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) diff --git a/trunk/fs/xfs/xfs_arch.h b/trunk/fs/xfs/xfs_arch.h index 0b3b5efe848c..f9472a2076d4 100644 --- a/trunk/fs/xfs/xfs_arch.h +++ b/trunk/fs/xfs/xfs_arch.h @@ -92,6 +92,16 @@ ((__u8*)(pointer))[1] = (((value) ) & 0xff); \ } +/* define generic INT_ macros */ + +#define INT_GET(reference,arch) \ + (((arch) == ARCH_NOCONVERT) \ + ? \ + (reference) \ + : \ + INT_SWAP((reference),(reference)) \ + ) + /* does not return a value */ #define INT_SET(reference,arch,valueref) \ (__builtin_constant_p(valueref) ? \ @@ -102,6 +112,64 @@ ) \ ) +/* does not return a value */ +#define INT_MOD_EXPR(reference,arch,code) \ + (((arch) == ARCH_NOCONVERT) \ + ? \ + (void)((reference) code) \ + : \ + (void)( \ + (reference) = INT_GET((reference),arch) , \ + ((reference) code), \ + INT_SET(reference, arch, reference) \ + ) \ + ) + +/* does not return a value */ +#define INT_MOD(reference,arch,delta) \ + (void)( \ + INT_MOD_EXPR(reference,arch,+=(delta)) \ + ) + +/* + * INT_COPY - copy a value between two locations with the + * _same architecture_ but _potentially different sizes_ + * + * if the types of the two parameters are equal or they are + * in native architecture, a simple copy is done + * + * otherwise, architecture conversions are done + * + */ + +/* does not return a value */ +#define INT_COPY(dst,src,arch) \ + ( \ + ((sizeof(dst) == sizeof(src)) || ((arch) == ARCH_NOCONVERT)) \ + ? \ + (void)((dst) = (src)) \ + : \ + INT_SET(dst, arch, INT_GET(src, arch)) \ + ) + +/* + * INT_XLATE - copy a value in either direction between two locations + * with different architectures + * + * dir < 0 - copy from memory to buffer (native to arch) + * dir > 0 - copy from buffer to memory (arch to native) + */ + +/* does not return a value */ +#define INT_XLATE(buf,mem,dir,arch) {\ + ASSERT(dir); \ + if (dir>0) { \ + (mem)=INT_GET(buf, arch); \ + } else { \ + INT_SET(buf, arch, mem); \ + } \ +} + /* * In directories inode numbers are stored as unaligned arrays of unsigned * 8bit integers on disk. diff --git a/trunk/fs/xfs/xfs_attr.c b/trunk/fs/xfs/xfs_attr.c index f7cdc28aff41..78de80e3caa2 100644 --- a/trunk/fs/xfs/xfs_attr.c +++ b/trunk/fs/xfs/xfs_attr.c @@ -194,46 +194,6 @@ xfs_attr_get( return(error); } -/* - * Calculate how many blocks we need for the new attribute, - */ -int -xfs_attr_calc_size( - struct xfs_inode *ip, - int namelen, - int valuelen, - int *local) -{ - struct xfs_mount *mp = ip->i_mount; - int size; - int nblks; - - /* - * Determine space new attribute will use, and if it would be - * "local" or "remote" (note: local != inline). - */ - size = xfs_attr_leaf_newentsize(namelen, valuelen, - mp->m_sb.sb_blocksize, local); - - nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); - if (*local) { - if (size > (mp->m_sb.sb_blocksize >> 1)) { - /* Double split possible */ - nblks *= 2; - } - } else { - /* - * Out of line attribute, cannot double split, but - * make room for the attribute value itself. - */ - uint dblocks = XFS_B_TO_FSB(mp, valuelen); - nblks += dblocks; - nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); - } - - return nblks; -} - STATIC int xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, char *value, int valuelen, int flags) @@ -242,9 +202,10 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, xfs_fsblock_t firstblock; xfs_bmap_free_t flist; int error, err2, committed; + int local, size; + uint nblks; xfs_mount_t *mp = dp->i_mount; int rsvd = (flags & ATTR_ROOT) != 0; - int local; /* * Attach the dquots to the inode. @@ -280,8 +241,30 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, args.whichfork = XFS_ATTR_FORK; args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; + /* + * Determine space new attribute will use, and if it would be + * "local" or "remote" (note: local != inline). + */ + size = xfs_attr_leaf_newentsize(name->len, valuelen, + mp->m_sb.sb_blocksize, &local); + + nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); + if (local) { + if (size > (mp->m_sb.sb_blocksize >> 1)) { + /* Double split possible */ + nblks <<= 1; + } + } else { + uint dblocks = XFS_B_TO_FSB(mp, valuelen); + /* Out of line attribute, cannot double split, but make + * room for the attribute value itself. + */ + nblks += dblocks; + nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); + } + /* Size is now blocks for attribute data */ - args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local); + args.total = nblks; /* * Start our first transaction of the day. @@ -303,17 +286,18 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, if (rsvd) args.trans->t_flags |= XFS_TRANS_RESERVE; - if ((error = xfs_trans_reserve(args.trans, args.total, - XFS_ATTRSET_LOG_RES(mp, args.total), 0, - XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) { + if ((error = xfs_trans_reserve(args.trans, (uint) nblks, + XFS_ATTRSET_LOG_RES(mp, nblks), + 0, XFS_TRANS_PERM_LOG_RES, + XFS_ATTRSET_LOG_COUNT))) { xfs_trans_cancel(args.trans, 0); return(error); } xfs_ilock(dp, XFS_ILOCK_EXCL); - error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0, - rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : - XFS_QMOPT_RES_REGBLKS); + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, + rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : + XFS_QMOPT_RES_REGBLKS); if (error) { xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); @@ -400,9 +384,7 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, * Commit the leaf transformation. We'll need another (linked) * transaction to add the new attribute to the leaf. */ - - error = xfs_trans_roll(&args.trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args.trans, dp))) goto out; } @@ -982,8 +964,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit the current trans (including the inode) and start * a new one. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) return (error); /* @@ -997,8 +978,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit the transaction that added the attr name so that * later routines can manage their own transactions. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) return (error); /* @@ -1087,7 +1067,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) /* * Commit the remove and start the next trans in series. */ - error = xfs_trans_roll(&args->trans, dp); + error = xfs_attr_rolltrans(&args->trans, dp); } else if (args->rmtblkno > 0) { /* @@ -1318,8 +1298,7 @@ xfs_attr_node_addname(xfs_da_args_t *args) * Commit the node conversion and start the next * trans in the chain. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) goto out; goto restart; @@ -1370,8 +1349,7 @@ xfs_attr_node_addname(xfs_da_args_t *args) * Commit the leaf addition or btree split and start the next * trans in the chain. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) goto out; /* @@ -1471,8 +1449,7 @@ xfs_attr_node_addname(xfs_da_args_t *args) /* * Commit and start the next trans in the chain. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) goto out; } else if (args->rmtblkno > 0) { @@ -1604,8 +1581,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) /* * Commit the Btree join operation and start a new trans. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) goto out; } @@ -2106,8 +2082,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) /* * Start the next trans in the chain. */ - error = xfs_trans_roll(&args->trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, dp))) return (error); } @@ -2257,8 +2232,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) /* * Close out trans and start the next one in the chain. */ - error = xfs_trans_roll(&args->trans, args->dp); - if (error) + if ((error = xfs_attr_rolltrans(&args->trans, args->dp))) return (error); } return(0); diff --git a/trunk/fs/xfs/xfs_attr.h b/trunk/fs/xfs/xfs_attr.h index fb3b2a68b9b9..8b2d31c19e4d 100644 --- a/trunk/fs/xfs/xfs_attr.h +++ b/trunk/fs/xfs/xfs_attr.h @@ -129,7 +129,6 @@ typedef struct xfs_attr_list_context { /* * Overall external interface routines. */ -int xfs_attr_calc_size(struct xfs_inode *, int, int, int *); int xfs_attr_inactive(struct xfs_inode *dp); int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int); int xfs_attr_rmtval_get(struct xfs_da_args *args); diff --git a/trunk/fs/xfs/xfs_attr_leaf.c b/trunk/fs/xfs/xfs_attr_leaf.c index 79da6b2ea99e..23ef5d7c87e1 100644 --- a/trunk/fs/xfs/xfs_attr_leaf.c +++ b/trunk/fs/xfs/xfs_attr_leaf.c @@ -2498,7 +2498,9 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - return xfs_trans_roll(&args->trans, args->dp); + error = xfs_attr_rolltrans(&args->trans, args->dp); + + return(error); } /* @@ -2545,7 +2547,9 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - return xfs_trans_roll(&args->trans, args->dp); + error = xfs_attr_rolltrans(&args->trans, args->dp); + + return(error); } /* @@ -2661,7 +2665,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - error = xfs_trans_roll(&args->trans, args->dp); + error = xfs_attr_rolltrans(&args->trans, args->dp); return(error); } @@ -2719,7 +2723,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) /* * Commit the invalidate and start the next transaction. */ - error = xfs_trans_roll(trans, dp); + error = xfs_attr_rolltrans(trans, dp); return (error); } @@ -2821,8 +2825,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, /* * Atomically commit the whole invalidate stuff. */ - error = xfs_trans_roll(trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(trans, dp))) return (error); } @@ -2961,8 +2964,7 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, /* * Roll to next transaction. */ - error = xfs_trans_roll(trans, dp); - if (error) + if ((error = xfs_attr_rolltrans(trans, dp))) return (error); } @@ -2972,3 +2974,60 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, return(0); } + + +/* + * Roll from one trans in the sequence of PERMANENT transactions to the next. + */ +int +xfs_attr_rolltrans(xfs_trans_t **transp, xfs_inode_t *dp) +{ + xfs_trans_t *trans; + unsigned int logres, count; + int error; + + /* + * Ensure that the inode is always logged. + */ + trans = *transp; + xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); + + /* + * Copy the critical parameters from one trans to the next. + */ + logres = trans->t_log_res; + count = trans->t_log_count; + *transp = xfs_trans_dup(trans); + + /* + * Commit the current transaction. + * If this commit failed, then it'd just unlock those items that + * are not marked ihold. That also means that a filesystem shutdown + * is in progress. The caller takes the responsibility to cancel + * the duplicate transaction that gets returned. + */ + if ((error = xfs_trans_commit(trans, 0))) + return (error); + + trans = *transp; + + /* + * Reserve space in the log for th next transaction. + * This also pushes items in the "AIL", the list of logged items, + * out to disk if they are taking up space at the tail of the log + * that we want to use. This requires that either nothing be locked + * across this call, or that anything that is locked be logged in + * the prior and the next transactions. + */ + error = xfs_trans_reserve(trans, 0, logres, 0, + XFS_TRANS_PERM_LOG_RES, count); + /* + * Ensure that the inode is in the new transaction and locked. + */ + if (!error) { + xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); + xfs_trans_ihold(trans, dp); + } + return (error); + +} diff --git a/trunk/fs/xfs/xfs_attr_leaf.h b/trunk/fs/xfs/xfs_attr_leaf.h index 83e9af417ca2..5ecf437b7825 100644 --- a/trunk/fs/xfs/xfs_attr_leaf.h +++ b/trunk/fs/xfs/xfs_attr_leaf.h @@ -274,4 +274,6 @@ int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp, struct xfs_dabuf *leaf2_bp); int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local); +int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp); + #endif /* __XFS_ATTR_LEAF_H__ */ diff --git a/trunk/fs/xfs/xfs_bit.c b/trunk/fs/xfs/xfs_bit.c index 48228848f5ae..fab0b6d5a41b 100644 --- a/trunk/fs/xfs/xfs_bit.c +++ b/trunk/fs/xfs/xfs_bit.c @@ -25,6 +25,109 @@ * XFS bit manipulation routines, used in non-realtime code. */ +#ifndef HAVE_ARCH_HIGHBIT +/* + * Index of high bit number in byte, -1 for none set, 0..7 otherwise. + */ +static const char xfs_highbit[256] = { + -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */ + 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */ + 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */ + 4, 4, 4, 4, 4, 4, 4, 4, /* 18 .. 1f */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 20 .. 27 */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 28 .. 2f */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 30 .. 37 */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 38 .. 3f */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 40 .. 47 */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 48 .. 4f */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 50 .. 57 */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 58 .. 5f */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 60 .. 67 */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 68 .. 6f */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 70 .. 77 */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 78 .. 7f */ + 7, 7, 7, 7, 7, 7, 7, 7, /* 80 .. 87 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* 88 .. 8f */ + 7, 7, 7, 7, 7, 7, 7, 7, /* 90 .. 97 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* 98 .. 9f */ + 7, 7, 7, 7, 7, 7, 7, 7, /* a0 .. a7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* a8 .. af */ + 7, 7, 7, 7, 7, 7, 7, 7, /* b0 .. b7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* b8 .. bf */ + 7, 7, 7, 7, 7, 7, 7, 7, /* c0 .. c7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* c8 .. cf */ + 7, 7, 7, 7, 7, 7, 7, 7, /* d0 .. d7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* d8 .. df */ + 7, 7, 7, 7, 7, 7, 7, 7, /* e0 .. e7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* e8 .. ef */ + 7, 7, 7, 7, 7, 7, 7, 7, /* f0 .. f7 */ + 7, 7, 7, 7, 7, 7, 7, 7, /* f8 .. ff */ +}; +#endif + +/* + * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set. + */ +inline int +xfs_highbit32( + __uint32_t v) +{ +#ifdef HAVE_ARCH_HIGHBIT + return highbit32(v); +#else + int i; + + if (v & 0xffff0000) + if (v & 0xff000000) + i = 24; + else + i = 16; + else if (v & 0x0000ffff) + if (v & 0x0000ff00) + i = 8; + else + i = 0; + else + return -1; + return i + xfs_highbit[(v >> i) & 0xff]; +#endif +} + +/* + * xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set. + */ +int +xfs_lowbit64( + __uint64_t v) +{ + __uint32_t w = (__uint32_t)v; + int n = 0; + + if (w) { /* lower bits */ + n = ffs(w); + } else { /* upper bits */ + w = (__uint32_t)(v >> 32); + if (w && (n = ffs(w))) + n += 32; + } + return n - 1; +} + +/* + * xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set. + */ +int +xfs_highbit64( + __uint64_t v) +{ + __uint32_t h = (__uint32_t)(v >> 32); + + if (h) + return xfs_highbit32(h) + 32; + return xfs_highbit32((__uint32_t)v); +} + + /* * Return whether bitmap is empty. * Size is number of words in the bitmap, which is padded to word boundary diff --git a/trunk/fs/xfs/xfs_bit.h b/trunk/fs/xfs/xfs_bit.h index 8e0e463dae2d..082641a9782c 100644 --- a/trunk/fs/xfs/xfs_bit.h +++ b/trunk/fs/xfs/xfs_bit.h @@ -47,39 +47,13 @@ static inline __uint64_t xfs_mask64lo(int n) } /* Get high bit set out of 32-bit argument, -1 if none set */ -static inline int xfs_highbit32(__uint32_t v) -{ - return fls(v) - 1; -} - -/* Get high bit set out of 64-bit argument, -1 if none set */ -static inline int xfs_highbit64(__uint64_t v) -{ - return fls64(v) - 1; -} - -/* Get low bit set out of 32-bit argument, -1 if none set */ -static inline int xfs_lowbit32(__uint32_t v) -{ - unsigned long t = v; - return (v) ? find_first_bit(&t, 32) : -1; -} +extern int xfs_highbit32(__uint32_t v); /* Get low bit set out of 64-bit argument, -1 if none set */ -static inline int xfs_lowbit64(__uint64_t v) -{ - __uint32_t w = (__uint32_t)v; - int n = 0; +extern int xfs_lowbit64(__uint64_t v); - if (w) { /* lower bits */ - n = ffs(w); - } else { /* upper bits */ - w = (__uint32_t)(v >> 32); - if (w && (n = ffs(w))) - n += 32; - } - return n - 1; -} +/* Get high bit set out of 64-bit argument, -1 if none set */ +extern int xfs_highbit64(__uint64_t); /* Return whether bitmap is empty (1 == empty) */ extern int xfs_bitmap_empty(uint *map, uint size); diff --git a/trunk/fs/xfs/xfs_bmap.c b/trunk/fs/xfs/xfs_bmap.c index a1aab9275d5a..3c4beb3a4326 100644 --- a/trunk/fs/xfs/xfs_bmap.c +++ b/trunk/fs/xfs/xfs_bmap.c @@ -384,14 +384,14 @@ xfs_bmap_count_tree( int levelin, int *count); -STATIC void +STATIC int xfs_bmap_count_leaves( xfs_ifork_t *ifp, xfs_extnum_t idx, int numrecs, int *count); -STATIC void +STATIC int xfs_bmap_disk_count_leaves( xfs_extnum_t idx, xfs_bmbt_block_t *block, @@ -4000,7 +4000,7 @@ xfs_bmap_add_attrfork( ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; } ASSERT(ip->i_d.di_anextents == 0); - IHOLD(ip); + VN_HOLD(XFS_ITOV(ip)); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); switch (ip->i_d.di_format) { @@ -6096,7 +6096,7 @@ xfs_bmap_get_bp( tp = cur->bc_tp; licp = &tp->t_items; while (!bp && licp != NULL) { - if (xfs_lic_are_all_free(licp)) { + if (XFS_LIC_ARE_ALL_FREE(licp)) { licp = licp->lic_next; continue; } @@ -6106,11 +6106,11 @@ xfs_bmap_get_bp( xfs_buf_log_item_t *bip; xfs_buf_t *lbp; - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - lidp = xfs_lic_slot(licp, i); + lidp = XFS_LIC_SLOT(licp, i); lip = lidp->lid_item; if (lip->li_type != XFS_LI_BUF) continue; @@ -6367,9 +6367,13 @@ xfs_bmap_count_blocks( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { - xfs_bmap_count_leaves(ifp, 0, + if (unlikely(xfs_bmap_count_leaves(ifp, 0, ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t), - count); + count) < 0)) { + XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)", + XFS_ERRLEVEL_LOW, mp); + return XFS_ERROR(EFSCORRUPTED); + } return 0; } @@ -6450,7 +6454,13 @@ xfs_bmap_count_tree( for (;;) { nextbno = be64_to_cpu(block->bb_rightsib); numrecs = be16_to_cpu(block->bb_numrecs); - xfs_bmap_disk_count_leaves(0, block, numrecs, count); + if (unlikely(xfs_bmap_disk_count_leaves(0, + block, numrecs, count) < 0)) { + xfs_trans_brelse(tp, bp); + XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", + XFS_ERRLEVEL_LOW, mp); + return XFS_ERROR(EFSCORRUPTED); + } xfs_trans_brelse(tp, bp); if (nextbno == NULLFSBLOCK) break; @@ -6468,7 +6478,7 @@ xfs_bmap_count_tree( /* * Count leaf blocks given a range of extent records. */ -STATIC void +STATIC int xfs_bmap_count_leaves( xfs_ifork_t *ifp, xfs_extnum_t idx, @@ -6481,13 +6491,14 @@ xfs_bmap_count_leaves( xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b); *count += xfs_bmbt_get_blockcount(frp); } + return 0; } /* * Count leaf blocks given a range of extent records originally * in btree format. */ -STATIC void +STATIC int xfs_bmap_disk_count_leaves( xfs_extnum_t idx, xfs_bmbt_block_t *block, @@ -6501,4 +6512,5 @@ xfs_bmap_disk_count_leaves( frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b); *count += xfs_bmbt_disk_get_blockcount(frp); } + return 0; } diff --git a/trunk/fs/xfs/xfs_btree.c b/trunk/fs/xfs/xfs_btree.c index cc593a84c345..aeb87ca69fcc 100644 --- a/trunk/fs/xfs/xfs_btree.c +++ b/trunk/fs/xfs/xfs_btree.c @@ -46,10 +46,37 @@ kmem_zone_t *xfs_btree_cur_zone; /* * Btree magic numbers. */ -const __uint32_t xfs_magics[XFS_BTNUM_MAX] = { +const __uint32_t xfs_magics[XFS_BTNUM_MAX] = +{ XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC }; +/* + * Prototypes for internal routines. + */ + +/* + * Checking routine: return maxrecs for the block. + */ +STATIC int /* number of records fitting in block */ +xfs_btree_maxrecs( + xfs_btree_cur_t *cur, /* btree cursor */ + xfs_btree_block_t *block);/* generic btree block pointer */ + +/* + * Internal routines. + */ + +/* + * Retrieve the block pointer from the cursor at the given level. + * This may be a bmap btree root or from a buffer. + */ +STATIC xfs_btree_block_t * /* generic btree block pointer */ +xfs_btree_get_block( + xfs_btree_cur_t *cur, /* btree cursor */ + int level, /* level in btree */ + struct xfs_buf **bpp); /* buffer containing the block */ + /* * Checking routine: return maxrecs for the block. */ @@ -429,6 +456,35 @@ xfs_btree_dup_cursor( return 0; } +/* + * Change the cursor to point to the first record at the given level. + * Other levels are unaffected. + */ +int /* success=1, failure=0 */ +xfs_btree_firstrec( + xfs_btree_cur_t *cur, /* btree cursor */ + int level) /* level to change */ +{ + xfs_btree_block_t *block; /* generic btree block pointer */ + xfs_buf_t *bp; /* buffer containing block */ + + /* + * Get the block pointer for this level. + */ + block = xfs_btree_get_block(cur, level, &bp); + xfs_btree_check_block(cur, block, level, bp); + /* + * It's empty, there is no such record. + */ + if (!block->bb_h.bb_numrecs) + return 0; + /* + * Set the ptr value to 1, that's the first record/key. + */ + cur->bc_ptrs[level] = 1; + return 1; +} + /* * Retrieve the block pointer from the cursor at the given level. * This may be a bmap btree root or from a buffer. @@ -570,13 +626,6 @@ xfs_btree_init_cursor( cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; break; - case XFS_BTNUM_INO: - /* - * Inode allocation btree fields. - */ - cur->bc_private.a.agbp = agbp; - cur->bc_private.a.agno = agno; - break; case XFS_BTNUM_BMAP: /* * Bmap btree fields. @@ -589,6 +638,13 @@ xfs_btree_init_cursor( cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; break; + case XFS_BTNUM_INO: + /* + * Inode allocation btree fields. + */ + cur->bc_private.i.agbp = agbp; + cur->bc_private.i.agno = agno; + break; default: ASSERT(0); } @@ -614,35 +670,6 @@ xfs_btree_islastblock( return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK; } -/* - * Change the cursor to point to the first record at the given level. - * Other levels are unaffected. - */ -int /* success=1, failure=0 */ -xfs_btree_firstrec( - xfs_btree_cur_t *cur, /* btree cursor */ - int level) /* level to change */ -{ - xfs_btree_block_t *block; /* generic btree block pointer */ - xfs_buf_t *bp; /* buffer containing block */ - - /* - * Get the block pointer for this level. - */ - block = xfs_btree_get_block(cur, level, &bp); - xfs_btree_check_block(cur, block, level, bp); - /* - * It's empty, there is no such record. - */ - if (!block->bb_h.bb_numrecs) - return 0; - /* - * Set the ptr value to 1, that's the first record/key. - */ - cur->bc_ptrs[level] = 1; - return 1; -} - /* * Change the cursor to point to the last record in the current block * at the given level. Other levels are unaffected. @@ -863,12 +890,12 @@ xfs_btree_readahead_core( case XFS_BTNUM_INO: i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]); if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) { - xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, + xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, be32_to_cpu(i->bb_leftsib), 1); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) { - xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, + xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, be32_to_cpu(i->bb_rightsib), 1); rval++; } diff --git a/trunk/fs/xfs/xfs_btree.h b/trunk/fs/xfs/xfs_btree.h index 1f528a2a3754..7440b78f9cec 100644 --- a/trunk/fs/xfs/xfs_btree.h +++ b/trunk/fs/xfs/xfs_btree.h @@ -158,8 +158,8 @@ typedef struct xfs_btree_cur __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ xfs_btnum_t bc_btnum; /* identifies which btree type */ union { - struct { /* needed for BNO, CNT, INO */ - struct xfs_buf *agbp; /* agf/agi buffer pointer */ + struct { /* needed for BNO, CNT */ + struct xfs_buf *agbp; /* agf buffer pointer */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ @@ -172,6 +172,10 @@ typedef struct xfs_btree_cur char flags; /* flags */ #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ } b; + struct { /* needed for INO */ + struct xfs_buf *agbp; /* agi buffer pointer */ + xfs_agnumber_t agno; /* ag number */ + } i; } bc_private; /* per-btree type data */ } xfs_btree_cur_t; diff --git a/trunk/fs/xfs/xfs_buf_item.c b/trunk/fs/xfs/xfs_buf_item.c index 608c30c3f76b..d86ca2c03a70 100644 --- a/trunk/fs/xfs/xfs_buf_item.c +++ b/trunk/fs/xfs/xfs_buf_item.c @@ -737,7 +737,7 @@ xfs_buf_item_init( bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); bip->bli_format.blf_map_size = map_size; #ifdef XFS_BLI_TRACE - bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_NOFS); + bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_TRANS_DEBUG @@ -1056,7 +1056,7 @@ xfs_buf_iodone_callbacks( anyway. */ XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse); XFS_BUF_DONE(bp); - XFS_BUF_FINISH_IOWAIT(bp); + XFS_BUF_V_IODONESEMA(bp); } return; } diff --git a/trunk/fs/xfs/xfs_dfrag.c b/trunk/fs/xfs/xfs_dfrag.c index 760f4c5b5160..2211e885ef24 100644 --- a/trunk/fs/xfs/xfs_dfrag.c +++ b/trunk/fs/xfs/xfs_dfrag.c @@ -128,8 +128,10 @@ xfs_swap_extents( xfs_swapext_t *sxp) { xfs_mount_t *mp; + xfs_inode_t *ips[2]; xfs_trans_t *tp; xfs_bstat_t *sbp = &sxp->sx_stat; + bhv_vnode_t *vp, *tvp; xfs_ifork_t *tempifp, *ifp, *tifp; int ilf_fields, tilf_fields; static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; @@ -148,8 +150,19 @@ xfs_swap_extents( } sbp = &sxp->sx_stat; + vp = XFS_ITOV(ip); + tvp = XFS_ITOV(tip); + + /* Lock in i_ino order */ + if (ip->i_ino < tip->i_ino) { + ips[0] = ip; + ips[1] = tip; + } else { + ips[0] = tip; + ips[1] = ip; + } - xfs_lock_two_inodes(ip, tip, lock_flags); + xfs_lock_inodes(ips, 2, lock_flags); locked = 1; /* Verify that both files have the same format */ @@ -171,7 +184,7 @@ xfs_swap_extents( goto error0; } - if (VN_CACHED(VFS_I(tip)) != 0) { + if (VN_CACHED(tvp) != 0) { xfs_inval_cached_trace(tip, 0, -1, 0, -1); error = xfs_flushinval_pages(tip, 0, -1, FI_REMAPF_LOCKED); @@ -180,7 +193,7 @@ xfs_swap_extents( } /* Verify O_DIRECT for ftmp */ - if (VN_CACHED(VFS_I(tip)) != 0) { + if (VN_CACHED(tvp) != 0) { error = XFS_ERROR(EINVAL); goto error0; } @@ -224,7 +237,7 @@ xfs_swap_extents( * vop_read (or write in the case of autogrow) they block on the iolock * until we have switched the extents. */ - if (VN_MAPPED(VFS_I(ip))) { + if (VN_MAPPED(vp)) { error = XFS_ERROR(EBUSY); goto error0; } @@ -252,7 +265,7 @@ xfs_swap_extents( locked = 0; goto error0; } - xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); + xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); /* * Count the number of extended attribute blocks @@ -337,11 +350,15 @@ xfs_swap_extents( break; } + /* + * Increment vnode ref counts since xfs_trans_commit & + * xfs_trans_cancel will both unlock the inodes and + * decrement the associated ref counts. + */ + VN_HOLD(vp); + VN_HOLD(tvp); - IHOLD(ip); xfs_trans_ijoin(tp, ip, lock_flags); - - IHOLD(tip); xfs_trans_ijoin(tp, tip, lock_flags); xfs_trans_log_inode(tp, ip, ilf_fields); diff --git a/trunk/fs/xfs/xfs_error.c b/trunk/fs/xfs/xfs_error.c index f227ecd1a294..f66756cfb5e8 100644 --- a/trunk/fs/xfs/xfs_error.c +++ b/trunk/fs/xfs/xfs_error.c @@ -58,6 +58,9 @@ xfs_error_trap(int e) } return e; } +#endif + +#if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) int xfs_etest[XFS_NUM_INJECT_ERROR]; int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; @@ -151,7 +154,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) return 0; } -#endif /* DEBUG */ +#endif /* DEBUG || INDUCE_IO_ERROR */ static void xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap) diff --git a/trunk/fs/xfs/xfs_error.h b/trunk/fs/xfs/xfs_error.h index 11543f10b0c6..d8559d132efa 100644 --- a/trunk/fs/xfs/xfs_error.h +++ b/trunk/fs/xfs/xfs_error.h @@ -125,14 +125,22 @@ extern void xfs_corruption_error(char *tag, int level, struct xfs_mount *mp, #define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10) #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT -#ifdef DEBUG +#if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); #define XFS_NUM_INJECT_ERROR 10 + +#ifdef __ANSI_CPP__ +#define XFS_TEST_ERROR(expr, mp, tag, rf) \ + ((expr) || \ + xfs_error_test((tag), (mp)->m_fixedfsid, #expr, __LINE__, __FILE__, \ + (rf))) +#else #define XFS_TEST_ERROR(expr, mp, tag, rf) \ ((expr) || \ xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ (rf))) +#endif /* __ANSI_CPP__ */ extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); @@ -140,7 +148,7 @@ extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); #define XFS_TEST_ERROR(expr, mp, tag, rf) (expr) #define xfs_errortag_add(tag, mp) (ENOSYS) #define xfs_errortag_clearall(mp, loud) (ENOSYS) -#endif /* DEBUG */ +#endif /* (DEBUG || INDUCE_IO_ERROR) */ /* * XFS panic tags -- allow a call to xfs_cmn_err() be turned into diff --git a/trunk/fs/xfs/xfs_filestream.c b/trunk/fs/xfs/xfs_filestream.c index f3bb75da384e..c38fd14fca29 100644 --- a/trunk/fs/xfs/xfs_filestream.c +++ b/trunk/fs/xfs/xfs_filestream.c @@ -400,7 +400,7 @@ xfs_filestream_init(void) if (!item_zone) return -ENOMEM; #ifdef XFS_FILESTREAMS_TRACE - xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_NOFS); + xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP); #endif return 0; } diff --git a/trunk/fs/xfs/xfs_ialloc_btree.c b/trunk/fs/xfs/xfs_ialloc_btree.c index 83502f3edef0..e5310c90e50f 100644 --- a/trunk/fs/xfs/xfs_ialloc_btree.c +++ b/trunk/fs/xfs/xfs_ialloc_btree.c @@ -181,7 +181,7 @@ xfs_inobt_delrec( * then we can get rid of this level. */ if (numrecs == 1 && level > 0) { - agbp = cur->bc_private.a.agbp; + agbp = cur->bc_private.i.agbp; agi = XFS_BUF_TO_AGI(agbp); /* * pp is still set to the first pointer in the block. @@ -194,7 +194,7 @@ xfs_inobt_delrec( * Free the block. */ if ((error = xfs_free_extent(cur->bc_tp, - XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1))) + XFS_AGB_TO_FSB(mp, cur->bc_private.i.agno, bno), 1))) return error; xfs_trans_binval(cur->bc_tp, bp); xfs_ialloc_log_agi(cur->bc_tp, agbp, @@ -379,7 +379,7 @@ xfs_inobt_delrec( rrecs = be16_to_cpu(right->bb_numrecs); rbp = bp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.a.agno, lbno, 0, &lbp, + cur->bc_private.i.agno, lbno, 0, &lbp, XFS_INO_BTREE_REF))) return error; left = XFS_BUF_TO_INOBT_BLOCK(lbp); @@ -401,7 +401,7 @@ xfs_inobt_delrec( lrecs = be16_to_cpu(left->bb_numrecs); lbp = bp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.a.agno, rbno, 0, &rbp, + cur->bc_private.i.agno, rbno, 0, &rbp, XFS_INO_BTREE_REF))) return error; right = XFS_BUF_TO_INOBT_BLOCK(rbp); @@ -484,7 +484,7 @@ xfs_inobt_delrec( xfs_buf_t *rrbp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, + cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), 0, &rrbp, XFS_INO_BTREE_REF))) return error; rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); @@ -497,7 +497,7 @@ xfs_inobt_delrec( * Free the deleting block. */ if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp, - cur->bc_private.a.agno, rbno), 1))) + cur->bc_private.i.agno, rbno), 1))) return error; xfs_trans_binval(cur->bc_tp, rbp); /* @@ -854,7 +854,7 @@ xfs_inobt_lookup( { xfs_agi_t *agi; /* a.g. inode header */ - agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); + agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp); agno = be32_to_cpu(agi->agi_seqno); agbno = be32_to_cpu(agi->agi_root); } @@ -1089,7 +1089,7 @@ xfs_inobt_lshift( * Set up the left neighbor as "left". */ if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), + cur->bc_private.i.agno, be32_to_cpu(right->bb_leftsib), 0, &lbp, XFS_INO_BTREE_REF))) return error; left = XFS_BUF_TO_INOBT_BLOCK(lbp); @@ -1207,10 +1207,10 @@ xfs_inobt_newroot( /* * Get a block & a buffer. */ - agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); + agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp); args.tp = cur->bc_tp; args.mp = cur->bc_mp; - args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, + args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, be32_to_cpu(agi->agi_root)); args.mod = args.minleft = args.alignment = args.total = args.wasdel = args.isfl = args.userdata = args.minalignslop = 0; @@ -1233,7 +1233,7 @@ xfs_inobt_newroot( */ agi->agi_root = cpu_to_be32(args.agbno); be32_add_cpu(&agi->agi_level, 1); - xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp, + xfs_ialloc_log_agi(args.tp, cur->bc_private.i.agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); /* * At the previous root level there are now two blocks: the old @@ -1376,7 +1376,7 @@ xfs_inobt_rshift( * Set up the right neighbor as "right". */ if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), + cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), 0, &rbp, XFS_INO_BTREE_REF))) return error; right = XFS_BUF_TO_INOBT_BLOCK(rbp); @@ -1492,7 +1492,7 @@ xfs_inobt_split( * Allocate the new block. * If we can't do it, we're toast. Give up. */ - args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, lbno); + args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, lbno); args.mod = args.minleft = args.alignment = args.total = args.wasdel = args.isfl = args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; @@ -1725,7 +1725,7 @@ xfs_inobt_decrement( agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.a.agno, agbno, 0, &bp, + cur->bc_private.i.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; @@ -1897,7 +1897,7 @@ xfs_inobt_increment( agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.a.agno, agbno, 0, &bp, + cur->bc_private.i.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; diff --git a/trunk/fs/xfs/xfs_iget.c b/trunk/fs/xfs/xfs_iget.c index e229e9e001c2..b07604b94d9f 100644 --- a/trunk/fs/xfs/xfs_iget.c +++ b/trunk/fs/xfs/xfs_iget.c @@ -216,14 +216,7 @@ xfs_iget_core( mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); init_waitqueue_head(&ip->i_ipin_wait); atomic_set(&ip->i_pincount, 0); - - /* - * Because we want to use a counting completion, complete - * the flush completion once to allow a single access to - * the flush completion without blocking. - */ - init_completion(&ip->i_flush); - complete(&ip->i_flush); + initnsema(&ip->i_flock, 1, "xfsfino"); if (lock_flags) xfs_ilock(ip, lock_flags); @@ -294,18 +287,11 @@ xfs_iget_core( xfs_iflags_set(ip, XFS_IMODIFIED); *ipp = ip; - /* - * Set up the Linux with the Linux inode. - */ - ip->i_vnode = inode; - inode->i_private = ip; - /* * If we have a real type for an on-disk inode, we can set ops(&unlock) * now. If it's a new inode being created, xfs_ialloc will handle it. */ - if (ip->i_d.di_mode != 0) - xfs_setup_inode(ip); + xfs_initialize_vnode(mp, inode, ip); return 0; } @@ -425,11 +411,10 @@ xfs_iput(xfs_inode_t *ip, * Special iput for brand-new inodes that are still locked */ void -xfs_iput_new( - xfs_inode_t *ip, - uint lock_flags) +xfs_iput_new(xfs_inode_t *ip, + uint lock_flags) { - struct inode *inode = VFS_I(ip); + struct inode *inode = ip->i_vnode; xfs_itrace_entry(ip); @@ -790,3 +775,26 @@ xfs_isilocked( } #endif +/* + * The following three routines simply manage the i_flock + * semaphore embedded in the inode. This semaphore synchronizes + * processes attempting to flush the in-core inode back to disk. + */ +void +xfs_iflock(xfs_inode_t *ip) +{ + psema(&(ip->i_flock), PINOD|PLTWAIT); +} + +int +xfs_iflock_nowait(xfs_inode_t *ip) +{ + return (cpsema(&(ip->i_flock))); +} + +void +xfs_ifunlock(xfs_inode_t *ip) +{ + ASSERT(issemalocked(&(ip->i_flock))); + vsema(&(ip->i_flock)); +} diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 358511b85ced..bedc66163176 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -580,8 +580,8 @@ xfs_iformat_extents( xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip)); for (i = 0; i < nex; i++, dp++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i); - ep->l0 = get_unaligned_be64(&dp->l0); - ep->l1 = get_unaligned_be64(&dp->l1); + ep->l0 = be64_to_cpu(get_unaligned(&dp->l0)); + ep->l1 = be64_to_cpu(get_unaligned(&dp->l1)); } XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork); if (whichfork != XFS_DATA_FORK || @@ -835,22 +835,22 @@ xfs_iread( * Do this before xfs_iformat in case it adds entries. */ #ifdef XFS_INODE_TRACE - ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS); + ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_BMAP_TRACE - ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS); + ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_BMBT_TRACE - ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS); + ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_RW_TRACE - ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS); + ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_ILOCK_TRACE - ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS); + ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP); #endif #ifdef XFS_DIR2_TRACE - ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); + ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP); #endif /* @@ -1046,9 +1046,9 @@ xfs_ialloc( { xfs_ino_t ino; xfs_inode_t *ip; + bhv_vnode_t *vp; uint flags; int error; - timespec_t tv; /* * Call the space management code to pick @@ -1077,6 +1077,7 @@ xfs_ialloc( } ASSERT(ip != NULL); + vp = XFS_ITOV(ip); ip->i_d.di_mode = (__uint16_t)mode; ip->i_d.di_onlink = 0; ip->i_d.di_nlink = nlink; @@ -1129,13 +1130,7 @@ xfs_ialloc( ip->i_size = 0; ip->i_d.di_nextents = 0; ASSERT(ip->i_d.di_nblocks == 0); - - nanotime(&tv); - ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; - ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; - ip->i_d.di_atime = ip->i_d.di_mtime; - ip->i_d.di_ctime = ip->i_d.di_mtime; - + xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD); /* * di_gen will have been taken care of in xfs_iread. */ @@ -1225,7 +1220,7 @@ xfs_ialloc( xfs_trans_log_inode(tp, ip, flags); /* now that we have an i_mode we can setup inode ops and unlock */ - xfs_setup_inode(ip); + xfs_initialize_vnode(tp->t_mountp, vp, ip); *ipp = ip; return 0; @@ -1404,6 +1399,7 @@ xfs_itruncate_start( xfs_fsize_t last_byte; xfs_off_t toss_start; xfs_mount_t *mp; + bhv_vnode_t *vp; int error = 0; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); @@ -1412,6 +1408,7 @@ xfs_itruncate_start( (flags == XFS_ITRUNC_MAYBE)); mp = ip->i_mount; + vp = XFS_ITOV(ip); /* wait for the completion of any pending DIOs */ if (new_size < ip->i_size) @@ -1460,7 +1457,7 @@ xfs_itruncate_start( #ifdef DEBUG if (new_size == 0) { - ASSERT(VN_CACHED(VFS_I(ip)) == 0); + ASSERT(VN_CACHED(vp) == 0); } #endif return error; @@ -2633,6 +2630,7 @@ xfs_idestroy( xfs_idestroy_fork(ip, XFS_ATTR_FORK); mrfree(&ip->i_lock); mrfree(&ip->i_iolock); + freesema(&ip->i_flock); #ifdef XFS_INODE_TRACE ktrace_free(ip->i_trace); @@ -3050,10 +3048,10 @@ xfs_iflush_cluster( /* * xfs_iflush() will write a modified inode's changes out to the * inode's on disk home. The caller must have the inode lock held - * in at least shared mode and the inode flush completion must be - * active as well. The inode lock will still be held upon return from + * in at least shared mode and the inode flush semaphore must be + * held as well. The inode lock will still be held upon return from * the call and the caller is free to unlock it. - * The inode flush will be completed when the inode reaches the disk. + * The inode flush lock will be unlocked when the inode reaches the disk. * The flags indicate how the inode's buffer should be written out. */ int @@ -3072,7 +3070,7 @@ xfs_iflush( XFS_STATS_INC(xs_iflush_count); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); - ASSERT(!completion_done(&ip->i_flush)); + ASSERT(issemalocked(&(ip->i_flock))); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); @@ -3235,7 +3233,7 @@ xfs_iflush_int( #endif ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); - ASSERT(!completion_done(&ip->i_flush)); + ASSERT(issemalocked(&(ip->i_flock))); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); @@ -3467,6 +3465,7 @@ xfs_iflush_all( xfs_mount_t *mp) { xfs_inode_t *ip; + bhv_vnode_t *vp; again: XFS_MOUNT_ILOCK(mp); @@ -3481,13 +3480,14 @@ xfs_iflush_all( continue; } - if (!VFS_I(ip)) { + vp = XFS_ITOV_NULL(ip); + if (!vp) { XFS_MOUNT_IUNLOCK(mp); xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC); goto again; } - ASSERT(vn_count(VFS_I(ip)) == 0); + ASSERT(vn_count(vp) == 0); ip = ip->i_mnext; } while (ip != mp->m_inodes); @@ -3707,7 +3707,7 @@ xfs_iext_add_indirect_multi( * (all extents past */ if (nex2) { byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); - nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_NOFS); + nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_SLEEP); memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff); erp->er_extcount -= nex2; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2); @@ -4007,7 +4007,8 @@ xfs_iext_realloc_direct( ifp->if_u1.if_extents = kmem_realloc(ifp->if_u1.if_extents, rnew_size, - ifp->if_real_bytes, KM_NOFS); + ifp->if_real_bytes, + KM_SLEEP); } if (rnew_size > ifp->if_real_bytes) { memset(&ifp->if_u1.if_extents[ifp->if_bytes / @@ -4066,7 +4067,7 @@ xfs_iext_inline_to_direct( xfs_ifork_t *ifp, /* inode fork pointer */ int new_size) /* number of extents in file */ { - ifp->if_u1.if_extents = kmem_alloc(new_size, KM_NOFS); + ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP); memset(ifp->if_u1.if_extents, 0, new_size); if (ifp->if_bytes) { memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext, @@ -4098,7 +4099,7 @@ xfs_iext_realloc_indirect( } else { ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *) kmem_realloc(ifp->if_u1.if_ext_irec, - new_size, size, KM_NOFS); + new_size, size, KM_SLEEP); } } @@ -4340,10 +4341,11 @@ xfs_iext_irec_init( nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT(nextents <= XFS_LINEAR_EXTS); - erp = kmem_alloc(sizeof(xfs_ext_irec_t), KM_NOFS); + erp = (xfs_ext_irec_t *) + kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP); if (nextents == 0) { - ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); + ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); } else if (!ifp->if_real_bytes) { xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ); } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) { @@ -4391,7 +4393,7 @@ xfs_iext_irec_new( /* Initialize new extent record */ erp = ifp->if_u1.if_ext_irec; - erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); + erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ); erp[erp_idx].er_extcount = 0; diff --git a/trunk/fs/xfs/xfs_inode.h b/trunk/fs/xfs/xfs_inode.h index 1420c49674d7..17a04b6321ed 100644 --- a/trunk/fs/xfs/xfs_inode.h +++ b/trunk/fs/xfs/xfs_inode.h @@ -87,7 +87,8 @@ typedef struct xfs_ifork { * Flags for xfs_ichgtime(). */ #define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ -#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ +#define XFS_ICHGTIME_ACC 0x2 /* data fork access timestamp */ +#define XFS_ICHGTIME_CHG 0x4 /* inode field change timestamp */ /* * Per-fork incore inode flags. @@ -203,7 +204,7 @@ typedef struct xfs_inode { struct xfs_inode *i_mprev; /* ptr to prev inode */ struct xfs_mount *i_mount; /* fs mount struct ptr */ struct list_head i_reclaim; /* reclaim list */ - struct inode *i_vnode; /* vnode backpointer */ + bhv_vnode_t *i_vnode; /* vnode backpointer */ struct xfs_dquot *i_udquot; /* user dquot */ struct xfs_dquot *i_gdquot; /* group dquot */ @@ -222,7 +223,7 @@ typedef struct xfs_inode { struct xfs_inode_log_item *i_itemp; /* logging information */ mrlock_t i_lock; /* inode lock */ mrlock_t i_iolock; /* inode IO lock */ - struct completion i_flush; /* inode flush completion q */ + sema_t i_flock; /* inode flush lock */ atomic_t i_pincount; /* inode pin count */ wait_queue_head_t i_ipin_wait; /* inode pinning wait queue */ spinlock_t i_flags_lock; /* inode i_flags lock */ @@ -262,18 +263,6 @@ typedef struct xfs_inode { #define XFS_ISIZE(ip) (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \ (ip)->i_size : (ip)->i_d.di_size; -/* Convert from vfs inode to xfs inode */ -static inline struct xfs_inode *XFS_I(struct inode *inode) -{ - return (struct xfs_inode *)inode->i_private; -} - -/* convert from xfs inode to vfs inode */ -static inline struct inode *VFS_I(struct xfs_inode *ip) -{ - return (struct inode *)ip->i_vnode; -} - /* * i_flags helper functions */ @@ -450,6 +439,9 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags) #define XFS_ITRUNC_DEFINITE 0x1 #define XFS_ITRUNC_MAYBE 0x2 +#define XFS_ITOV(ip) ((ip)->i_vnode) +#define XFS_ITOV_NULL(ip) ((ip)->i_vnode) + /* * For multiple groups support: if S_ISGID bit is set in the parent * directory, group of new file is set to that of the parent, and @@ -481,8 +473,11 @@ int xfs_ilock_nowait(xfs_inode_t *, uint); void xfs_iunlock(xfs_inode_t *, uint); void xfs_ilock_demote(xfs_inode_t *, uint); int xfs_isilocked(xfs_inode_t *, uint); +void xfs_iflock(xfs_inode_t *); +int xfs_iflock_nowait(xfs_inode_t *); uint xfs_ilock_map_shared(xfs_inode_t *); void xfs_iunlock_map_shared(xfs_inode_t *, uint); +void xfs_ifunlock(xfs_inode_t *); void xfs_ireclaim(xfs_inode_t *); int xfs_finish_reclaim(xfs_inode_t *, int, int); int xfs_finish_reclaim_all(struct xfs_mount *, int); @@ -527,7 +522,6 @@ void xfs_iflush_all(struct xfs_mount *); void xfs_ichgtime(xfs_inode_t *, int); xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); void xfs_lock_inodes(xfs_inode_t **, int, uint); -void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); void xfs_synchronize_atime(xfs_inode_t *); void xfs_mark_inode_dirty_sync(xfs_inode_t *); @@ -576,26 +570,6 @@ extern struct kmem_zone *xfs_ifork_zone; extern struct kmem_zone *xfs_inode_zone; extern struct kmem_zone *xfs_ili_zone; -/* - * Manage the i_flush queue embedded in the inode. This completion - * queue synchronizes processes attempting to flush the in-core - * inode back to disk. - */ -static inline void xfs_iflock(xfs_inode_t *ip) -{ - wait_for_completion(&ip->i_flush); -} - -static inline int xfs_iflock_nowait(xfs_inode_t *ip) -{ - return try_wait_for_completion(&ip->i_flush); -} - -static inline void xfs_ifunlock(xfs_inode_t *ip) -{ - complete(&ip->i_flush); -} - #endif /* __KERNEL__ */ #endif /* __XFS_INODE_H__ */ diff --git a/trunk/fs/xfs/xfs_inode_item.c b/trunk/fs/xfs/xfs_inode_item.c index 97c7452e2620..0eee08a32c26 100644 --- a/trunk/fs/xfs/xfs_inode_item.c +++ b/trunk/fs/xfs/xfs_inode_item.c @@ -779,10 +779,11 @@ xfs_inode_item_pushbuf( ASSERT(iip->ili_push_owner == current_pid()); /* - * If a flush is not in progress anymore, chances are that the - * inode was taken off the AIL. So, just get out. + * If flushlock isn't locked anymore, chances are that the + * inode flush completed and the inode was taken off the AIL. + * So, just get out. */ - if (completion_done(&ip->i_flush) || + if (!issemalocked(&(ip->i_flock)) || ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); @@ -804,7 +805,7 @@ xfs_inode_item_pushbuf( * If not, we can flush it async. */ dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && - !completion_done(&ip->i_flush)); + issemalocked(&(ip->i_flock))); iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_buftrace("INODE ITEM PUSH", bp); @@ -857,7 +858,7 @@ xfs_inode_item_push( ip = iip->ili_inode; ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); - ASSERT(!completion_done(&ip->i_flush)); + ASSERT(issemalocked(&(ip->i_flock))); /* * Since we were able to lock the inode's flush lock and * we found it on the AIL, the inode must be dirty. This diff --git a/trunk/fs/xfs/xfs_itable.c b/trunk/fs/xfs/xfs_itable.c index cf6754a3c5b3..9a3ef9dcaeb9 100644 --- a/trunk/fs/xfs/xfs_itable.c +++ b/trunk/fs/xfs/xfs_itable.c @@ -59,6 +59,7 @@ xfs_bulkstat_one_iget( { xfs_icdinode_t *dic; /* dinode core info pointer */ xfs_inode_t *ip; /* incore inode pointer */ + bhv_vnode_t *vp; int error; error = xfs_iget(mp, NULL, ino, @@ -71,6 +72,7 @@ xfs_bulkstat_one_iget( ASSERT(ip != NULL); ASSERT(ip->i_blkno != (xfs_daddr_t)0); + vp = XFS_ITOV(ip); dic = &ip->i_d; /* xfs_iget returns the following without needing @@ -83,7 +85,7 @@ xfs_bulkstat_one_iget( buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; - vn_atime_to_bstime(VFS_I(ip), &buf->bs_atime); + vn_atime_to_bstime(vp, &buf->bs_atime); buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; diff --git a/trunk/fs/xfs/xfs_log.c b/trunk/fs/xfs/xfs_log.c index ccba14eb9dbe..91b00a5686cd 100644 --- a/trunk/fs/xfs/xfs_log.c +++ b/trunk/fs/xfs/xfs_log.c @@ -160,7 +160,7 @@ void xlog_trace_iclog(xlog_in_core_t *iclog, uint state) { if (!iclog->ic_trace) - iclog->ic_trace = ktrace_alloc(256, KM_NOFS); + iclog->ic_trace = ktrace_alloc(256, KM_SLEEP); ktrace_enter(iclog->ic_trace, (void *)((unsigned long)state), (void *)((unsigned long)current_pid()), @@ -336,13 +336,16 @@ xfs_log_done(xfs_mount_t *mp, } else { xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)"); xlog_regrant_reserve_log_space(log, ticket); - /* If this ticket was a permanent reservation and we aren't - * trying to release it, reset the inited flags; so next time - * we write, a start record will be written out. - */ - ticket->t_flags |= XLOG_TIC_INITED; } + /* If this ticket was a permanent reservation and we aren't + * trying to release it, reset the inited flags; so next time + * we write, a start record will be written out. + */ + if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) && + (flags & XFS_LOG_REL_PERM_RESERV) == 0) + ticket->t_flags |= XLOG_TIC_INITED; + return lsn; } /* xfs_log_done */ @@ -354,11 +357,11 @@ xfs_log_done(xfs_mount_t *mp, * Asynchronous forces are implemented by setting the WANT_SYNC * bit in the appropriate in-core log and then returning. * - * Synchronous forces are implemented with a signal variable. All callers - * to force a given lsn to disk will wait on a the sv attached to the + * Synchronous forces are implemented with a semaphore. All callers + * to force a given lsn to disk will wait on a semaphore attached to the * specific in-core log. When given in-core log finally completes its * write to disk, that thread will wake up all threads waiting on the - * sv. + * semaphore. */ int _xfs_log_force( @@ -585,12 +588,12 @@ xfs_log_mount( * mp - ubiquitous xfs mount point structure */ int -xfs_log_mount_finish(xfs_mount_t *mp) +xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags) { int error; if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) - error = xlog_recover_finish(mp->m_log); + error = xlog_recover_finish(mp->m_log, mfsi_flags); else { error = 0; ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); @@ -704,7 +707,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) if (!(iclog->ic_state == XLOG_STATE_ACTIVE || iclog->ic_state == XLOG_STATE_DIRTY)) { if (!XLOG_FORCED_SHUTDOWN(log)) { - sv_wait(&iclog->ic_force_wait, PMEM, + sv_wait(&iclog->ic_forcesema, PMEM, &log->l_icloglock, s); } else { spin_unlock(&log->l_icloglock); @@ -745,7 +748,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) || iclog->ic_state == XLOG_STATE_DIRTY || iclog->ic_state == XLOG_STATE_IOERROR) ) { - sv_wait(&iclog->ic_force_wait, PMEM, + sv_wait(&iclog->ic_forcesema, PMEM, &log->l_icloglock, s); } else { spin_unlock(&log->l_icloglock); @@ -835,7 +838,7 @@ xfs_log_move_tail(xfs_mount_t *mp, break; tail_lsn = 0; free_bytes -= tic->t_unit_res; - sv_signal(&tic->t_wait); + sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_write_headq); } @@ -856,7 +859,7 @@ xfs_log_move_tail(xfs_mount_t *mp, break; tail_lsn = 0; free_bytes -= need_bytes; - sv_signal(&tic->t_wait); + sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_reserve_headq); } @@ -1282,8 +1285,8 @@ xlog_alloc_log(xfs_mount_t *mp, ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); - sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); - sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); + sv_init(&iclog->ic_forcesema, SV_DEFAULT, "iclog-force"); + sv_init(&iclog->ic_writesema, SV_DEFAULT, "iclog-write"); iclogp = &iclog->ic_next; } @@ -1562,8 +1565,8 @@ xlog_dealloc_log(xlog_t *log) iclog = log->l_iclog; for (i=0; il_iclog_bufs; i++) { - sv_destroy(&iclog->ic_force_wait); - sv_destroy(&iclog->ic_write_wait); + sv_destroy(&iclog->ic_forcesema); + sv_destroy(&iclog->ic_writesema); xfs_buf_free(iclog->ic_bp); #ifdef XFS_LOG_TRACE if (iclog->ic_trace != NULL) { @@ -1973,7 +1976,7 @@ xlog_write(xfs_mount_t * mp, /* Clean iclogs starting from the head. This ordering must be * maintained, so an iclog doesn't become ACTIVE beyond one that * is SYNCING. This is also required to maintain the notion that we use - * a ordered wait queue to hold off would be writers to the log when every + * a counting semaphore to hold off would be writers to the log when every * iclog is trying to sync to disk. * * State Change: DIRTY -> ACTIVE @@ -2237,7 +2240,7 @@ xlog_state_do_callback( xlog_state_clean_log(log); /* wake up threads waiting in xfs_log_force() */ - sv_broadcast(&iclog->ic_force_wait); + sv_broadcast(&iclog->ic_forcesema); iclog = iclog->ic_next; } while (first_iclog != iclog); @@ -2299,7 +2302,8 @@ xlog_state_do_callback( * the second completion goes through. * * Callbacks could take time, so they are done outside the scope of the - * global state machine log lock. + * global state machine log lock. Assume that the calls to cvsema won't + * take a long time. At least we know it won't sleep. */ STATIC void xlog_state_done_syncing( @@ -2335,7 +2339,7 @@ xlog_state_done_syncing( * iclog buffer, we wake them all, one will get to do the * I/O, the others get to wait for the result. */ - sv_broadcast(&iclog->ic_write_wait); + sv_broadcast(&iclog->ic_writesema); spin_unlock(&log->l_icloglock); xlog_state_do_callback(log, aborted, iclog); /* also cleans log */ } /* xlog_state_done_syncing */ @@ -2343,9 +2347,11 @@ xlog_state_done_syncing( /* * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must - * sleep. We wait on the flush queue on the head iclog as that should be - * the first iclog to complete flushing. Hence if all iclogs are syncing, - * we will wait here and all new writes will sleep until a sync completes. + * sleep. The flush semaphore is set to the number of in-core buffers and + * decremented around disk syncing. Therefore, if all buffers are syncing, + * this semaphore will cause new writes to sleep until a sync completes. + * Otherwise, this code just does p() followed by v(). This approximates + * a sleep/wakeup except we can't race. * * The in-core logs are used in a circular fashion. They are not used * out-of-order even when an iclog past the head is free. @@ -2502,7 +2508,7 @@ xlog_grant_log_space(xlog_t *log, goto error_return; XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); /* * If we got an error, and the filesystem is shutting down, * we'll catch it down below. So just continue... @@ -2528,7 +2534,7 @@ xlog_grant_log_space(xlog_t *log, xlog_trace_loggrant(log, tic, "xlog_grant_log_space: sleep 2"); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); if (XLOG_FORCED_SHUTDOWN(log)) { spin_lock(&log->l_grant_lock); @@ -2627,7 +2633,7 @@ xlog_regrant_write_log_space(xlog_t *log, if (free_bytes < ntic->t_unit_res) break; free_bytes -= ntic->t_unit_res; - sv_signal(&ntic->t_wait); + sv_signal(&ntic->t_sema); ntic = ntic->t_next; } while (ntic != log->l_write_headq); @@ -2638,7 +2644,7 @@ xlog_regrant_write_log_space(xlog_t *log, xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: sleep 1"); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_wait, PINOD|PLTWAIT, + sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already @@ -2667,7 +2673,7 @@ xlog_regrant_write_log_space(xlog_t *log, if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) xlog_ins_ticketq(&log->l_write_headq, tic); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already off the queue */ if (XLOG_FORCED_SHUTDOWN(log)) { @@ -2910,7 +2916,7 @@ xlog_state_switch_iclogs(xlog_t *log, * 2. the current iclog is drity, and the previous iclog is in the * active or dirty state. * - * We may sleep if: + * We may sleep (call psema) if: * * 1. the current iclog is not in the active nor dirty state. * 2. the current iclog dirty, and the previous iclog is not in the @@ -3007,7 +3013,7 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed) return XFS_ERROR(EIO); } XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s); + sv_wait(&iclog->ic_forcesema, PINOD, &log->l_icloglock, s); /* * No need to grab the log lock here since we're * only deciding whether or not to return EIO @@ -3090,7 +3096,7 @@ xlog_state_sync(xlog_t *log, XLOG_STATE_SYNCING))) { ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR)); XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_prev->ic_write_wait, PSWP, + sv_wait(&iclog->ic_prev->ic_writesema, PSWP, &log->l_icloglock, s); *log_flushed = 1; already_slept = 1; @@ -3110,7 +3116,7 @@ xlog_state_sync(xlog_t *log, !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) { /* - * Don't wait on completion if we know that we've + * Don't wait on the forcesema if we know that we've * gotten a log write error. */ if (iclog->ic_state & XLOG_STATE_IOERROR) { @@ -3118,7 +3124,7 @@ xlog_state_sync(xlog_t *log, return XFS_ERROR(EIO); } XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s); + sv_wait(&iclog->ic_forcesema, PSWP, &log->l_icloglock, s); /* * No need to grab the log lock here since we're * only deciding whether or not to return EIO @@ -3174,7 +3180,7 @@ STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket) { - sv_destroy(&ticket->t_wait); + sv_destroy(&ticket->t_sema); kmem_zone_free(xfs_log_ticket_zone, ticket); } /* xlog_ticket_put */ @@ -3264,7 +3270,7 @@ xlog_ticket_get(xlog_t *log, tic->t_trans_type = 0; if (xflags & XFS_LOG_PERM_RESERV) tic->t_flags |= XLOG_TIC_PERM_RESERV; - sv_init(&(tic->t_wait), SV_DEFAULT, "logtick"); + sv_init(&(tic->t_sema), SV_DEFAULT, "logtick"); xlog_tic_reset_res(tic); @@ -3551,14 +3557,14 @@ xfs_log_force_umount( */ if ((tic = log->l_reserve_headq)) { do { - sv_signal(&tic->t_wait); + sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_reserve_headq); } if ((tic = log->l_write_headq)) { do { - sv_signal(&tic->t_wait); + sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_write_headq); } diff --git a/trunk/fs/xfs/xfs_log.h b/trunk/fs/xfs/xfs_log.h index d47b91f10822..d1d678ecb63e 100644 --- a/trunk/fs/xfs/xfs_log.h +++ b/trunk/fs/xfs/xfs_log.h @@ -149,7 +149,7 @@ int xfs_log_mount(struct xfs_mount *mp, struct xfs_buftarg *log_target, xfs_daddr_t start_block, int num_bblocks); -int xfs_log_mount_finish(struct xfs_mount *mp); +int xfs_log_mount_finish(struct xfs_mount *mp, int); void xfs_log_move_tail(struct xfs_mount *mp, xfs_lsn_t tail_lsn); int xfs_log_notify(struct xfs_mount *mp, diff --git a/trunk/fs/xfs/xfs_log_priv.h b/trunk/fs/xfs/xfs_log_priv.h index c8a5b22ee3e3..6245913196b4 100644 --- a/trunk/fs/xfs/xfs_log_priv.h +++ b/trunk/fs/xfs/xfs_log_priv.h @@ -241,7 +241,7 @@ typedef struct xlog_res { } xlog_res_t; typedef struct xlog_ticket { - sv_t t_wait; /* ticket wait queue : 20 */ + sv_t t_sema; /* sleep on this semaphore : 20 */ struct xlog_ticket *t_next; /* :4|8 */ struct xlog_ticket *t_prev; /* :4|8 */ xlog_tid_t t_tid; /* transaction identifier : 4 */ @@ -314,7 +314,7 @@ typedef struct xlog_rec_ext_header { * xlog_rec_header_t into the reserved space. * - ic_data follows, so a write to disk can start at the beginning of * the iclog. - * - ic_forcewait is used to implement synchronous forcing of the iclog to disk. + * - ic_forcesema is used to implement synchronous forcing of the iclog to disk. * - ic_next is the pointer to the next iclog in the ring. * - ic_bp is a pointer to the buffer used to write this incore log to disk. * - ic_log is a pointer back to the global log structure. @@ -339,8 +339,8 @@ typedef struct xlog_rec_ext_header { * and move everything else out to subsequent cachelines. */ typedef struct xlog_iclog_fields { - sv_t ic_force_wait; - sv_t ic_write_wait; + sv_t ic_forcesema; + sv_t ic_writesema; struct xlog_in_core *ic_next; struct xlog_in_core *ic_prev; struct xfs_buf *ic_bp; @@ -377,8 +377,8 @@ typedef struct xlog_in_core { /* * Defines to save our code from this glop. */ -#define ic_force_wait hic_fields.ic_force_wait -#define ic_write_wait hic_fields.ic_write_wait +#define ic_forcesema hic_fields.ic_forcesema +#define ic_writesema hic_fields.ic_writesema #define ic_next hic_fields.ic_next #define ic_prev hic_fields.ic_prev #define ic_bp hic_fields.ic_bp @@ -468,7 +468,7 @@ extern int xlog_find_tail(xlog_t *log, xfs_daddr_t *head_blk, xfs_daddr_t *tail_blk); extern int xlog_recover(xlog_t *log); -extern int xlog_recover_finish(xlog_t *log); +extern int xlog_recover_finish(xlog_t *log, int mfsi_flags); extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); extern void xlog_recover_process_iunlinks(xlog_t *log); diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index 82d46ce69d5f..9eb722ec744e 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -3940,7 +3940,8 @@ xlog_recover( */ int xlog_recover_finish( - xlog_t *log) + xlog_t *log, + int mfsi_flags) { /* * Now we're ready to do the transactions needed for the @@ -3968,7 +3969,9 @@ xlog_recover_finish( xfs_log_force(log->l_mp, (xfs_lsn_t)0, (XFS_LOG_FORCE | XFS_LOG_SYNC)); - xlog_recover_process_iunlinks(log); + if ( (mfsi_flags & XFS_MFSI_NOUNLINK) == 0 ) { + xlog_recover_process_iunlinks(log); + } xlog_recover_check_summary(log); diff --git a/trunk/fs/xfs/xfs_mount.c b/trunk/fs/xfs/xfs_mount.c index a4503f5e9497..6c5d1325e7f6 100644 --- a/trunk/fs/xfs/xfs_mount.c +++ b/trunk/fs/xfs/xfs_mount.c @@ -128,7 +128,7 @@ static const struct { * initialized. */ STATIC void -xfs_free_perag( +xfs_mount_free( xfs_mount_t *mp) { if (mp->m_perag) { @@ -139,6 +139,20 @@ xfs_free_perag( kmem_free(mp->m_perag[agno].pagb_list); kmem_free(mp->m_perag); } + + spinlock_destroy(&mp->m_ail_lock); + spinlock_destroy(&mp->m_sb_lock); + mutex_destroy(&mp->m_ilock); + mutex_destroy(&mp->m_growlock); + if (mp->m_quotainfo) + XFS_QM_DONE(mp); + + if (mp->m_fsname != NULL) + kmem_free(mp->m_fsname); + if (mp->m_rtname != NULL) + kmem_free(mp->m_rtname); + if (mp->m_logname != NULL) + kmem_free(mp->m_logname); } /* @@ -690,11 +704,11 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) * Update alignment values based on mount options and sb values */ STATIC int -xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags) +xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags) { xfs_sb_t *sbp = &(mp->m_sb); - if (mp->m_dalign) { + if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) { /* * If stripe unit and stripe width are not multiples * of the fs blocksize turn off alignment. @@ -850,7 +864,7 @@ xfs_set_inoalignment(xfs_mount_t *mp) * Check that the data (and log if separate) are an ok size. */ STATIC int -xfs_check_sizes(xfs_mount_t *mp) +xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags) { xfs_buf_t *bp; xfs_daddr_t d; @@ -873,7 +887,8 @@ xfs_check_sizes(xfs_mount_t *mp) return error; } - if (mp->m_logdev_targp != mp->m_ddev_targp) { + if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) && + mp->m_logdev_targp != mp->m_ddev_targp) { d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { cmn_err(CE_WARN, "XFS: size check 3 failed"); @@ -908,13 +923,15 @@ xfs_check_sizes(xfs_mount_t *mp) */ int xfs_mountfs( - xfs_mount_t *mp) + xfs_mount_t *mp, + int mfsi_flags) { xfs_sb_t *sbp = &(mp->m_sb); xfs_inode_t *rip; __uint64_t resblks; __int64_t update_flags = 0LL; uint quotamount, quotaflags; + int agno; int uuid_mounted = 0; int error = 0; @@ -968,7 +985,7 @@ xfs_mountfs( * allocator alignment is within an ag, therefore ag has * to be aligned at stripe boundary. */ - error = xfs_update_alignment(mp, &update_flags); + error = xfs_update_alignment(mp, mfsi_flags, &update_flags); if (error) goto error1; @@ -987,7 +1004,8 @@ xfs_mountfs( * since a single partition filesystem is identical to a single * partition volume/filesystem. */ - if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) { + if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && + (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { if (xfs_uuid_mount(mp)) { error = XFS_ERROR(EINVAL); goto error1; @@ -1015,7 +1033,7 @@ xfs_mountfs( /* * Check that the data (and log if separate) are an ok size. */ - error = xfs_check_sizes(mp); + error = xfs_check_sizes(mp, mfsi_flags); if (error) goto error1; @@ -1028,6 +1046,13 @@ xfs_mountfs( goto error1; } + /* + * For client case we are done now + */ + if (mfsi_flags & XFS_MFSI_CLIENT) { + return 0; + } + /* * Copies the low order bits of the timestamp and the randomly * set "sequence" number out of a UUID. @@ -1052,10 +1077,8 @@ xfs_mountfs( * Allocate and initialize the per-ag data. */ init_rwsem(&mp->m_peraglock); - mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), - KM_MAYFAIL); - if (!mp->m_perag) - goto error1; + mp->m_perag = + kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP); mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); @@ -1167,7 +1190,7 @@ xfs_mountfs( * delayed until after the root and real-time bitmap inodes * were consistently read in. */ - error = xfs_log_mount_finish(mp); + error = xfs_log_mount_finish(mp, mfsi_flags); if (error) { cmn_err(CE_WARN, "XFS: log mount finish failed"); goto error4; @@ -1176,7 +1199,7 @@ xfs_mountfs( /* * Complete the quota initialisation, post-log-replay component. */ - error = XFS_QM_MOUNT(mp, quotamount, quotaflags); + error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags); if (error) goto error4; @@ -1210,7 +1233,12 @@ xfs_mountfs( error3: xfs_log_unmount_dealloc(mp); error2: - xfs_free_perag(mp); + for (agno = 0; agno < sbp->sb_agcount; agno++) + if (mp->m_perag[agno].pagb_list) + kmem_free(mp->m_perag[agno].pagb_list); + kmem_free(mp->m_perag); + mp->m_perag = NULL; + /* FALLTHROUGH */ error1: if (uuid_mounted) uuid_table_remove(&mp->m_sb.sb_uuid); @@ -1218,17 +1246,16 @@ xfs_mountfs( } /* + * xfs_unmountfs + * * This flushes out the inodes,dquots and the superblock, unmounts the * log and makes sure that incore structures are freed. */ -void -xfs_unmountfs( - struct xfs_mount *mp) +int +xfs_unmountfs(xfs_mount_t *mp) { - __uint64_t resblks; - int error; - - IRELE(mp->m_rootip); + __uint64_t resblks; + int error = 0; /* * We can potentially deadlock here if we have an inode cluster @@ -1285,6 +1312,8 @@ xfs_unmountfs( xfs_unmountfs_wait(mp); /* wait for async bufs */ xfs_log_unmount(mp); /* Done! No more fs ops. */ + xfs_freesb(mp); + /* * All inodes from this mount point should be freed. */ @@ -1293,12 +1322,11 @@ xfs_unmountfs( if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) uuid_table_remove(&mp->m_sb.sb_uuid); -#if defined(DEBUG) +#if defined(DEBUG) || defined(INDUCE_IO_ERROR) xfs_errortag_clearall(mp, 0); #endif - xfs_free_perag(mp); - if (mp->m_quotainfo) - XFS_QM_DONE(mp); + xfs_mount_free(mp); + return 0; } STATIC void diff --git a/trunk/fs/xfs/xfs_mount.h b/trunk/fs/xfs/xfs_mount.h index f3c1024b1241..5269bd6e3df0 100644 --- a/trunk/fs/xfs/xfs_mount.h +++ b/trunk/fs/xfs/xfs_mount.h @@ -114,7 +114,7 @@ struct xfs_dqtrxops; struct xfs_quotainfo; typedef int (*xfs_qminit_t)(struct xfs_mount *, uint *, uint *); -typedef int (*xfs_qmmount_t)(struct xfs_mount *, uint, uint); +typedef int (*xfs_qmmount_t)(struct xfs_mount *, uint, uint, int); typedef int (*xfs_qmunmount_t)(struct xfs_mount *); typedef void (*xfs_qmdone_t)(struct xfs_mount *); typedef void (*xfs_dqrele_t)(struct xfs_dquot *); @@ -158,8 +158,8 @@ typedef struct xfs_qmops { #define XFS_QM_INIT(mp, mnt, fl) \ (*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl) -#define XFS_QM_MOUNT(mp, mnt, fl) \ - (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl) +#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \ + (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags) #define XFS_QM_UNMOUNT(mp) \ (*(mp)->m_qm_ops->xfs_qmunmount)(mp) #define XFS_QM_DONE(mp) \ @@ -442,6 +442,13 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, /* * Flags for xfs_mountfs */ +#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ +#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ +/* XFS_MFSI_RRINODES */ +#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ + /* log recovery */ +#define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */ +/* XFS_MFSI_CONVERT_SUNIT */ #define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */ #define XFS_DADDR_TO_AGNO(mp,d) xfs_daddr_to_agno(mp,d) @@ -510,10 +517,10 @@ typedef struct xfs_mod_sb { extern void xfs_mod_sb(xfs_trans_t *, __int64_t); extern int xfs_log_sbcount(xfs_mount_t *, uint); -extern int xfs_mountfs(xfs_mount_t *mp); +extern int xfs_mountfs(xfs_mount_t *mp, int); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); -extern void xfs_unmountfs(xfs_mount_t *); +extern int xfs_unmountfs(xfs_mount_t *); extern int xfs_unmountfs_writesb(xfs_mount_t *); extern int xfs_unmount_flush(xfs_mount_t *, int); extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); diff --git a/trunk/fs/xfs/xfs_rtalloc.c b/trunk/fs/xfs/xfs_rtalloc.c index e2f68de16159..bf87a5913504 100644 --- a/trunk/fs/xfs/xfs_rtalloc.c +++ b/trunk/fs/xfs/xfs_rtalloc.c @@ -73,6 +73,18 @@ STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int, * Internal functions. */ +/* + * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set. + */ +STATIC int +xfs_lowbit32( + __uint32_t v) +{ + if (v) + return ffs(v) - 1; + return -1; +} + /* * Allocate space to the bitmap or summary file, and zero it, for growfs. */ @@ -438,7 +450,6 @@ xfs_rtallocate_extent_near( } bbno = XFS_BITTOBLOCK(mp, bno); i = 0; - ASSERT(minlen != 0); log2len = xfs_highbit32(minlen); /* * Loop over all bitmap blocks (bbno + i is current block). @@ -607,8 +618,6 @@ xfs_rtallocate_extent_size( xfs_suminfo_t sum; /* summary information for extents */ ASSERT(minlen % prod == 0 && maxlen % prod == 0); - ASSERT(maxlen != 0); - /* * Loop over all the levels starting with maxlen. * At each level, look at all the bitmap blocks, to see if there @@ -666,9 +675,6 @@ xfs_rtallocate_extent_size( *rtblock = NULLRTBLOCK; return 0; } - ASSERT(minlen != 0); - ASSERT(maxlen != 0); - /* * Loop over sizes, from maxlen down to minlen. * This time, when we do the allocations, allow smaller ones @@ -1955,7 +1961,6 @@ xfs_growfs_rt( nsbp->sb_blocksize * nsbp->sb_rextsize); nsbp->sb_rextents = nsbp->sb_rblocks; do_div(nsbp->sb_rextents, nsbp->sb_rextsize); - ASSERT(nsbp->sb_rextents != 0); nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents); nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1; nrsumsize = diff --git a/trunk/fs/xfs/xfs_rw.c b/trunk/fs/xfs/xfs_rw.c index 3a82576dde9a..b0f31c09a76d 100644 --- a/trunk/fs/xfs/xfs_rw.c +++ b/trunk/fs/xfs/xfs_rw.c @@ -314,7 +314,7 @@ xfs_bioerror_relse( * ASYNC buffers. */ XFS_BUF_ERROR(bp, EIO); - XFS_BUF_FINISH_IOWAIT(bp); + XFS_BUF_V_IODONESEMA(bp); } else { xfs_buf_relse(bp); } diff --git a/trunk/fs/xfs/xfs_trans.c b/trunk/fs/xfs/xfs_trans.c index 4e1c22a23be5..e4ebddd3c500 100644 --- a/trunk/fs/xfs/xfs_trans.c +++ b/trunk/fs/xfs/xfs_trans.c @@ -43,7 +43,6 @@ #include "xfs_quota.h" #include "xfs_trans_priv.h" #include "xfs_trans_space.h" -#include "xfs_inode_item.h" STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); @@ -254,7 +253,7 @@ _xfs_trans_alloc( tp->t_mountp = mp; tp->t_items_free = XFS_LIC_NUM_SLOTS; tp->t_busy_free = XFS_LBC_NUM_SLOTS; - xfs_lic_init(&(tp->t_items)); + XFS_LIC_INIT(&(tp->t_items)); XFS_LBC_INIT(&(tp->t_busy)); return tp; } @@ -283,7 +282,7 @@ xfs_trans_dup( ntp->t_mountp = tp->t_mountp; ntp->t_items_free = XFS_LIC_NUM_SLOTS; ntp->t_busy_free = XFS_LBC_NUM_SLOTS; - xfs_lic_init(&(ntp->t_items)); + XFS_LIC_INIT(&(ntp->t_items)); XFS_LBC_INIT(&(ntp->t_busy)); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); @@ -1170,7 +1169,7 @@ xfs_trans_cancel( while (licp != NULL) { lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } @@ -1217,68 +1216,6 @@ xfs_trans_free( kmem_zone_free(xfs_trans_zone, tp); } -/* - * Roll from one trans in the sequence of PERMANENT transactions to - * the next: permanent transactions are only flushed out when - * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon - * as possible to let chunks of it go to the log. So we commit the - * chunk we've been working on and get a new transaction to continue. - */ -int -xfs_trans_roll( - struct xfs_trans **tpp, - struct xfs_inode *dp) -{ - struct xfs_trans *trans; - unsigned int logres, count; - int error; - - /* - * Ensure that the inode is always logged. - */ - trans = *tpp; - xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); - - /* - * Copy the critical parameters from one trans to the next. - */ - logres = trans->t_log_res; - count = trans->t_log_count; - *tpp = xfs_trans_dup(trans); - - /* - * Commit the current transaction. - * If this commit failed, then it'd just unlock those items that - * are not marked ihold. That also means that a filesystem shutdown - * is in progress. The caller takes the responsibility to cancel - * the duplicate transaction that gets returned. - */ - error = xfs_trans_commit(trans, 0); - if (error) - return (error); - - trans = *tpp; - - /* - * Reserve space in the log for th next transaction. - * This also pushes items in the "AIL", the list of logged items, - * out to disk if they are taking up space at the tail of the log - * that we want to use. This requires that either nothing be locked - * across this call, or that anything that is locked be logged in - * the prior and the next transactions. - */ - error = xfs_trans_reserve(trans, 0, logres, 0, - XFS_TRANS_PERM_LOG_RES, count); - /* - * Ensure that the inode is in the new transaction and locked. - */ - if (error) - return error; - - xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); - xfs_trans_ihold(trans, dp); - return 0; -} /* * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item(). @@ -1316,7 +1253,7 @@ xfs_trans_committed( * Special case the chunk embedded in the transaction. */ licp = &(tp->t_items); - if (!(xfs_lic_are_all_free(licp))) { + if (!(XFS_LIC_ARE_ALL_FREE(licp))) { xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); } @@ -1325,7 +1262,7 @@ xfs_trans_committed( */ licp = licp->lic_next; while (licp != NULL) { - ASSERT(!xfs_lic_are_all_free(licp)); + ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); next_licp = licp->lic_next; kmem_free(licp); @@ -1388,7 +1325,7 @@ xfs_trans_chunk_committed( lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } diff --git a/trunk/fs/xfs/xfs_trans.h b/trunk/fs/xfs/xfs_trans.h index 74c80bd2b0ec..0804207c7391 100644 --- a/trunk/fs/xfs/xfs_trans.h +++ b/trunk/fs/xfs/xfs_trans.h @@ -210,52 +210,62 @@ typedef struct xfs_log_item_chunk { * lic_unused to the right value (0 matches all free). The * lic_descs.lid_index values are set up as each desc is allocated. */ +#define XFS_LIC_INIT(cp) xfs_lic_init(cp) static inline void xfs_lic_init(xfs_log_item_chunk_t *cp) { cp->lic_free = XFS_LIC_FREEMASK; } +#define XFS_LIC_INIT_SLOT(cp,slot) xfs_lic_init_slot(cp, slot) static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot) { cp->lic_descs[slot].lid_index = (unsigned char)(slot); } +#define XFS_LIC_VACANCY(cp) xfs_lic_vacancy(cp) static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp) { return cp->lic_free & XFS_LIC_FREEMASK; } +#define XFS_LIC_ALL_FREE(cp) xfs_lic_all_free(cp) static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp) { cp->lic_free = XFS_LIC_FREEMASK; } +#define XFS_LIC_ARE_ALL_FREE(cp) xfs_lic_are_all_free(cp) static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp) { return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK); } +#define XFS_LIC_ISFREE(cp,slot) xfs_lic_isfree(cp,slot) static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot) { return (cp->lic_free & (1 << slot)); } +#define XFS_LIC_CLAIM(cp,slot) xfs_lic_claim(cp,slot) static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot) { cp->lic_free &= ~(1 << slot); } +#define XFS_LIC_RELSE(cp,slot) xfs_lic_relse(cp,slot) static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot) { cp->lic_free |= 1 << slot; } +#define XFS_LIC_SLOT(cp,slot) xfs_lic_slot(cp,slot) static inline xfs_log_item_desc_t * xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot) { return &(cp->lic_descs[slot]); } +#define XFS_LIC_DESC_TO_SLOT(dp) xfs_lic_desc_to_slot(dp) static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp) { return (uint)dp->lid_index; @@ -268,6 +278,7 @@ static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp) * All of this yields the address of the chunk, which is * cast to a chunk pointer. */ +#define XFS_LIC_DESC_TO_CHUNK(dp) xfs_lic_desc_to_chunk(dp) static inline xfs_log_item_chunk_t * xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) { @@ -975,7 +986,6 @@ int _xfs_trans_commit(xfs_trans_t *, int *); #define xfs_trans_commit(tp, flags) _xfs_trans_commit(tp, flags, NULL) void xfs_trans_cancel(xfs_trans_t *, int); -int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); int xfs_trans_ail_init(struct xfs_mount *); void xfs_trans_ail_destroy(struct xfs_mount *); void xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t); diff --git a/trunk/fs/xfs/xfs_trans_buf.c b/trunk/fs/xfs/xfs_trans_buf.c index 4e855b5ced66..cb0c5839154b 100644 --- a/trunk/fs/xfs/xfs_trans_buf.c +++ b/trunk/fs/xfs/xfs_trans_buf.c @@ -1021,16 +1021,16 @@ xfs_trans_buf_item_match( bp = NULL; len = BBTOB(len); licp = &tp->t_items; - if (!xfs_lic_are_all_free(licp)) { + if (!XFS_LIC_ARE_ALL_FREE(licp)) { for (i = 0; i < licp->lic_unused; i++) { /* * Skip unoccupied slots. */ - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - lidp = xfs_lic_slot(licp, i); + lidp = XFS_LIC_SLOT(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; @@ -1074,7 +1074,7 @@ xfs_trans_buf_item_match_all( bp = NULL; len = BBTOB(len); for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { - if (xfs_lic_are_all_free(licp)) { + if (XFS_LIC_ARE_ALL_FREE(licp)) { ASSERT(licp == &tp->t_items); ASSERT(licp->lic_next == NULL); return NULL; @@ -1083,11 +1083,11 @@ xfs_trans_buf_item_match_all( /* * Skip unoccupied slots. */ - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - lidp = xfs_lic_slot(licp, i); + lidp = XFS_LIC_SLOT(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; diff --git a/trunk/fs/xfs/xfs_trans_item.c b/trunk/fs/xfs/xfs_trans_item.c index 3c666e8317f8..db5c83595526 100644 --- a/trunk/fs/xfs/xfs_trans_item.c +++ b/trunk/fs/xfs/xfs_trans_item.c @@ -53,11 +53,11 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) * Initialize the chunk, and then * claim the first slot in the newly allocated chunk. */ - xfs_lic_init(licp); - xfs_lic_claim(licp, 0); + XFS_LIC_INIT(licp); + XFS_LIC_CLAIM(licp, 0); licp->lic_unused = 1; - xfs_lic_init_slot(licp, 0); - lidp = xfs_lic_slot(licp, 0); + XFS_LIC_INIT_SLOT(licp, 0); + lidp = XFS_LIC_SLOT(licp, 0); /* * Link in the new chunk and update the free count. @@ -88,14 +88,14 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) */ licp = &tp->t_items; while (licp != NULL) { - if (xfs_lic_vacancy(licp)) { + if (XFS_LIC_VACANCY(licp)) { if (licp->lic_unused <= XFS_LIC_MAX_SLOT) { i = licp->lic_unused; - ASSERT(xfs_lic_isfree(licp, i)); + ASSERT(XFS_LIC_ISFREE(licp, i)); break; } for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) { - if (xfs_lic_isfree(licp, i)) + if (XFS_LIC_ISFREE(licp, i)) break; } ASSERT(i <= XFS_LIC_MAX_SLOT); @@ -108,12 +108,12 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) * If we find a free descriptor, claim it, * initialize it, and return it. */ - xfs_lic_claim(licp, i); + XFS_LIC_CLAIM(licp, i); if (licp->lic_unused <= i) { licp->lic_unused = i + 1; - xfs_lic_init_slot(licp, i); + XFS_LIC_INIT_SLOT(licp, i); } - lidp = xfs_lic_slot(licp, i); + lidp = XFS_LIC_SLOT(licp, i); tp->t_items_free--; lidp->lid_item = lip; lidp->lid_flags = 0; @@ -136,9 +136,9 @@ xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) xfs_log_item_chunk_t *licp; xfs_log_item_chunk_t **licpp; - slot = xfs_lic_desc_to_slot(lidp); - licp = xfs_lic_desc_to_chunk(lidp); - xfs_lic_relse(licp, slot); + slot = XFS_LIC_DESC_TO_SLOT(lidp); + licp = XFS_LIC_DESC_TO_CHUNK(lidp); + XFS_LIC_RELSE(licp, slot); lidp->lid_item->li_desc = NULL; tp->t_items_free++; @@ -154,7 +154,7 @@ xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) * Also decrement the transaction structure's count of free items * by the number in a chunk since we are freeing an empty chunk. */ - if (xfs_lic_are_all_free(licp) && (licp != &(tp->t_items))) { + if (XFS_LIC_ARE_ALL_FREE(licp) && (licp != &(tp->t_items))) { licpp = &(tp->t_items.lic_next); while (*licpp != licp) { ASSERT(*licpp != NULL); @@ -207,20 +207,20 @@ xfs_trans_first_item(xfs_trans_t *tp) /* * If it's not in the first chunk, skip to the second. */ - if (xfs_lic_are_all_free(licp)) { + if (XFS_LIC_ARE_ALL_FREE(licp)) { licp = licp->lic_next; } /* * Return the first non-free descriptor in the chunk. */ - ASSERT(!xfs_lic_are_all_free(licp)); + ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); for (i = 0; i < licp->lic_unused; i++) { - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - return xfs_lic_slot(licp, i); + return XFS_LIC_SLOT(licp, i); } cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item"); return NULL; @@ -242,18 +242,18 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) xfs_log_item_chunk_t *licp; int i; - licp = xfs_lic_desc_to_chunk(lidp); + licp = XFS_LIC_DESC_TO_CHUNK(lidp); /* * First search the rest of the chunk. The for loop keeps us * from referencing things beyond the end of the chunk. */ - for (i = (int)xfs_lic_desc_to_slot(lidp) + 1; i < licp->lic_unused; i++) { - if (xfs_lic_isfree(licp, i)) { + for (i = (int)XFS_LIC_DESC_TO_SLOT(lidp) + 1; i < licp->lic_unused; i++) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - return xfs_lic_slot(licp, i); + return XFS_LIC_SLOT(licp, i); } /* @@ -266,13 +266,13 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) } licp = licp->lic_next; - ASSERT(!xfs_lic_are_all_free(licp)); + ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); for (i = 0; i < licp->lic_unused; i++) { - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } - return xfs_lic_slot(licp, i); + return XFS_LIC_SLOT(licp, i); } ASSERT(0); /* NOTREACHED */ @@ -300,9 +300,9 @@ xfs_trans_free_items( /* * Special case the embedded chunk so we don't free it below. */ - if (!xfs_lic_are_all_free(licp)) { + if (!XFS_LIC_ARE_ALL_FREE(licp)) { (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN); - xfs_lic_all_free(licp); + XFS_LIC_ALL_FREE(licp); licp->lic_unused = 0; } licp = licp->lic_next; @@ -311,7 +311,7 @@ xfs_trans_free_items( * Unlock each item in each chunk and free the chunks. */ while (licp != NULL) { - ASSERT(!xfs_lic_are_all_free(licp)); + ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN); next_licp = licp->lic_next; kmem_free(licp); @@ -347,7 +347,7 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn) /* * Special case the embedded chunk so we don't free. */ - if (!xfs_lic_are_all_free(licp)) { + if (!XFS_LIC_ARE_ALL_FREE(licp)) { freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); } licpp = &(tp->t_items.lic_next); @@ -358,10 +358,10 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn) * and free empty chunks. */ while (licp != NULL) { - ASSERT(!xfs_lic_are_all_free(licp)); + ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); next_licp = licp->lic_next; - if (xfs_lic_are_all_free(licp)) { + if (XFS_LIC_ARE_ALL_FREE(licp)) { *licpp = next_licp; kmem_free(licp); freed -= XFS_LIC_NUM_SLOTS; @@ -402,7 +402,7 @@ xfs_trans_unlock_chunk( freed = 0; lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (xfs_lic_isfree(licp, i)) { + if (XFS_LIC_ISFREE(licp, i)) { continue; } lip = lidp->lid_item; @@ -421,7 +421,7 @@ xfs_trans_unlock_chunk( */ if (!(freeing_chunk) && (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) { - xfs_lic_relse(licp, i); + XFS_LIC_RELSE(licp, i); freed++; } } diff --git a/trunk/fs/xfs/xfs_utils.c b/trunk/fs/xfs/xfs_utils.c index 35d4d414bcc2..98e5f110ba5f 100644 --- a/trunk/fs/xfs/xfs_utils.c +++ b/trunk/fs/xfs/xfs_utils.c @@ -237,7 +237,7 @@ xfs_droplink( ASSERT (ip->i_d.di_nlink > 0); ip->i_d.di_nlink--; - drop_nlink(VFS_I(ip)); + drop_nlink(ip->i_vnode); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = 0; @@ -301,7 +301,7 @@ xfs_bumplink( ASSERT(ip->i_d.di_nlink > 0); ip->i_d.di_nlink++; - inc_nlink(VFS_I(ip)); + inc_nlink(ip->i_vnode); if ((ip->i_d.di_version == XFS_DINODE_VERSION_1) && (ip->i_d.di_nlink > XFS_MAXLINK_1)) { /* diff --git a/trunk/fs/xfs/xfs_utils.h b/trunk/fs/xfs/xfs_utils.h index ef321225d269..f316cb85d8e2 100644 --- a/trunk/fs/xfs/xfs_utils.h +++ b/trunk/fs/xfs/xfs_utils.h @@ -18,6 +18,9 @@ #ifndef __XFS_UTILS_H__ #define __XFS_UTILS_H__ +#define IRELE(ip) VN_RELE(XFS_ITOV(ip)) +#define IHOLD(ip) VN_HOLD(XFS_ITOV(ip)) + extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *); extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, xfs_dev_t, cred_t *, prid_t, int, diff --git a/trunk/fs/xfs/xfs_vfsops.c b/trunk/fs/xfs/xfs_vfsops.c index 439dd3939dda..4a9a43315a86 100644 --- a/trunk/fs/xfs/xfs_vfsops.c +++ b/trunk/fs/xfs/xfs_vfsops.c @@ -128,6 +128,7 @@ xfs_unmount_flush( xfs_inode_t *rip = mp->m_rootip; xfs_inode_t *rbmip; xfs_inode_t *rsumip = NULL; + bhv_vnode_t *rvp = XFS_ITOV(rip); int error; xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); @@ -145,7 +146,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out; - ASSERT(vn_count(VFS_I(rbmip)) == 1); + ASSERT(vn_count(XFS_ITOV(rbmip)) == 1); rsumip = mp->m_rsumip; xfs_ilock(rsumip, XFS_ILOCK_EXCL); @@ -156,7 +157,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out; - ASSERT(vn_count(VFS_I(rsumip)) == 1); + ASSERT(vn_count(XFS_ITOV(rsumip)) == 1); } /* @@ -166,7 +167,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out2; - if (vn_count(VFS_I(rip)) != 1 && !relocation) { + if (vn_count(rvp) != 1 && !relocation) { xfs_iunlock(rip, XFS_ILOCK_EXCL); return XFS_ERROR(EBUSY); } @@ -283,7 +284,7 @@ xfs_sync_inodes( int *bypassed) { xfs_inode_t *ip = NULL; - struct inode *vp = NULL; + bhv_vnode_t *vp = NULL; int error; int last_error; uint64_t fflag; @@ -403,7 +404,7 @@ xfs_sync_inodes( continue; } - vp = VFS_I(ip); + vp = XFS_ITOV_NULL(ip); /* * If the vnode is gone then this is being torn down, @@ -478,7 +479,7 @@ xfs_sync_inodes( IPOINTER_INSERT(ip, mp); xfs_ilock(ip, lock_flags); - ASSERT(vp == VFS_I(ip)); + ASSERT(vp == XFS_ITOV(ip)); ASSERT(ip->i_mount == mp); vnode_refed = B_TRUE; diff --git a/trunk/fs/xfs/xfs_vnodeops.c b/trunk/fs/xfs/xfs_vnodeops.c index 588bb4aa215d..76a1166af822 100644 --- a/trunk/fs/xfs/xfs_vnodeops.c +++ b/trunk/fs/xfs/xfs_vnodeops.c @@ -83,7 +83,7 @@ xfs_setattr( cred_t *credp) { xfs_mount_t *mp = ip->i_mount; - struct inode *inode = VFS_I(ip); + struct inode *inode = XFS_ITOV(ip); int mask = iattr->ia_valid; xfs_trans_t *tp; int code; @@ -513,6 +513,7 @@ xfs_setattr( ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec; ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec; ip->i_update_core = 1; + timeflags &= ~XFS_ICHGTIME_ACC; } if (mask & ATTR_MTIME) { inode->i_mtime = iattr->ia_mtime; @@ -713,7 +714,7 @@ xfs_fsync( return XFS_ERROR(EIO); /* capture size updates in I/O completion before writing the inode. */ - error = filemap_fdatawait(VFS_I(ip)->i_mapping); + error = filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping); if (error) return XFS_ERROR(error); @@ -1159,6 +1160,7 @@ int xfs_release( xfs_inode_t *ip) { + bhv_vnode_t *vp = XFS_ITOV(ip); xfs_mount_t *mp = ip->i_mount; int error; @@ -1193,13 +1195,13 @@ xfs_release( * be exposed to that problem. */ truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); - if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) + if (truncated && VN_DIRTY(vp) && ip->i_delayed_blks > 0) xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE); } if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || + ((ip->i_size > 0) || (VN_CACHED(vp) > 0 || ip->i_delayed_blks > 0)) && (ip->i_df.if_flags & XFS_IFEXTENTS)) && (!(ip->i_d.di_flags & @@ -1225,6 +1227,7 @@ int xfs_inactive( xfs_inode_t *ip) { + bhv_vnode_t *vp = XFS_ITOV(ip); xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int committed; @@ -1239,7 +1242,7 @@ xfs_inactive( * If the inode is already free, then there can be nothing * to clean up here. */ - if (ip->i_d.di_mode == 0 || VN_BAD(VFS_I(ip))) { + if (ip->i_d.di_mode == 0 || VN_BAD(vp)) { ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0); return VN_INACTIVE_CACHE; @@ -1269,7 +1272,7 @@ xfs_inactive( if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || + ((ip->i_size > 0) || (VN_CACHED(vp) > 0 || ip->i_delayed_blks > 0)) && (ip->i_df.if_flags & XFS_IFEXTENTS) && (!(ip->i_d.di_flags & @@ -1704,6 +1707,111 @@ xfs_create( goto std_return; } +#ifdef DEBUG +/* + * Some counters to see if (and how often) we are hitting some deadlock + * prevention code paths. + */ + +int xfs_rm_locks; +int xfs_rm_lock_delays; +int xfs_rm_attempts; +#endif + +/* + * The following routine will lock the inodes associated with the + * directory and the named entry in the directory. The locks are + * acquired in increasing inode number. + * + * If the entry is "..", then only the directory is locked. The + * vnode ref count will still include that from the .. entry in + * this case. + * + * There is a deadlock we need to worry about. If the locked directory is + * in the AIL, it might be blocking up the log. The next inode we lock + * could be already locked by another thread waiting for log space (e.g + * a permanent log reservation with a long running transaction (see + * xfs_itruncate_finish)). To solve this, we must check if the directory + * is in the ail and use lock_nowait. If we can't lock, we need to + * drop the inode lock on the directory and try again. xfs_iunlock will + * potentially push the tail if we were holding up the log. + */ +STATIC int +xfs_lock_dir_and_entry( + xfs_inode_t *dp, + xfs_inode_t *ip) /* inode of entry 'name' */ +{ + int attempts; + xfs_ino_t e_inum; + xfs_inode_t *ips[2]; + xfs_log_item_t *lp; + +#ifdef DEBUG + xfs_rm_locks++; +#endif + attempts = 0; + +again: + xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); + + e_inum = ip->i_ino; + + xfs_itrace_ref(ip); + + /* + * We want to lock in increasing inum. Since we've already + * acquired the lock on the directory, we may need to release + * if if the inum of the entry turns out to be less. + */ + if (e_inum > dp->i_ino) { + /* + * We are already in the right order, so just + * lock on the inode of the entry. + * We need to use nowait if dp is in the AIL. + */ + + lp = (xfs_log_item_t *)dp->i_itemp; + if (lp && (lp->li_flags & XFS_LI_IN_AIL)) { + if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { + attempts++; +#ifdef DEBUG + xfs_rm_attempts++; +#endif + + /* + * Unlock dp and try again. + * xfs_iunlock will try to push the tail + * if the inode is in the AIL. + */ + + xfs_iunlock(dp, XFS_ILOCK_EXCL); + + if ((attempts % 5) == 0) { + delay(1); /* Don't just spin the CPU */ +#ifdef DEBUG + xfs_rm_lock_delays++; +#endif + } + goto again; + } + } else { + xfs_ilock(ip, XFS_ILOCK_EXCL); + } + } else if (e_inum < dp->i_ino) { + xfs_iunlock(dp, XFS_ILOCK_EXCL); + + ips[0] = ip; + ips[1] = dp; + xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); + } + /* else e_inum == dp->i_ino */ + /* This can happen if we're asked to lock /x/.. + * the entry is "..", which is also the parent directory. + */ + + return 0; +} + #ifdef DEBUG int xfs_locked_n; int xfs_small_retries; @@ -1838,45 +1946,6 @@ xfs_lock_inodes( #endif } -void -xfs_lock_two_inodes( - xfs_inode_t *ip0, - xfs_inode_t *ip1, - uint lock_mode) -{ - xfs_inode_t *temp; - int attempts = 0; - xfs_log_item_t *lp; - - ASSERT(ip0->i_ino != ip1->i_ino); - - if (ip0->i_ino > ip1->i_ino) { - temp = ip0; - ip0 = ip1; - ip1 = temp; - } - - again: - xfs_ilock(ip0, xfs_lock_inumorder(lock_mode, 0)); - - /* - * If the first lock we have locked is in the AIL, we must TRY to get - * the second lock. If we can't get it, we must release the first one - * and try again. - */ - lp = (xfs_log_item_t *)ip0->i_itemp; - if (lp && (lp->li_flags & XFS_LI_IN_AIL)) { - if (!xfs_ilock_nowait(ip1, xfs_lock_inumorder(lock_mode, 1))) { - xfs_iunlock(ip0, lock_mode); - if ((++attempts % 5) == 0) - delay(1); /* Don't just spin the CPU */ - goto again; - } - } else { - xfs_ilock(ip1, xfs_lock_inumorder(lock_mode, 1)); - } -} - int xfs_remove( xfs_inode_t *dp, @@ -1949,7 +2018,9 @@ xfs_remove( goto out_trans_cancel; } - xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); + error = xfs_lock_dir_and_entry(dp, ip); + if (error) + goto out_trans_cancel; /* * At this point, we've gotten both the directory and the entry @@ -1976,6 +2047,9 @@ xfs_remove( } } + /* + * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. + */ XFS_BMAP_INIT(&free_list, &first_block); error = xfs_dir_removename(tp, dp, name, ip->i_ino, &first_block, &free_list, resblks); @@ -2081,6 +2155,7 @@ xfs_link( { xfs_mount_t *mp = tdp->i_mount; xfs_trans_t *tp; + xfs_inode_t *ips[2]; int error; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; @@ -2128,7 +2203,15 @@ xfs_link( goto error_return; } - xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); + if (sip->i_ino < tdp->i_ino) { + ips[0] = sip; + ips[1] = tdp; + } else { + ips[0] = tdp; + ips[1] = sip; + } + + xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); /* * Increment vnode ref counts since xfs_trans_commit & @@ -2790,13 +2873,14 @@ int xfs_reclaim( xfs_inode_t *ip) { + bhv_vnode_t *vp = XFS_ITOV(ip); xfs_itrace_entry(ip); - ASSERT(!VN_MAPPED(VFS_I(ip))); + ASSERT(!VN_MAPPED(vp)); /* bad inode, get out here ASAP */ - if (VN_BAD(VFS_I(ip))) { + if (VN_BAD(vp)) { xfs_ireclaim(ip); return 0; } @@ -2833,7 +2917,7 @@ xfs_reclaim( XFS_MOUNT_ILOCK(mp); spin_lock(&ip->i_flags_lock); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); - VFS_I(ip)->i_private = NULL; + vn_to_inode(vp)->i_private = NULL; ip->i_vnode = NULL; spin_unlock(&ip->i_flags_lock); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); @@ -2849,7 +2933,7 @@ xfs_finish_reclaim( int sync_mode) { xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); - struct inode *vp = VFS_I(ip); + bhv_vnode_t *vp = XFS_ITOV_NULL(ip); if (vp && VN_BAD(vp)) goto reclaim; @@ -3237,6 +3321,7 @@ xfs_free_file_space( xfs_off_t len, int attr_flags) { + bhv_vnode_t *vp; int committed; int done; xfs_off_t end_dmi_offset; @@ -3256,6 +3341,7 @@ xfs_free_file_space( xfs_trans_t *tp; int need_iolock = 1; + vp = XFS_ITOV(ip); mp = ip->i_mount; xfs_itrace_entry(ip); @@ -3292,7 +3378,7 @@ xfs_free_file_space( rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); ioffset = offset & ~(rounding - 1); - if (VN_CACHED(VFS_I(ip)) != 0) { + if (VN_CACHED(vp) != 0) { xfs_inval_cached_trace(ip, ioffset, -1, ioffset, -1); error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED); if (error) diff --git a/trunk/arch/h8300/include/asm/Kbuild b/trunk/include/asm-h8300/Kbuild similarity index 100% rename from trunk/arch/h8300/include/asm/Kbuild rename to trunk/include/asm-h8300/Kbuild diff --git a/trunk/arch/h8300/include/asm/a.out.h b/trunk/include/asm-h8300/a.out.h similarity index 100% rename from trunk/arch/h8300/include/asm/a.out.h rename to trunk/include/asm-h8300/a.out.h diff --git a/trunk/arch/h8300/include/asm/atomic.h b/trunk/include/asm-h8300/atomic.h similarity index 100% rename from trunk/arch/h8300/include/asm/atomic.h rename to trunk/include/asm-h8300/atomic.h diff --git a/trunk/arch/h8300/include/asm/auxvec.h b/trunk/include/asm-h8300/auxvec.h similarity index 100% rename from trunk/arch/h8300/include/asm/auxvec.h rename to trunk/include/asm-h8300/auxvec.h diff --git a/trunk/arch/h8300/include/asm/bitops.h b/trunk/include/asm-h8300/bitops.h similarity index 100% rename from trunk/arch/h8300/include/asm/bitops.h rename to trunk/include/asm-h8300/bitops.h diff --git a/trunk/arch/h8300/include/asm/bootinfo.h b/trunk/include/asm-h8300/bootinfo.h similarity index 100% rename from trunk/arch/h8300/include/asm/bootinfo.h rename to trunk/include/asm-h8300/bootinfo.h diff --git a/trunk/arch/h8300/include/asm/bug.h b/trunk/include/asm-h8300/bug.h similarity index 100% rename from trunk/arch/h8300/include/asm/bug.h rename to trunk/include/asm-h8300/bug.h diff --git a/trunk/arch/h8300/include/asm/bugs.h b/trunk/include/asm-h8300/bugs.h similarity index 100% rename from trunk/arch/h8300/include/asm/bugs.h rename to trunk/include/asm-h8300/bugs.h diff --git a/trunk/arch/h8300/include/asm/byteorder.h b/trunk/include/asm-h8300/byteorder.h similarity index 100% rename from trunk/arch/h8300/include/asm/byteorder.h rename to trunk/include/asm-h8300/byteorder.h diff --git a/trunk/arch/h8300/include/asm/cache.h b/trunk/include/asm-h8300/cache.h similarity index 100% rename from trunk/arch/h8300/include/asm/cache.h rename to trunk/include/asm-h8300/cache.h diff --git a/trunk/arch/h8300/include/asm/cachectl.h b/trunk/include/asm-h8300/cachectl.h similarity index 100% rename from trunk/arch/h8300/include/asm/cachectl.h rename to trunk/include/asm-h8300/cachectl.h diff --git a/trunk/arch/h8300/include/asm/cacheflush.h b/trunk/include/asm-h8300/cacheflush.h similarity index 100% rename from trunk/arch/h8300/include/asm/cacheflush.h rename to trunk/include/asm-h8300/cacheflush.h diff --git a/trunk/arch/h8300/include/asm/checksum.h b/trunk/include/asm-h8300/checksum.h similarity index 100% rename from trunk/arch/h8300/include/asm/checksum.h rename to trunk/include/asm-h8300/checksum.h diff --git a/trunk/arch/h8300/include/asm/cputime.h b/trunk/include/asm-h8300/cputime.h similarity index 100% rename from trunk/arch/h8300/include/asm/cputime.h rename to trunk/include/asm-h8300/cputime.h diff --git a/trunk/arch/h8300/include/asm/current.h b/trunk/include/asm-h8300/current.h similarity index 100% rename from trunk/arch/h8300/include/asm/current.h rename to trunk/include/asm-h8300/current.h diff --git a/trunk/arch/h8300/include/asm/dbg.h b/trunk/include/asm-h8300/dbg.h similarity index 100% rename from trunk/arch/h8300/include/asm/dbg.h rename to trunk/include/asm-h8300/dbg.h diff --git a/trunk/arch/h8300/include/asm/delay.h b/trunk/include/asm-h8300/delay.h similarity index 100% rename from trunk/arch/h8300/include/asm/delay.h rename to trunk/include/asm-h8300/delay.h diff --git a/trunk/arch/h8300/include/asm/device.h b/trunk/include/asm-h8300/device.h similarity index 100% rename from trunk/arch/h8300/include/asm/device.h rename to trunk/include/asm-h8300/device.h diff --git a/trunk/arch/h8300/include/asm/div64.h b/trunk/include/asm-h8300/div64.h similarity index 100% rename from trunk/arch/h8300/include/asm/div64.h rename to trunk/include/asm-h8300/div64.h diff --git a/trunk/arch/h8300/include/asm/dma.h b/trunk/include/asm-h8300/dma.h similarity index 100% rename from trunk/arch/h8300/include/asm/dma.h rename to trunk/include/asm-h8300/dma.h diff --git a/trunk/arch/h8300/include/asm/elf.h b/trunk/include/asm-h8300/elf.h similarity index 100% rename from trunk/arch/h8300/include/asm/elf.h rename to trunk/include/asm-h8300/elf.h diff --git a/trunk/arch/h8300/include/asm/emergency-restart.h b/trunk/include/asm-h8300/emergency-restart.h similarity index 100% rename from trunk/arch/h8300/include/asm/emergency-restart.h rename to trunk/include/asm-h8300/emergency-restart.h diff --git a/trunk/arch/h8300/include/asm/errno.h b/trunk/include/asm-h8300/errno.h similarity index 100% rename from trunk/arch/h8300/include/asm/errno.h rename to trunk/include/asm-h8300/errno.h diff --git a/trunk/arch/h8300/include/asm/fb.h b/trunk/include/asm-h8300/fb.h similarity index 100% rename from trunk/arch/h8300/include/asm/fb.h rename to trunk/include/asm-h8300/fb.h diff --git a/trunk/arch/h8300/include/asm/fcntl.h b/trunk/include/asm-h8300/fcntl.h similarity index 100% rename from trunk/arch/h8300/include/asm/fcntl.h rename to trunk/include/asm-h8300/fcntl.h diff --git a/trunk/arch/h8300/include/asm/flat.h b/trunk/include/asm-h8300/flat.h similarity index 100% rename from trunk/arch/h8300/include/asm/flat.h rename to trunk/include/asm-h8300/flat.h diff --git a/trunk/arch/h8300/include/asm/fpu.h b/trunk/include/asm-h8300/fpu.h similarity index 100% rename from trunk/arch/h8300/include/asm/fpu.h rename to trunk/include/asm-h8300/fpu.h diff --git a/trunk/arch/h8300/include/asm/futex.h b/trunk/include/asm-h8300/futex.h similarity index 100% rename from trunk/arch/h8300/include/asm/futex.h rename to trunk/include/asm-h8300/futex.h diff --git a/trunk/arch/h8300/include/asm/gpio.h b/trunk/include/asm-h8300/gpio.h similarity index 100% rename from trunk/arch/h8300/include/asm/gpio.h rename to trunk/include/asm-h8300/gpio.h diff --git a/trunk/arch/h8300/include/asm/hardirq.h b/trunk/include/asm-h8300/hardirq.h similarity index 100% rename from trunk/arch/h8300/include/asm/hardirq.h rename to trunk/include/asm-h8300/hardirq.h diff --git a/trunk/arch/h8300/include/asm/hw_irq.h b/trunk/include/asm-h8300/hw_irq.h similarity index 100% rename from trunk/arch/h8300/include/asm/hw_irq.h rename to trunk/include/asm-h8300/hw_irq.h diff --git a/trunk/arch/h8300/include/asm/io.h b/trunk/include/asm-h8300/io.h similarity index 100% rename from trunk/arch/h8300/include/asm/io.h rename to trunk/include/asm-h8300/io.h diff --git a/trunk/arch/h8300/include/asm/ioctl.h b/trunk/include/asm-h8300/ioctl.h similarity index 100% rename from trunk/arch/h8300/include/asm/ioctl.h rename to trunk/include/asm-h8300/ioctl.h diff --git a/trunk/arch/h8300/include/asm/ioctls.h b/trunk/include/asm-h8300/ioctls.h similarity index 100% rename from trunk/arch/h8300/include/asm/ioctls.h rename to trunk/include/asm-h8300/ioctls.h diff --git a/trunk/arch/h8300/include/asm/ipcbuf.h b/trunk/include/asm-h8300/ipcbuf.h similarity index 100% rename from trunk/arch/h8300/include/asm/ipcbuf.h rename to trunk/include/asm-h8300/ipcbuf.h diff --git a/trunk/arch/h8300/include/asm/irq.h b/trunk/include/asm-h8300/irq.h similarity index 100% rename from trunk/arch/h8300/include/asm/irq.h rename to trunk/include/asm-h8300/irq.h diff --git a/trunk/arch/h8300/include/asm/irq_regs.h b/trunk/include/asm-h8300/irq_regs.h similarity index 100% rename from trunk/arch/h8300/include/asm/irq_regs.h rename to trunk/include/asm-h8300/irq_regs.h diff --git a/trunk/arch/h8300/include/asm/kdebug.h b/trunk/include/asm-h8300/kdebug.h similarity index 100% rename from trunk/arch/h8300/include/asm/kdebug.h rename to trunk/include/asm-h8300/kdebug.h diff --git a/trunk/arch/h8300/include/asm/kmap_types.h b/trunk/include/asm-h8300/kmap_types.h similarity index 100% rename from trunk/arch/h8300/include/asm/kmap_types.h rename to trunk/include/asm-h8300/kmap_types.h diff --git a/trunk/arch/h8300/include/asm/linkage.h b/trunk/include/asm-h8300/linkage.h similarity index 100% rename from trunk/arch/h8300/include/asm/linkage.h rename to trunk/include/asm-h8300/linkage.h diff --git a/trunk/arch/h8300/include/asm/local.h b/trunk/include/asm-h8300/local.h similarity index 100% rename from trunk/arch/h8300/include/asm/local.h rename to trunk/include/asm-h8300/local.h diff --git a/trunk/arch/h8300/include/asm/mc146818rtc.h b/trunk/include/asm-h8300/mc146818rtc.h similarity index 100% rename from trunk/arch/h8300/include/asm/mc146818rtc.h rename to trunk/include/asm-h8300/mc146818rtc.h diff --git a/trunk/arch/h8300/include/asm/md.h b/trunk/include/asm-h8300/md.h similarity index 100% rename from trunk/arch/h8300/include/asm/md.h rename to trunk/include/asm-h8300/md.h diff --git a/trunk/arch/h8300/include/asm/mman.h b/trunk/include/asm-h8300/mman.h similarity index 100% rename from trunk/arch/h8300/include/asm/mman.h rename to trunk/include/asm-h8300/mman.h diff --git a/trunk/arch/h8300/include/asm/mmu.h b/trunk/include/asm-h8300/mmu.h similarity index 100% rename from trunk/arch/h8300/include/asm/mmu.h rename to trunk/include/asm-h8300/mmu.h diff --git a/trunk/arch/h8300/include/asm/mmu_context.h b/trunk/include/asm-h8300/mmu_context.h similarity index 100% rename from trunk/arch/h8300/include/asm/mmu_context.h rename to trunk/include/asm-h8300/mmu_context.h diff --git a/trunk/arch/h8300/include/asm/module.h b/trunk/include/asm-h8300/module.h similarity index 100% rename from trunk/arch/h8300/include/asm/module.h rename to trunk/include/asm-h8300/module.h diff --git a/trunk/arch/h8300/include/asm/msgbuf.h b/trunk/include/asm-h8300/msgbuf.h similarity index 100% rename from trunk/arch/h8300/include/asm/msgbuf.h rename to trunk/include/asm-h8300/msgbuf.h diff --git a/trunk/arch/h8300/include/asm/mutex.h b/trunk/include/asm-h8300/mutex.h similarity index 100% rename from trunk/arch/h8300/include/asm/mutex.h rename to trunk/include/asm-h8300/mutex.h diff --git a/trunk/arch/h8300/include/asm/page.h b/trunk/include/asm-h8300/page.h similarity index 100% rename from trunk/arch/h8300/include/asm/page.h rename to trunk/include/asm-h8300/page.h diff --git a/trunk/arch/h8300/include/asm/page_offset.h b/trunk/include/asm-h8300/page_offset.h similarity index 100% rename from trunk/arch/h8300/include/asm/page_offset.h rename to trunk/include/asm-h8300/page_offset.h diff --git a/trunk/arch/h8300/include/asm/param.h b/trunk/include/asm-h8300/param.h similarity index 100% rename from trunk/arch/h8300/include/asm/param.h rename to trunk/include/asm-h8300/param.h diff --git a/trunk/arch/h8300/include/asm/pci.h b/trunk/include/asm-h8300/pci.h similarity index 100% rename from trunk/arch/h8300/include/asm/pci.h rename to trunk/include/asm-h8300/pci.h diff --git a/trunk/arch/h8300/include/asm/percpu.h b/trunk/include/asm-h8300/percpu.h similarity index 100% rename from trunk/arch/h8300/include/asm/percpu.h rename to trunk/include/asm-h8300/percpu.h diff --git a/trunk/arch/h8300/include/asm/pgalloc.h b/trunk/include/asm-h8300/pgalloc.h similarity index 100% rename from trunk/arch/h8300/include/asm/pgalloc.h rename to trunk/include/asm-h8300/pgalloc.h diff --git a/trunk/arch/h8300/include/asm/pgtable.h b/trunk/include/asm-h8300/pgtable.h similarity index 100% rename from trunk/arch/h8300/include/asm/pgtable.h rename to trunk/include/asm-h8300/pgtable.h diff --git a/trunk/arch/h8300/include/asm/poll.h b/trunk/include/asm-h8300/poll.h similarity index 100% rename from trunk/arch/h8300/include/asm/poll.h rename to trunk/include/asm-h8300/poll.h diff --git a/trunk/arch/h8300/include/asm/posix_types.h b/trunk/include/asm-h8300/posix_types.h similarity index 100% rename from trunk/arch/h8300/include/asm/posix_types.h rename to trunk/include/asm-h8300/posix_types.h diff --git a/trunk/arch/h8300/include/asm/processor.h b/trunk/include/asm-h8300/processor.h similarity index 100% rename from trunk/arch/h8300/include/asm/processor.h rename to trunk/include/asm-h8300/processor.h diff --git a/trunk/arch/h8300/include/asm/ptrace.h b/trunk/include/asm-h8300/ptrace.h similarity index 100% rename from trunk/arch/h8300/include/asm/ptrace.h rename to trunk/include/asm-h8300/ptrace.h diff --git a/trunk/arch/h8300/include/asm/regs267x.h b/trunk/include/asm-h8300/regs267x.h similarity index 100% rename from trunk/arch/h8300/include/asm/regs267x.h rename to trunk/include/asm-h8300/regs267x.h diff --git a/trunk/arch/h8300/include/asm/regs306x.h b/trunk/include/asm-h8300/regs306x.h similarity index 100% rename from trunk/arch/h8300/include/asm/regs306x.h rename to trunk/include/asm-h8300/regs306x.h diff --git a/trunk/arch/h8300/include/asm/resource.h b/trunk/include/asm-h8300/resource.h similarity index 100% rename from trunk/arch/h8300/include/asm/resource.h rename to trunk/include/asm-h8300/resource.h diff --git a/trunk/arch/h8300/include/asm/scatterlist.h b/trunk/include/asm-h8300/scatterlist.h similarity index 100% rename from trunk/arch/h8300/include/asm/scatterlist.h rename to trunk/include/asm-h8300/scatterlist.h diff --git a/trunk/arch/h8300/include/asm/sections.h b/trunk/include/asm-h8300/sections.h similarity index 100% rename from trunk/arch/h8300/include/asm/sections.h rename to trunk/include/asm-h8300/sections.h diff --git a/trunk/arch/h8300/include/asm/segment.h b/trunk/include/asm-h8300/segment.h similarity index 100% rename from trunk/arch/h8300/include/asm/segment.h rename to trunk/include/asm-h8300/segment.h diff --git a/trunk/arch/h8300/include/asm/sembuf.h b/trunk/include/asm-h8300/sembuf.h similarity index 100% rename from trunk/arch/h8300/include/asm/sembuf.h rename to trunk/include/asm-h8300/sembuf.h diff --git a/trunk/arch/h8300/include/asm/setup.h b/trunk/include/asm-h8300/setup.h similarity index 100% rename from trunk/arch/h8300/include/asm/setup.h rename to trunk/include/asm-h8300/setup.h diff --git a/trunk/arch/h8300/include/asm/sh_bios.h b/trunk/include/asm-h8300/sh_bios.h similarity index 100% rename from trunk/arch/h8300/include/asm/sh_bios.h rename to trunk/include/asm-h8300/sh_bios.h diff --git a/trunk/arch/h8300/include/asm/shm.h b/trunk/include/asm-h8300/shm.h similarity index 100% rename from trunk/arch/h8300/include/asm/shm.h rename to trunk/include/asm-h8300/shm.h diff --git a/trunk/arch/h8300/include/asm/shmbuf.h b/trunk/include/asm-h8300/shmbuf.h similarity index 100% rename from trunk/arch/h8300/include/asm/shmbuf.h rename to trunk/include/asm-h8300/shmbuf.h diff --git a/trunk/arch/h8300/include/asm/shmparam.h b/trunk/include/asm-h8300/shmparam.h similarity index 100% rename from trunk/arch/h8300/include/asm/shmparam.h rename to trunk/include/asm-h8300/shmparam.h diff --git a/trunk/arch/h8300/include/asm/sigcontext.h b/trunk/include/asm-h8300/sigcontext.h similarity index 100% rename from trunk/arch/h8300/include/asm/sigcontext.h rename to trunk/include/asm-h8300/sigcontext.h diff --git a/trunk/arch/h8300/include/asm/siginfo.h b/trunk/include/asm-h8300/siginfo.h similarity index 100% rename from trunk/arch/h8300/include/asm/siginfo.h rename to trunk/include/asm-h8300/siginfo.h diff --git a/trunk/arch/h8300/include/asm/signal.h b/trunk/include/asm-h8300/signal.h similarity index 100% rename from trunk/arch/h8300/include/asm/signal.h rename to trunk/include/asm-h8300/signal.h diff --git a/trunk/arch/h8300/include/asm/smp.h b/trunk/include/asm-h8300/smp.h similarity index 100% rename from trunk/arch/h8300/include/asm/smp.h rename to trunk/include/asm-h8300/smp.h diff --git a/trunk/arch/h8300/include/asm/socket.h b/trunk/include/asm-h8300/socket.h similarity index 100% rename from trunk/arch/h8300/include/asm/socket.h rename to trunk/include/asm-h8300/socket.h diff --git a/trunk/arch/h8300/include/asm/sockios.h b/trunk/include/asm-h8300/sockios.h similarity index 100% rename from trunk/arch/h8300/include/asm/sockios.h rename to trunk/include/asm-h8300/sockios.h diff --git a/trunk/arch/h8300/include/asm/spinlock.h b/trunk/include/asm-h8300/spinlock.h similarity index 100% rename from trunk/arch/h8300/include/asm/spinlock.h rename to trunk/include/asm-h8300/spinlock.h diff --git a/trunk/arch/h8300/include/asm/stat.h b/trunk/include/asm-h8300/stat.h similarity index 100% rename from trunk/arch/h8300/include/asm/stat.h rename to trunk/include/asm-h8300/stat.h diff --git a/trunk/arch/h8300/include/asm/statfs.h b/trunk/include/asm-h8300/statfs.h similarity index 100% rename from trunk/arch/h8300/include/asm/statfs.h rename to trunk/include/asm-h8300/statfs.h diff --git a/trunk/arch/h8300/include/asm/string.h b/trunk/include/asm-h8300/string.h similarity index 100% rename from trunk/arch/h8300/include/asm/string.h rename to trunk/include/asm-h8300/string.h diff --git a/trunk/arch/h8300/include/asm/system.h b/trunk/include/asm-h8300/system.h similarity index 100% rename from trunk/arch/h8300/include/asm/system.h rename to trunk/include/asm-h8300/system.h diff --git a/trunk/arch/h8300/include/asm/target_time.h b/trunk/include/asm-h8300/target_time.h similarity index 100% rename from trunk/arch/h8300/include/asm/target_time.h rename to trunk/include/asm-h8300/target_time.h diff --git a/trunk/arch/h8300/include/asm/termbits.h b/trunk/include/asm-h8300/termbits.h similarity index 100% rename from trunk/arch/h8300/include/asm/termbits.h rename to trunk/include/asm-h8300/termbits.h diff --git a/trunk/arch/h8300/include/asm/termios.h b/trunk/include/asm-h8300/termios.h similarity index 100% rename from trunk/arch/h8300/include/asm/termios.h rename to trunk/include/asm-h8300/termios.h diff --git a/trunk/arch/h8300/include/asm/thread_info.h b/trunk/include/asm-h8300/thread_info.h similarity index 100% rename from trunk/arch/h8300/include/asm/thread_info.h rename to trunk/include/asm-h8300/thread_info.h diff --git a/trunk/arch/h8300/include/asm/timex.h b/trunk/include/asm-h8300/timex.h similarity index 100% rename from trunk/arch/h8300/include/asm/timex.h rename to trunk/include/asm-h8300/timex.h diff --git a/trunk/arch/h8300/include/asm/tlb.h b/trunk/include/asm-h8300/tlb.h similarity index 100% rename from trunk/arch/h8300/include/asm/tlb.h rename to trunk/include/asm-h8300/tlb.h diff --git a/trunk/arch/h8300/include/asm/tlbflush.h b/trunk/include/asm-h8300/tlbflush.h similarity index 100% rename from trunk/arch/h8300/include/asm/tlbflush.h rename to trunk/include/asm-h8300/tlbflush.h diff --git a/trunk/arch/h8300/include/asm/topology.h b/trunk/include/asm-h8300/topology.h similarity index 100% rename from trunk/arch/h8300/include/asm/topology.h rename to trunk/include/asm-h8300/topology.h diff --git a/trunk/arch/h8300/include/asm/traps.h b/trunk/include/asm-h8300/traps.h similarity index 100% rename from trunk/arch/h8300/include/asm/traps.h rename to trunk/include/asm-h8300/traps.h diff --git a/trunk/arch/h8300/include/asm/types.h b/trunk/include/asm-h8300/types.h similarity index 100% rename from trunk/arch/h8300/include/asm/types.h rename to trunk/include/asm-h8300/types.h diff --git a/trunk/arch/h8300/include/asm/uaccess.h b/trunk/include/asm-h8300/uaccess.h similarity index 100% rename from trunk/arch/h8300/include/asm/uaccess.h rename to trunk/include/asm-h8300/uaccess.h diff --git a/trunk/arch/h8300/include/asm/ucontext.h b/trunk/include/asm-h8300/ucontext.h similarity index 100% rename from trunk/arch/h8300/include/asm/ucontext.h rename to trunk/include/asm-h8300/ucontext.h diff --git a/trunk/arch/h8300/include/asm/unaligned.h b/trunk/include/asm-h8300/unaligned.h similarity index 100% rename from trunk/arch/h8300/include/asm/unaligned.h rename to trunk/include/asm-h8300/unaligned.h diff --git a/trunk/arch/h8300/include/asm/unistd.h b/trunk/include/asm-h8300/unistd.h similarity index 100% rename from trunk/arch/h8300/include/asm/unistd.h rename to trunk/include/asm-h8300/unistd.h diff --git a/trunk/arch/h8300/include/asm/user.h b/trunk/include/asm-h8300/user.h similarity index 100% rename from trunk/arch/h8300/include/asm/user.h rename to trunk/include/asm-h8300/user.h diff --git a/trunk/arch/h8300/include/asm/virtconvert.h b/trunk/include/asm-h8300/virtconvert.h similarity index 100% rename from trunk/arch/h8300/include/asm/virtconvert.h rename to trunk/include/asm-h8300/virtconvert.h diff --git a/trunk/include/linux/completion.h b/trunk/include/linux/completion.h index 57faa60de9bd..d2961b66d53d 100644 --- a/trunk/include/linux/completion.h +++ b/trunk/include/linux/completion.h @@ -55,49 +55,4 @@ extern void complete_all(struct completion *); #define INIT_COMPLETION(x) ((x).done = 0) - -/** - * try_wait_for_completion - try to decrement a completion without blocking - * @x: completion structure - * - * Returns: 0 if a decrement cannot be done without blocking - * 1 if a decrement succeeded. - * - * If a completion is being used as a counting completion, - * attempt to decrement the counter without blocking. This - * enables us to avoid waiting if the resource the completion - * is protecting is not available. - */ -static inline bool try_wait_for_completion(struct completion *x) -{ - int ret = 1; - - spin_lock_irq(&x->wait.lock); - if (!x->done) - ret = 0; - else - x->done--; - spin_unlock_irq(&x->wait.lock); - return ret; -} - -/** - * completion_done - Test to see if a completion has any waiters - * @x: completion structure - * - * Returns: 0 if there are waiters (wait_for_completion() in progress) - * 1 if there are no waiters. - * - */ -static inline bool completion_done(struct completion *x) -{ - int ret = 1; - - spin_lock_irq(&x->wait.lock); - if (!x->done) - ret = 0; - spin_unlock_irq(&x->wait.lock); - return ret; -} - #endif