diff options
-rw-r--r-- | xlators/storage/bd_map/src/bd_map.c | 110 |
1 files changed, 104 insertions, 6 deletions
diff --git a/xlators/storage/bd_map/src/bd_map.c b/xlators/storage/bd_map/src/bd_map.c index 3495ecdae7b..f11038e497a 100644 --- a/xlators/storage/bd_map/src/bd_map.c +++ b/xlators/storage/bd_map/src/bd_map.c @@ -652,6 +652,87 @@ out: return 0; } +#define LVM_RESIZE "/sbin/lvresize" + +int32_t +bd_resize (bd_priv_t *priv, bd_entry_t *lventry, off_t *size) +{ + bd_entry_t *vgentry = NULL; + uint64_t extent = 0; + int32_t op_ret = -1; + vg_t vg = NULL; + uint32_t nr_ex = 0; + lv_t lv = NULL; + uint64_t new_size = 0; + runner_t runner = {0, }; + + BD_ENTRY (priv, vgentry, lventry->parent->name); + if (!vgentry) { + op_ret = ENOENT; + goto out; + } + + BD_WR_LOCK (&priv->lock); + vg = lvm_vg_open (priv->handle, vgentry->name, "w", 0); + if (!vg) { + op_ret = lvm_errno (priv->handle); + BD_UNLOCK (&priv->lock); + goto out; + } + + extent = lvm_vg_get_extent_size (vg); + lvm_vg_close (vg); + BD_UNLOCK (&priv->lock); + + nr_ex = *size / extent; + if (*size % extent) + nr_ex++; + *size = extent * nr_ex; + + runinit (&runner); + + runner_add_args (&runner, LVM_RESIZE, NULL); + runner_argprintf (&runner, "/dev/%s/%s", lventry->parent->name, + lventry->name); + runner_argprintf (&runner, "-l%ld", nr_ex); + runner_add_args (&runner, "-f", NULL); + + runner_start (&runner); + runner_end (&runner); + + BD_WR_LOCK (&priv->lock); + vg = lvm_vg_open (priv->handle, vgentry->name, "w", 0); + if (!vg) { + op_ret = lvm_errno (priv->handle); + BD_UNLOCK (&priv->lock); + goto out; + } + + lv = lvm_lv_from_name (vg, lventry->name); + if (!lv) { + op_ret = lvm_errno (priv->handle); + lvm_vg_close (vg); + BD_UNLOCK (&priv->lock); + goto out; + } + new_size = lvm_lv_get_size (lv); + lvm_vg_close (vg); + if (new_size != *size) { + op_ret = EIO; + BD_UNLOCK (&priv->lock); + goto out; + } + + BD_UNLOCK (&priv->lock); + op_ret = 0; + +out: + if (vgentry) + BD_PUT_ENTRY (priv, vgentry); + + return op_ret; +} + int32_t bd_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdict) @@ -663,12 +744,16 @@ bd_ftruncate (call_frame_t *frame, xlator_t *this, bd_fd_t *bd_fd = NULL; int ret = -1; uint64_t tmp_bd_fd = 0; + bd_priv_t *priv = NULL; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); VALIDATE_OR_GOTO (fd, out); + priv = this->private; + VALIDATE_OR_GOTO (priv, out); ret = fd_ctx_get (fd, this, &tmp_bd_fd); + if (ret < 0) { gf_log (this->name, GF_LOG_WARNING, "bd_fd is NULL, fd=%p", fd); @@ -678,9 +763,14 @@ bd_ftruncate (call_frame_t *frame, xlator_t *this, bd_fd = (bd_fd_t *)(long)tmp_bd_fd; memcpy (&preop, bd_fd->entry->attr, sizeof(preop)); - if (offset >= bd_fd->entry->size) { - op_errno = EFBIG; - goto out; + if (offset > bd_fd->entry->size) { + op_errno = bd_resize (priv, bd_fd->entry, &offset); + if (op_errno) + goto out; + if (offset > bd_fd->entry->size) { + bd_fd->entry->attr->ia_size = offset; + bd_fd->entry->size = offset; + } } /* If the requested size is less then current size * we will not update that in bd_fd->entry->attr @@ -707,6 +797,7 @@ bd_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt postbuf = {0, }; bd_entry_t *lventry = NULL; bd_priv_t *priv = NULL; + off_t size = 0; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -722,15 +813,22 @@ bd_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, goto out; } memcpy (&prebuf, lventry->attr, sizeof(prebuf)); - if (offset >= lventry->size) { - op_errno = EFBIG; - goto out; + if (offset > lventry->size) { + op_errno = bd_resize (priv, lventry, &size); + if (op_errno) + goto out; + if (lventry->size < offset) { + lventry->attr->ia_size = offset; + lventry->size = size; + } } BD_ENTRY_UPDATE_MTIME (lventry); memcpy (&postbuf, lventry->attr, sizeof(postbuf)); BD_PUT_ENTRY (priv, lventry); op_ret = 0; out: + if (lventry) + BD_PUT_ENTRY (priv, lventry); STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, &prebuf, &postbuf, NULL); return 0; |