From 17f287172413dc04244781aa5302a0e4f10e2777 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Thu, 23 May 2013 12:19:42 -0400 Subject: glusterfs: discard (hole punch) support Add support for the DISCARD file operation. Discard punches a hole in a file in the provided range. Block de-allocation is implemented via fallocate() (as requested via fuse and passed on to the brick fs) but a separate fop is created within gluster to emphasize the fact that discard changes file data (the discarded region is replaced with zeroes) and must invalidate caches where appropriate. BUG: 963678 Change-Id: I34633a0bfff2187afeab4292a15f3cc9adf261af Signed-off-by: Brian Foster Reviewed-on: http://review.gluster.org/5090 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- libglusterfs/src/call-stub.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ libglusterfs/src/call-stub.h | 16 +++++++++++ libglusterfs/src/defaults.c | 28 +++++++++++++++++++ libglusterfs/src/defaults.h | 14 ++++++++++ libglusterfs/src/globals.c | 1 + libglusterfs/src/glusterfs.h | 1 + libglusterfs/src/syncop.c | 30 +++++++++++++++++++++ libglusterfs/src/syncop.h | 1 + libglusterfs/src/xlator.c | 1 + libglusterfs/src/xlator.h | 17 ++++++++++++ 10 files changed, 173 insertions(+) (limited to 'libglusterfs') diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c index 2bb99341..2f07a007 100644 --- a/libglusterfs/src/call-stub.c +++ b/libglusterfs/src/call-stub.c @@ -2186,6 +2186,61 @@ out: } +call_stub_t * +fop_discard_cbk_stub(call_frame_t *frame, fop_discard_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn_cbk.discard = fn; + + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + + if (statpre) + stub->args_cbk.prestat = *statpre; + if (statpost) + stub->args_cbk.poststat = *statpost; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; +} + +call_stub_t * +fop_discard_stub(call_frame_t *frame, fop_discard_t fn, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); + + stub = stub_new (frame, 1, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.discard = fn; + + if (fd) + stub->args.fd = fd_ref (fd); + + stub->args.offset = offset; + stub->args.size = len; + + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; + +} + static void call_resume_wind (call_stub_t *stub) { @@ -2408,6 +2463,11 @@ call_resume_wind (call_stub_t *stub) stub->args.offset, stub->args.size, stub->args.xdata); break; + case GF_FOP_DISCARD: + stub->fn.discard(stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); + break; default: gf_log_callingfn ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", @@ -2606,6 +2666,10 @@ call_resume_unwind (call_stub_t *stub) STUB_UNWIND(stub, fallocate, &stub->args_cbk.prestat, &stub->args_cbk.poststat, stub->args_cbk.xdata); break; + case GF_FOP_DISCARD: + STUB_UNWIND(stub, discard, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; default: gf_log_callingfn ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", diff --git a/libglusterfs/src/call-stub.h b/libglusterfs/src/call-stub.h index d940fe6f..f0872b12 100644 --- a/libglusterfs/src/call-stub.h +++ b/libglusterfs/src/call-stub.h @@ -70,6 +70,7 @@ typedef struct { fop_setattr_t setattr; fop_fsetattr_t fsetattr; fop_fallocate_t fallocate; + fop_discard_t discard; } fn; union { @@ -115,6 +116,7 @@ typedef struct { fop_setattr_cbk_t setattr; fop_fsetattr_cbk_t fsetattr; fop_fallocate_cbk_t fallocate; + fop_discard_cbk_t discard; } fn_cbk; struct { @@ -729,6 +731,20 @@ fop_fallocate_cbk_stub(call_frame_t *frame, struct iatt *statpre, struct iatt *statpost, dict_t *xdata); +call_stub_t * +fop_discard_stub(call_frame_t *frame, + fop_discard_t fn, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + +call_stub_t * +fop_discard_cbk_stub(call_frame_t *frame, + fop_discard_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); + void call_resume (call_stub_t *stub); void call_stub_destroy (call_stub_t *stub); void call_unwind_error (call_stub_t *stub, int op_ret, int op_errno); diff --git a/libglusterfs/src/defaults.c b/libglusterfs/src/defaults.c index 32454a1e..a3c8d97f 100644 --- a/libglusterfs/src/defaults.c +++ b/libglusterfs/src/defaults.c @@ -463,6 +463,15 @@ default_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, return 0; } +int32_t +default_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata) +{ + STACK_UNWIND_STRICT(discard, frame, op_ret, op_errno, pre, post, xdata); + return 0; +} + int32_t default_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, char *spec_data) @@ -881,6 +890,15 @@ default_fallocate_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, return 0; } +int32_t +default_discard_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) +{ + STACK_WIND(frame, default_discard_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, + xdata); + return 0; +} /* FOPS */ @@ -1296,6 +1314,16 @@ default_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, return 0; } +int32_t +default_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) +{ + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, + xdata); + return 0; +} + int32_t default_forget (xlator_t *this, inode_t *inode) { diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h index bc2f6429..f3cbb3a4 100644 --- a/libglusterfs/src/defaults.h +++ b/libglusterfs/src/defaults.h @@ -249,6 +249,12 @@ int32_t default_fallocate(call_frame_t *frame, int32_t keep_size, off_t offset, size_t len, dict_t *xdata); +int32_t default_discard(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + /* Resume */ int32_t default_getspec_resume (call_frame_t *frame, xlator_t *this, @@ -465,6 +471,11 @@ int32_t default_fallocate_resume(call_frame_t *frame, int32_t keep_size, off_t offset, size_t len, dict_t *xdata); +int32_t default_discard_resume(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); /* _cbk */ @@ -680,6 +691,9 @@ int32_t default_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *pre, struct iatt *post, dict_t *xdata); +int32_t default_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); int32_t default_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index ba5075b2..072b1d52 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -68,6 +68,7 @@ const char *gf_fop_list[GF_FOP_MAXVALUE] = { [GF_FOP_RELEASEDIR] = "RELEASEDIR", [GF_FOP_FREMOVEXATTR]= "FREMOVEXATTR", [GF_FOP_FALLOCATE] = "FALLOCATE", + [GF_FOP_DISCARD] = "DISCARD", }; /* THIS */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 013cdfff..c2fbf5ac 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -198,6 +198,7 @@ typedef enum { GF_FOP_GETSPEC, GF_FOP_FREMOVEXATTR, GF_FOP_FALLOCATE, + GF_FOP_DISCARD, GF_FOP_MAXVALUE, } glusterfs_fop_t; diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index f57e8da5..9cceaf55 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -1947,6 +1947,36 @@ syncop_fallocate(xlator_t *subvol, fd_t *fd, int32_t keep_size, off_t offset, } +int +syncop_discard_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_discard(xlator_t *subvol, fd_t *fd, off_t offset, size_t len) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_discard_cbk, subvol->fops->discard, + fd, offset, len, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + int syncop_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, struct gf_flock *flock, diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 59e62ad1..43e71c4f 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -335,6 +335,7 @@ int syncop_fsyncdir (xlator_t *subvol, fd_t *fd, int datasync); int syncop_access (xlator_t *subvol, loc_t *loc, int32_t mask); int syncop_fallocate(xlator_t *subvol, fd_t *fd, int32_t keep_size, off_t offset, size_t len); +int syncop_discard(xlator_t *subvol, fd_t *fd, off_t offset, size_t len); int syncop_rename (xlator_t *subvol, loc_t *oldloc, loc_t *newloc); diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 1926240e..b1c090c1 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -80,6 +80,7 @@ fill_defaults (xlator_t *xl) SET_DEFAULT_FOP (setattr); SET_DEFAULT_FOP (fsetattr); SET_DEFAULT_FOP (fallocate); + SET_DEFAULT_FOP (discard); SET_DEFAULT_FOP (getspec); diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index ace73f2e..817eadde 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -425,6 +425,14 @@ typedef int32_t (*fop_fallocate_cbk_t) (call_frame_t *frame, struct iatt *preop_stbuf, struct iatt *postop_stbuf, dict_t *xdata); +typedef int32_t (*fop_discard_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + typedef int32_t (*fop_lookup_t) (call_frame_t *frame, xlator_t *this, loc_t *loc, @@ -650,6 +658,13 @@ typedef int32_t (*fop_fallocate_t) (call_frame_t *frame, size_t len, dict_t *xdata); +typedef int32_t (*fop_discard_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, + dict_t *xdata); + struct xlator_fops { fop_lookup_t lookup; fop_stat_t stat; @@ -694,6 +709,7 @@ struct xlator_fops { fop_fsetattr_t fsetattr; fop_getspec_t getspec; fop_fallocate_t fallocate; + fop_discard_t discard; /* these entries are used for a typechecking hack in STACK_WIND _only_ */ fop_lookup_cbk_t lookup_cbk; @@ -739,6 +755,7 @@ struct xlator_fops { fop_fsetattr_cbk_t fsetattr_cbk; fop_getspec_cbk_t getspec_cbk; fop_fallocate_cbk_t fallocate_cbk; + fop_discard_cbk_t discard_cbk; }; typedef int32_t (*cbk_forget_t) (xlator_t *this, -- cgit