diff options
| author | Amar Tumballi <amar@gluster.com> | 2009-11-30 01:20:20 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-12-01 10:03:02 -0800 | 
| commit | ade63327d7beaf6f8458aba9f8980e15016b6f31 (patch) | |
| tree | 03b367fe2a84a69d1900d6e49664bc010cc6a92f | |
| parent | 4f7886034742709b285499aa0052fdb21e9c42f6 (diff) | |
trash_ftruncate fop added
Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 142 (enhance features/trash  translator so it can work on client side too..)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=142
| -rw-r--r-- | xlators/features/trash/src/trash.c | 357 | 
1 files changed, 357 insertions, 0 deletions
diff --git a/xlators/features/trash/src/trash.c b/xlators/features/trash/src/trash.c index 2efca78b725..378c579b921 100644 --- a/xlators/features/trash/src/trash.c +++ b/xlators/features/trash/src/trash.c @@ -26,6 +26,12 @@  int32_t +trash_ftruncate_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                           int32_t op_ret, int32_t op_errno, +                           struct iovec *vector, int32_t count, +                           struct stat *stbuf, struct iobref *iobuf); + +int32_t  trash_truncate_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                             int32_t op_ret, int32_t op_errno,                             struct stat *prebuf, struct stat *postbuf); @@ -1048,6 +1054,356 @@ out:          return 0;  } +int32_t +trash_ftruncate_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                            int32_t op_ret, int32_t op_errno, +                            struct stat *preparent, struct stat *postparent) +{ +        trash_local_t *local = NULL; + +        local = frame->local; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "%s: failed to unlink new file: %s", +                        local->newloc.path, strerror(op_errno)); + +        } + +        STACK_WIND (frame, trash_common_unwind_buf_cbk, +                    FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate, +                    local->fd, local->fop_offset); + +        return 0; +} + +int32_t +trash_ftruncate_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                            int32_t op_ret, int32_t op_errno, +                            struct stat *prebuf, struct stat *postbuf) +{ +        trash_local_t *local = NULL; + +        local = frame->local; + +        if (op_ret == -1) { +                STACK_WIND (frame, trash_ftruncate_unlink_cbk, +                            FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink, +                            &local->newloc); +                return 0; +        } + +        if (local->cur_offset < local->fsize) { +                local->cur_offset += GF_BLOCK_READV_SIZE; +                STACK_WIND (frame, trash_ftruncate_readv_cbk, +                            FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv, +                            local->fd, (size_t)GF_BLOCK_READV_SIZE, +                            local->cur_offset); +                return 0; +        } + +        STACK_WIND (frame, trash_common_unwind_buf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->ftruncate, local->fd, +                    local->fop_offset); + +        return 0; +} + + +int32_t +trash_ftruncate_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                           int32_t op_ret, int32_t op_errno, +                           struct iovec *vector, int32_t count, +                           struct stat *stbuf, struct iobref *iobuf) +{ +        trash_local_t *local = NULL; + +        local = frame->local; +        local->fsize = stbuf->st_size; + +        if (op_ret == -1) { +                STACK_WIND (frame, trash_ftruncate_unlink_cbk, +                            FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink, +                            &local->newloc); +                return 0; +        } + +        STACK_WIND (frame, trash_ftruncate_writev_cbk, +                    FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, +                    local->newfd, vector, count, local->cur_offset, NULL); + +        return 0; +} + + +int32_t +trash_ftruncate_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                            int32_t op_ret, int32_t op_errno, fd_t *fd, +                            inode_t *inode, struct stat *buf, +                            struct stat *preparent, struct stat *postparent) +{ +        trash_local_t *local = NULL; +        char          *tmp_str = NULL; +        char          *dir_name = NULL; +        char          *tmp_path = NULL; +        loc_t          tmp_loc = {0,}; + +        local = frame->local; + +        if ((op_ret == -1) && (op_errno == ENOENT)) { +                tmp_str = strdup (local->newpath); +                if (!tmp_str) { +                        gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                } +                dir_name = dirname (tmp_str); + +                tmp_path = strdup (dir_name); +                if (!tmp_path) { +                        gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                } +                tmp_loc.path = tmp_path; + +                /* TODO: create the directory with proper permissions */ +                STACK_WIND_COOKIE (frame, trash_truncate_mkdir_cbk, +                                   tmp_path, FIRST_CHILD(this), +                                   FIRST_CHILD(this)->fops->mkdir, +                                   &tmp_loc, 0755); +                free (tmp_str); +                return 0; +        } + +        if (op_ret == -1) { +                STACK_WIND (frame, trash_common_unwind_buf_cbk, +                            FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->ftruncate, +                            local->fd, local->fop_offset); +                return 0; +        } + +        STACK_WIND (frame, trash_ftruncate_readv_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->readv, local->fd, +                    (size_t)GF_BLOCK_READV_SIZE, local->cur_offset); + +        return 0; +} + + +int32_t +trash_ftruncate_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                           int32_t op_ret, int32_t op_errno, inode_t *inode, +                           struct stat *stbuf, struct stat *preparent, +                           struct stat *postparent) +{ +        trash_local_t       *local = NULL; +        char                *tmp_str = NULL; +        char                *tmp_path = NULL; +        char                *tmp_dirname = NULL; +        char                *dir_name = NULL; +        int32_t              count = 0; +        int32_t              flags = 0; +        int32_t              loop_count = 0; +        int                  i = 0; +        loc_t                tmp_loc = {0,}; + +        local   = frame->local; +        if (!local) +                return 0; + +        loop_count = local->loop_count; + +        tmp_str = strdup (local->newpath); +        if (!tmp_str) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +        } + +        if ((op_ret == -1) && (op_errno == ENOENT)) { +                tmp_dirname = strchr (tmp_str, '/'); +                while (tmp_dirname) { +                        count = tmp_dirname - tmp_str; +                        if (count == 0) +                                count = 1; +                        i++; +                        if (i > loop_count) +                                break; +                        tmp_dirname = strchr (tmp_str + count + 1, '/'); +                } +                tmp_path = strndup (local->newpath, count); +                if (!tmp_path) { +                        gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                } +                tmp_loc.path = tmp_path; +                STACK_WIND_COOKIE (frame, trash_ftruncate_mkdir_cbk, +                                   tmp_path, this->children->xlator, +                                   this->children->xlator->fops->mkdir, +                                   &tmp_loc, 0755); + +                goto out; +        } + +        if (op_ret == 0) { +                dir_name = dirname (tmp_str); +                if (strcmp ((char*)cookie, dir_name) == 0) { +                        flags = O_CREAT|O_EXCL|O_WRONLY; + +                        //Call create again once directory structure is created. +                        STACK_WIND (frame, trash_ftruncate_create_cbk, +                                    FIRST_CHILD(this), +                                    FIRST_CHILD(this)->fops->create, +                                    &local->newloc, flags, +                                    local->loc.inode->st_mode, local->newfd); +                        goto out; +                } +        } + +        LOCK (&frame->lock); +        { +                loop_count = ++local->loop_count; +        } +        UNLOCK (&frame->lock); +        tmp_dirname = strchr (tmp_str, '/'); +        while (tmp_dirname) { +                count = tmp_dirname - tmp_str; +                if (count == 0) +                        count = 1; + +                i++; +                if ((i > loop_count) || (count > PATH_MAX)) +                        break; +                tmp_dirname = strchr (tmp_str + count + 1, '/'); +        } +        tmp_path = strndup (local->newpath, count); +        if (!tmp_path) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +        } +        tmp_loc.path = tmp_path; + +        STACK_WIND_COOKIE (frame, trash_ftruncate_mkdir_cbk, tmp_path, +                           this->children->xlator, +                           this->children->xlator->fops->mkdir, +                           &tmp_loc, 0755); + +out: +        free (cookie); /* strdup (dir_name) was sent here :) */ +        free (tmp_str); + +        return 0; +} + + +int32_t +trash_ftruncate_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                           int32_t op_ret, int32_t op_errno, struct stat *buf) +{ +        trash_private_t *priv  = NULL; +        trash_local_t   *local = NULL; + +        priv  = this->private; +        local = frame->local; + +        if (op_ret == -1) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "%s: %s",local->newloc.path, strerror(op_errno)); + +                TRASH_STACK_UNWIND (frame, -1, op_errno, buf, NULL); +                return 0; +        } +        if ((buf->st_size == 0) || (buf->st_size > priv->max_trash_file_size)) +        { +                STACK_WIND (frame, trash_common_unwind_buf_cbk, +                            this->children->xlator, +                            this->children->xlator->fops->ftruncate, +                            local->fd, local->fop_offset); +                return 0; +        } + + +        STACK_WIND (frame, trash_ftruncate_create_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->create, &local->newloc, +                    ( O_CREAT | O_EXCL | O_WRONLY ), +                    local->loc.inode->st_mode, local->newfd); + +        return 0; +} + +int32_t +trash_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ +        trash_elim_pattern_t  *trav = NULL; +        trash_private_t       *priv = NULL; +        trash_local_t         *local = NULL; +        dentry_t              *dir_entry = NULL; +        struct tm             *tm = NULL; +        char                  *pathbuf = NULL; +        inode_t               *newinode = NULL; +        time_t                 utime = 0; +        char                   timestr[256]; +        int32_t                retval = 0; +        int32_t                match = 0; + +        priv = this->private; + +        dir_entry = __dentry_search_arbit (fd->inode); +        retval = inode_path (fd->inode, NULL, &pathbuf); + +        if (priv->eliminate) { +                trav = priv->eliminate; +                while (trav) { +                        if (fnmatch(trav->pattern, dir_entry->name, 0) == 0) { +                                match++; +                                break; +                        } +                        trav = trav->next; +                } +        } + +        if ((strncmp (pathbuf, priv->trash_dir, +                      strlen (priv->trash_dir)) == 0) || +            (offset >= priv->max_trash_file_size) || +            (!retval) || +            match) { +                STACK_WIND (frame, trash_common_unwind_buf_cbk, +                            FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->ftruncate, +                            fd, offset); +                return 0; +        } + +        local = CALLOC (1, sizeof (trash_local_t)); +        if (!local) { +                gf_log (this->name, GF_LOG_DEBUG, "out of memory"); +                TRASH_STACK_UNWIND (frame, -1, ENOMEM, NULL, NULL); +                return 0; +        } + +        utime = time (NULL); +        tm    = localtime (&utime); +        strftime (timestr, 256, ".%Y-%m-%d-%H%M%S", tm); + +        strcpy (local->newpath, priv->trash_dir); +        strcat (local->newpath, pathbuf); +        strcat (local->newpath, timestr); + +        local->fd = fd_ref (fd); +        newinode = inode_new (fd->inode->table); +        local->newfd = fd_create (newinode, frame->root->pid); +        frame->local=local; + +        local->newloc.inode = newinode; +        local->newloc.path = local->newpath; + +        local->loc.inode = inode_ref (fd->inode); +        local->loc.ino   = fd->inode->ino; +        local->loc.path  = pathbuf; + +        local->fop_offset = offset; +        local->cur_offset = offset; + +        STACK_WIND (frame, trash_ftruncate_fstat_cbk, this->children->xlator, +                    this->children->xlator->fops->fstat, fd); + +        return 0; +} +  /**   * trash_init -   */ @@ -1166,6 +1522,7 @@ struct xlator_fops fops = {          .unlink    = trash_unlink,          .rename    = trash_rename,          .truncate  = trash_truncate, +        .ftruncate = trash_ftruncate,  };  struct xlator_mops mops = {  | 
