From 5b170a69c1c3ad6cb2fbaf69f8bff43ba7b9c6e8 Mon Sep 17 00:00:00 2001 From: pschwan Date: Thu, 22 Aug 2002 04:56:24 +0000 Subject: [PATCH] - abstracted some parts of ll_size into ll_size_lock and ll_size_unlock - added file size locking around the mds_setattr in ll_file_release --- lustre/include/linux/lustre_lite.h | 4 ++ lustre/llite/file.c | 101 +++++++++++++++++++++++++++++-------- lustre/llite/namei.c | 34 ++++--------- 3 files changed, 94 insertions(+), 45 deletions(-) diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index 086758e..8c1f66c 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -137,6 +137,10 @@ extern struct inode_operations ll_file_inode_operations; struct ldlm_lock; int ll_lock_callback(struct ldlm_lock *, struct ldlm_lock_desc *, void *data, __u32 data_len); +int ll_size_lock(struct inode *, struct lov_stripe_md *, __u64 start, int mode, + struct lustre_handle **); +int ll_size_unlock(struct inode *, struct lov_stripe_md *, int mode, + struct lustre_handle *); /* rw.c */ struct page *ll_getpage(struct inode *inode, unsigned long offset, diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 8951c43..da2d2af 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -126,12 +126,54 @@ out: return rc; } +int ll_size_lock(struct inode *inode, struct lov_stripe_md *md, __u64 start, + int mode, struct lustre_handle **lockhs_p) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct ldlm_extent extent; + struct lustre_handle *lockhs = NULL; + int rc, flags = 0; + + OBD_ALLOC(lockhs, md->lmd_stripe_count * sizeof(*lockhs)); + if (lockhs == NULL) + RETURN(-ENOMEM); + + extent.start = start; + extent.end = ~0; + + rc = obd_enqueue(&sbi->ll_osc_conn, md, NULL, LDLM_EXTENT, &extent, + sizeof(extent), mode, &flags, ll_lock_callback, + inode, sizeof(*inode), lockhs); + if (rc != ELDLM_OK) { + CERROR("lock enqueue: %d\n", rc); + OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs)); + } else + *lockhs_p = lockhs; + RETURN(rc); +} + +int ll_size_unlock(struct inode *inode, struct lov_stripe_md *md, int mode, + struct lustre_handle *lockhs) +{ + struct ll_sb_info *sbi = ll_i2sbi(inode); + int rc; + + rc = obd_cancel(&sbi->ll_osc_conn, md, mode, lockhs); + if (rc != ELDLM_OK) { + CERROR("lock cancel: %d\n", rc); + LBUG(); + } + + OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs)); + RETURN(rc); +} + static int ll_file_release(struct inode *inode, struct file *file) { int rc; struct ptlrpc_request *req = NULL; struct ll_file_data *fd; - struct obdo *oa; + struct obdo oa; struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_inode_info *lli = ll_i2info(inode); //struct obd_device *obddev = class_conn2obd(&sbi->ll_osc_conn); @@ -145,33 +187,48 @@ static int ll_file_release(struct inode *inode, struct file *file) GOTO(out, rc = -EINVAL); } - oa = obdo_alloc(); - if (oa == NULL) { - LBUG(); - GOTO(out_fd, rc = -ENOENT); - } - oa->o_id = lli->lli_smd->lmd_object_id; - oa->o_mode = S_IFREG; - oa->o_valid = (OBD_MD_FLMODE | OBD_MD_FLID); - rc = obd_close(ll_i2obdconn(inode), oa, lli->lli_smd); - obdo_free(oa); + memset(&oa, 0, sizeof(oa)); + oa.o_id = lli->lli_smd->lmd_object_id; + oa.o_mode = S_IFREG; + oa.o_valid = (OBD_MD_FLMODE | OBD_MD_FLID); + rc = obd_close(ll_i2obdconn(inode), &oa, lli->lli_smd); if (rc) GOTO(out_fd, abs(rc)); + /* If this fails and we goto out_fd, the file size on the MDS is out of + * date. Is that a big deal? */ if (file->f_mode & FMODE_WRITE) { struct iattr attr; - attr.ia_valid = (ATTR_MTIME | ATTR_CTIME | ATTR_ATIME | - ATTR_SIZE); - attr.ia_mtime = inode->i_mtime; - attr.ia_ctime = inode->i_ctime; - attr.ia_atime = inode->i_atime; - attr.ia_size = inode->i_size; - - /* XXX: this introduces a small race that we should evaluate */ - rc = ll_inode_setattr(inode, &attr, 0); + struct lustre_handle *lockhs; + + rc = ll_size_lock(inode, lli->lli_smd, 0, LCK_PR, &lockhs); + if (rc) + GOTO(out_fd, abs(rc)); + + oa.o_id = lli->lli_smd->lmd_object_id; + oa.o_mode = S_IFREG; + oa.o_valid = OBD_MD_FLID | OBD_MD_FLMODE | OBD_MD_FLSIZE; + rc = obd_getattr(&sbi->ll_osc_conn, &oa, lli->lli_smd); + if (!rc) { + attr.ia_valid = (ATTR_MTIME | ATTR_CTIME | ATTR_ATIME | + ATTR_SIZE); + attr.ia_mtime = inode->i_mtime; + attr.ia_ctime = inode->i_ctime; + attr.ia_atime = inode->i_atime; + attr.ia_size = oa.o_size; + + /* XXX: this introduces a small race that we should + * evaluate */ + rc = ll_inode_setattr(inode, &attr, 0); + if (rc) { + CERROR("failed - %d.\n", rc); + rc = -EIO; /* XXX - GOTO(out)? -phil */ + } + } + rc = ll_size_unlock(inode, lli->lli_smd, LCK_PR, lockhs); if (rc) { - CERROR("failed - %d.\n", rc); - rc = -EIO; /* XXX - GOTO(out)? -phil */ + CERROR("lock cancel: %d\n", rc); + LBUG(); } } diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 052d6b1..3263013 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -134,45 +134,34 @@ int ll_unlock(__u32 mode, struct lustre_handle *lockh) RETURN(0); } -static int ll_file_size(struct inode *inode, obd_id ino, - struct lov_stripe_md *md, __u64 *size) +static int ll_file_size(struct inode *inode, struct lov_stripe_md *md, + __u64 *size) { struct ll_sb_info *sbi = ll_i2sbi(inode); + struct lustre_handle *lockhs; struct obdo oa; - struct lustre_handle *lockhs = NULL; - struct ldlm_extent extent; - int err, rc, flags = 0; + int err, rc; - OBD_ALLOC(lockhs, md->lmd_stripe_count * sizeof(*lockhs)); - if (lockhs == NULL) - RETURN(-ENOMEM); - - extent.start = 0; - extent.end = ~0; - - rc = obd_enqueue(&sbi->ll_osc_conn, md, NULL, LDLM_EXTENT, &extent, - sizeof(extent), LCK_PR, &flags, ll_lock_callback, - inode, sizeof(*inode), lockhs); + rc = ll_size_lock(inode, md, 0, LCK_PR, &lockhs); if (rc != ELDLM_OK) { CERROR("lock enqueue: %d\n", rc); - GOTO(out, rc); + RETURN(rc); } - oa.o_id = ino; + /* FIXME: I don't like this; why doesn't osc_getattr get o_id from md + * like lov_getattr? --phil */ + oa.o_id = md->lmd_object_id; oa.o_mode = S_IFREG; oa.o_valid = OBD_MD_FLID | OBD_MD_FLMODE | OBD_MD_FLSIZE; rc = obd_getattr(&sbi->ll_osc_conn, &oa, md); if (!rc) *size = oa.o_size; - err = obd_cancel(&sbi->ll_osc_conn, md, LCK_PR, lockhs); + err = ll_size_unlock(inode, md, LCK_PR, lockhs); if (err != ELDLM_OK) { CERROR("lock cancel: %d\n", err); LBUG(); } - - out: - OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs)); RETURN(rc); } @@ -300,8 +289,7 @@ static struct dentry *ll_lookup2(struct inode *dir, struct dentry *dentry, /* Get the authoritative file size */ #warning FIXME: race condition exists between iget4 and this update! if ((it->it_op & IT_GETATTR) && (inode->i_mode & S_IFREG)) { - err = ll_file_size(inode, md.md->lmd_object_id, md.md, - &inode->i_size); + err = ll_file_size(inode, md.md, &inode->i_size); if (err) { CERROR("ll_file_size: %d\n", err); /* FIXME: need to destroy inode here */ -- 1.8.3.1