@@ -5028,11 +5028,6 @@ int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len)
rc = -EFBIG;
goto out;
}
- io->u.ci_setattr.sa_attr.lvb_size = sa_falloc_end;
- if (!(mode & FALLOC_FL_KEEP_SIZE))
- io->u.ci_setattr.sa_avalid |= ATTR_SIZE;
- } else {
- io->u.ci_setattr.sa_attr.lvb_size = size;
}
again:
@@ -41,6 +41,8 @@
#include <obd.h>
#include <linux/pagevec.h>
#include <linux/memcontrol.h>
+#include <linux/falloc.h>
+
#include "llite_internal.h"
#include "vvp_internal.h"
@@ -647,7 +649,7 @@ static int vvp_io_setattr_lock(const struct lu_env *env,
enqflags = CEF_DISCARD_DATA;
} else if (cl_io_is_fallocate(io)) {
lock_start = io->u.ci_setattr.sa_falloc_offset;
- lock_end = io->u.ci_setattr.sa_falloc_end;
+ lock_end = io->u.ci_setattr.sa_falloc_end - 1;
} else {
unsigned int valid = io->u.ci_setattr.sa_avalid;
@@ -715,14 +717,27 @@ static int vvp_io_setattr_start(const struct lu_env *env,
struct cl_io *io = ios->cis_io;
struct inode *inode = vvp_object_inode(io->ci_obj);
struct ll_inode_info *lli = ll_i2info(inode);
+ int mode = io->u.ci_setattr.sa_falloc_mode;
if (cl_io_is_trunc(io)) {
trunc_sem_down_write(&lli->lli_trunc_sem);
mutex_lock(&lli->lli_setattr_mutex);
inode_dio_wait(inode);
} else if (cl_io_is_fallocate(io)) {
- inode_lock(inode);
+ loff_t size;
+
+ trunc_sem_down_write(&lli->lli_trunc_sem);
+ mutex_lock(&lli->lli_setattr_mutex);
inode_dio_wait(inode);
+
+ ll_merge_attr(env, inode);
+ size = i_size_read(inode);
+ if (io->u.ci_setattr.sa_falloc_end > size &&
+ !(mode & FALLOC_FL_KEEP_SIZE)) {
+ size = io->u.ci_setattr.sa_falloc_end;
+ io->u.ci_setattr.sa_avalid |= ATTR_SIZE;
+ }
+ io->u.ci_setattr.sa_attr.lvb_size = size;
} else {
mutex_lock(&lli->lli_setattr_mutex);
}
@@ -748,7 +763,8 @@ static void vvp_io_setattr_end(const struct lu_env *env,
mutex_unlock(&lli->lli_setattr_mutex);
trunc_sem_up_write(&lli->lli_trunc_sem);
} else if (cl_io_is_fallocate(io)) {
- inode_unlock(inode);
+ mutex_unlock(&lli->lli_setattr_mutex);
+ trunc_sem_up_write(&lli->lli_trunc_sem);
} else {
mutex_unlock(&lli->lli_setattr_mutex);
}
@@ -681,7 +681,7 @@ static void lov_io_sub_inherit(struct lov_io_sub *sub, struct lov_io *lio,
io->u.ci_setattr.sa_falloc_offset = start;
io->u.ci_setattr.sa_falloc_end = end;
}
- if (cl_io_is_trunc(io) || cl_io_is_fallocate(io)) {
+ if (cl_io_is_trunc(io)) {
loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size;
new_size = lov_size_to_stripe(lsm, index, new_size,
@@ -1441,6 +1441,30 @@ static int lov_io_fault_start(const struct lu_env *env,
return lov_io_start(env, ios);
}
+static int lov_io_setattr_start(const struct lu_env *env,
+ const struct cl_io_slice *ios)
+{
+ struct lov_io *lio = cl2lov_io(env, ios);
+ struct cl_io *parent = ios->cis_io;
+ struct lov_io_sub *sub;
+ struct lov_stripe_md *lsm = lio->lis_object->lo_lsm;
+
+ if (cl_io_is_fallocate(parent)) {
+ list_for_each_entry(sub, &lio->lis_active, sub_linkage) {
+ loff_t size = parent->u.ci_setattr.sa_attr.lvb_size;
+ int index = lov_comp_entry(sub->sub_subio_index);
+ int stripe = lov_comp_stripe(sub->sub_subio_index);
+
+ size = lov_size_to_stripe(lsm, index, size, stripe);
+ sub->sub_io.u.ci_setattr.sa_attr.lvb_size = size;
+ sub->sub_io.u.ci_setattr.sa_avalid =
+ parent->u.ci_setattr.sa_avalid;
+ }
+ }
+
+ return lov_io_start(env, ios);
+}
+
static void lov_io_fsync_end(const struct lu_env *env,
const struct cl_io_slice *ios)
{
@@ -1577,7 +1601,7 @@ static void lov_io_lseek_end(const struct lu_env *env,
.cio_iter_fini = lov_io_iter_fini,
.cio_lock = lov_io_lock,
.cio_unlock = lov_io_unlock,
- .cio_start = lov_io_start,
+ .cio_start = lov_io_setattr_start,
.cio_end = lov_io_end
},
[CIT_DATA_VERSION] = {