02 May, 2013

40 commits

  • ceph_writepages_start() reads inode->i_size in two places. It can get
    different values between successive read, because truncate can change
    inode->i_size at any time. The race can lead to mismatch between data
    length of osd request and pages marked as writeback. When osd request
    finishes, it clear writeback page according to its data length. So
    some pages can be left in writeback state forever. The fix is only
    read inode->i_size once, save its value to a local variable and use
    the local variable when i_size is needed.

    Signed-off-by: Yan, Zheng
    Reviewed-by: Alex Elder

    Yan, Zheng
     
  • copy write checks in __generic_file_aio_write to ceph_aio_write.
    To make these checks cover sync write path.

    Signed-off-by: Yan, Zheng
    Reviewed-by: Alex Elder

    Yan, Zheng
     
  • There is deadlock as illustrated bellow. The fix is taking i_mutex
    before getting Fw cap reference.

    write truncate MDS
    --------------------- -------------------- --------------
    get Fw cap
    lock i_mutex
    lock i_mutex (blocked)
    request setattr.size ->

    Reviewed-by: Alex Elder
    Reviewed-by: Sage Weil

    Yan, Zheng
     
  • An osd request currently has two callbacks. They inform the
    initiator of the request when we've received confirmation for the
    target osd that a request was received, and when the osd indicates
    all changes described by the request are durable.

    The only time the second callback is used is in the ceph file system
    for a synchronous write. There's a race that makes some handling of
    this case unsafe. This patch addresses this problem. The error
    handling for this callback is also kind of gross, and this patch
    changes that as well.

    In ceph_sync_write(), if a safe callback is requested we want to add
    the request on the ceph inode's unsafe items list. Because items on
    this list must have their tid set (by ceph_osd_start_request()), the
    request added *after* the call to that function returns. The
    problem with this is that there's a race between starting the
    request and adding it to the unsafe items list; the request may
    already be complete before ceph_sync_write() even begins to put it
    on the list.

    To address this, we change the way the "safe" callback is used.
    Rather than just calling it when the request is "safe", we use it to
    notify the initiator the bounds (start and end) of the period during
    which the request is *unsafe*. So the initiator gets notified just
    before the request gets sent to the osd (when it is "unsafe"), and
    again when it's known the results are durable (it's no longer
    unsafe). The first call will get made in __send_request(), just
    before the request message gets sent to the messenger for the first
    time. That function is only called by __send_queued(), which is
    always called with the osd client's request mutex held.

    We then have this callback function insert the request on the ceph
    inode's unsafe list when we're told the request is unsafe. This
    will avoid the race because this call will be made under protection
    of the osd client's request mutex. It also nicely groups the setup
    and cleanup of the state associated with managing unsafe requests.

    The name of the "safe" callback field is changed to "unsafe" to
    better reflect its new purpose. It has a Boolean "unsafe" parameter
    to indicate whether the request is becoming unsafe or is now safe.
    Because the "msg" parameter wasn't used, we drop that.

    This resolves the original problem reportedin:
    http://tracker.ceph.com/issues/4706

    Reported-by: Yan, Zheng
    Signed-off-by: Alex Elder
    Reviewed-by: Yan, Zheng
    Reviewed-by: Sage Weil

    Alex Elder
     
  • In ceph_sync_write(), if a safe callback is supplied with a request,
    and an error is returned by ceph_osdc_wait_request(), a block of
    code is executed to remove the request from the unsafe writes list
    and drop references to capabilities acquired just prior to a call to
    ceph_osdc_wait_request().

    The only function used for this callback is sync_write_commit(),
    and it does *exactly* what that block of error handling code does.

    Now in ceph_osdc_wait_request(), if an error occurs (due to an
    interupt during a wait_for_completion_interruptible() call),
    complete_request() gets called, and that calls the request's
    safe_callback method if it's defined.

    So this means that this cleanup activity gets called twice in this
    case, which is erroneous (and in fact leads to a crash).

    Fix this by just letting the osd client handle the cleanup in
    the event of an interrupt.

    This resolves one problem mentioned in:
    http://tracker.ceph.com/issues/4706

    Signed-off-by: Alex Elder
    Reviewed-by: Yan, Zheng

    Alex Elder
     
  • add getattr/setattr and xattrs related methods.

    Signed-off-by: Yan, Zheng
    Reviewed-by: Greg Farnum

    Yan, Zheng
     
  • We don't need to use up entropy to choose an mds,
    so use prandom_u32() to get a pseudo-random number.

    Also, we don't need to choose a random mds if only
    one mds is available, so add special casing for the
    common case.

    Fixes http://tracker.ceph.com/issues/3579

    Signed-off-by: Sam Lang
    Reviewed-by: Greg Farnum
    Reviewed-by: Alex Elder

    Sam Lang
     
  • Implement layered read requests for format 2 rbd images.

    If an rbd image is a clone of a snapshot, the snapshot will be the
    clone's "parent" image. When an object read request on a clone
    comes back with ENOENT it indicates that the clone is not yet
    populated with that portion of the image's data, and the parent
    image should be consulted to satisfy the read.

    When this occurs, a new image request is created, directed to the
    parent image. The offset and length of the image are the same as
    the image-relative offset and length of the object request that
    produced ENOENT. Data from the parent image therefore satisfies the
    object read request for the original image request.

    While this code works, it will not be active until we enable the
    layering feature (by adding RBD_FEATURE_LAYERING to the value of
    RBD_FEATURES_SUPPORTED).

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Call the probe function for the parent device if one is present.
    Since we don't formally support the layering feature we won't
    be using this functionality just yet.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Add a flag to distinguish between object requests being done on
    standalone objects and requests being sent for objects representing
    rbd image data (i.e., object requests that are the result of image
    request).

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • We're going to need some more Boolean values for object requests,
    so create a flags bit field and use it to record whether the request
    is done.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Encapsulate the code that completes processing of an object request
    that's part of an image request.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Define a flag indicating whether an image request is for a layered
    image (one with a parent image to which requests will be redirected
    if the target object of a request does not exist). The code that
    checks this flag will be added shortly.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Define a flag indicating whether an image request originated from
    the Linux block layer (from blk_fetch_request()) or whether it was
    initiated in order to satisfy an object request for a child image
    of a layered rbd device. For image requests initiated by objects of
    child images we'll save a pointer to the object request rather than
    the Linux block request.

    For now, only block requests are used.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • There are several Boolean values we'll be maintaining for image
    requests. Switch from the single write_request field to a
    general-purpose flags field, and use one if its bits to represent
    the direction of I/O for the image request. Define helper functions
    for setting and testing that flag.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • For an image object request we will need to know what offset within
    the rbd image the request covers. Record that when the object
    request gets created.

    Update the I/O error warnings so they use this so what's reported
    is more informative.

    Rename a local variable to fit the convention used everywhere else.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Compute the total number of bytes transferred for an image
    request--the sum across each of the request's object requests.
    To avoid contention do it only when all object requests are
    complete, in rbd_img_request_complete().

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • If any image object request produces a non-zero result, preserve
    that as the result of the overall image request. If multiple
    objects have non-zero results, save only the first one.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • There is a new rbd feature bit defined for "fancy striping." Add
    it to the ones defined in the kernel client.

    Change RBD_FEATURES_ALL so it represents the set of all feature
    bits (rather than just the ones we support). Define a new symbol
    RBD_FEATURES_SUPPORTED to indicate the supported ones.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Right now the data for a method call is specified via a pointer and
    length, and it's copied--along with the class and method name--into
    a pagelist data item to be sent to the osd. Instead, encode the
    data in a data item separate from the class and method names.

    This will allow large amounts of data to be supplied to methods
    without copying. Only rbd uses the class functionality right now,
    and when it really needs this it will probably need to use a page
    array rather than a page list. But this simple implementation
    demonstrates the functionality on the osd client, and that's enough
    for now.

    This resolves:
    http://tracker.ceph.com/issues/4104

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Change the names of the functions that put data on a pagelist to
    reflect that we're adding to whatever's already there rather than
    just setting it to the one thing. Currently only one data item is
    ever added to a message, but that's about to change.

    This resolves:
    http://tracker.ceph.com/issues/2770

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • This patch adds support to the messenger for more than one data item
    in its data list.

    A message data cursor has two more fields to support this:
    - a count of the number of bytes left to be consumed across
    all data items in the list, "total_resid"
    - a pointer to the head of the list (for validation only)

    The cursor initialization routine has been split into two parts: the
    outer one, which initializes the cursor for traversing the entire
    list of data items; and the inner one, which initializes the cursor
    to start processing a single data item.

    When a message cursor is first initialized, the outer initialization
    routine sets total_resid to the length provided. The data pointer
    is initialized to the first data item on the list. From there, the
    inner initialization routine finishes by setting up to process the
    data item the cursor points to.

    Advancing the cursor consumes bytes in total_resid. If the resid
    field reaches zero, it means the current data item is fully
    consumed. If total_resid indicates there is more data, the cursor
    is advanced to point to the next data item, and then the inner
    initialization routine prepares for using that. (A check is made at
    this point to make sure we don't wrap around the front of the list.)

    The type-specific init routines are modified so they can be given a
    length that's larger than what the data item can support. The resid
    field is initialized to the smaller of the provided length and the
    length of the entire data item.

    When total_resid reaches zero, we're done.

    This resolves:
    http://tracker.ceph.com/issues/3761

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • In place of the message data pointer, use a list head which links
    through message data items. For now we only support a single entry
    on that list.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Rather than having a ceph message data item point to the cursor it's
    associated with, have the cursor point to a data item. This will
    allow a message cursor to be used for more than one data item.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • A message will only be processing a single data item at a time, so
    there's no need for each data item to have its own cursor.

    Move the cursor embedded in the message data structure into the
    message itself. To minimize the impact, keep the data->cursor
    field, but make it be a pointer to the cursor in the message.

    Move the definition of ceph_msg_data above ceph_msg_data_cursor so
    the cursor can point to the data without a forward definition rather
    than vice-versa.

    This and the upcoming patches are part of:
    http://tracker.ceph.com/issues/3761

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • The bio is the only data item type that doesn't record its full
    length. Fix that.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • We know the length of our message buffers. If we get a message
    that's too long, just dump it and ignore it. If skip was set
    then con->in_msg won't be valid, so be careful not to dereference
    a null pointer in the process.

    This resolves:
    http://tracker.ceph.com/issues/4664

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • This patch:
    15a0d7b libceph: record message data length
    did not enclose some bio-specific code inside CONFIG_BLOCK as
    it should have. Fix that.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Finally! Convert the osd op data pointers into real structures, and
    make the switch over to using them instead of having all ops share
    the in and/or out data structures in the osd request.

    Set up a new function to traverse the set of ops and release any
    data associated with them (pages).

    This and the patches leading up to it resolve:
    http://tracker.ceph.com/issues/4657

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Still using the osd request r_data_in and r_data_out pointer, but
    we're basically only referring to it via the data pointers in the
    osd ops. And we're transferring that information to the request
    or reply message only when the op indicates it's needed, in
    osd_req_encode_op().

    To avoid a forward reference, ceph_osdc_msg_data_set() was moved up
    in the file.

    Don't bother calling ceph_osd_data_init(), in ceph_osd_alloc(),
    because the ops array will already be zeroed anyway.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • This ends up being a rather large patch but what it's doing is
    somewhat straightforward.

    Basically, this is replacing two calls with one. The first of the
    two calls is initializing a struct ceph_osd_data with data (either a
    page array, a page list, or a bio list); the second is setting an
    osd request op so it associates that data with one of the op's
    parameters. In place of those two will be a single function that
    initializes the op directly.

    That means we sort of fan out a set of the needed functions:
    - extent ops with pages data
    - extent ops with pagelist data
    - extent ops with bio list data
    and
    - class ops with page data for receiving a response

    We also have define another one, but it's only used internally:
    - class ops with pagelist data for request parameters

    Note that we *still* haven't gotten rid of the osd request's
    r_data_in and r_data_out fields. All the osd ops refer to them for
    their data. For now, these data fields are pointers assigned to the
    appropriate r_data_* field when these new functions are called.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • All calls of ceph_osdc_start_request() are preceded (in the case of
    rbd, almost) immediately by a call to ceph_osdc_build_request().

    Move the build calls at the top of ceph_osdc_start_request() out of
    there and into the ceph_osdc_build_request(). Nothing prevents
    moving these calls to the top of ceph_osdc_build_request(), either
    (and we're going to want them there in the next patch) so put them
    at the top.

    This and the next patch are related to:
    http://tracker.ceph.com/issues/4657

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • This simply moves ceph_osdc_build_request() later in its source
    file without any change. Done as a separate patch to facilitate
    review of the change in the next patch.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • An object class method is formatted using a pagelist which contains
    the class name, the method name, and the data concatenated into an
    osd request's outbound data.

    Currently when a class op is initialized in osd_req_op_cls_init(),
    the lengths of and pointers to these three items are recorded.
    Later, when the op is getting formatted into the request message, a
    new pagelist is created and that is when these items get copied into
    the pagelist.

    This patch makes it so the pagelist to hold these items is created
    when the op is initialized instead.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • This patch just trivially moves around some code for consistency.

    In preparation for initializing osd request data fields in
    ceph_osdc_build_request(), I wanted to verify that rbd did in fact
    call that immediately before it called ceph_osdc_start_request().
    It was true (although image requests are built in a group and then
    started as a group). But I made the changes here just to make
    it more obvious, by making all of the calls follow a common
    sequence:
    osd_req_op__init();
    ceph_osd_data__init()
    osd_req_op__()
    rbd_osd_req_format()
    ...
    ret = rbd_obj_request_submit()

    I moved the initialization of the callback for image object requests
    into rbd_img_request_fill_bio(), again, for consistency. To avoid
    a forward reference, I moved the definition of rbd_img_obj_callback()
    up in the file.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • The osd data for a request is currently initialized inside
    rbd_osd_req_create(), but that assumes an object request's data
    belongs in the osd request's data in or data out field.

    There are only three places where requests with data are set up, and
    it turns out it's easier to call just the osd data init routines
    directly there rather than handling it in rbd_osd_req_create().

    (The real motivation here is moving toward getting rid of the
    osd request in and out data fields.)

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • Currently an object request has its osd request's data field set in
    rbd_osd_req_format_op(). That assumes a single osd op per object
    request, and that won't be the case for long.

    Move the code that sets this out and into the caller.

    Rename rbd_osd_req_format_op() to be just rbd_osd_req_format(),
    removing the notion that it's doing anything op-specific.

    This and the next patch resolve:
    http://tracker.ceph.com/issues/4658

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • An osd request now holds all of its source op structures, and every
    place that initializes one of these is in fact initializing one
    of the entries in the the osd request's array.

    So rather than supplying the address of the op to initialize, have
    caller specify the osd request and an indication of which op it
    would like to initialize. This better hides the details the
    op structure (and faciltates moving the data pointers they use).

    Since osd_req_op_init() is a common routine, and it's not used
    outside the osd client code, give it static scope. Also make
    it return the address of the specified op (so all the other
    init routines don't have to repeat that code).

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • An extent type osd operation currently implies that there will
    be corresponding data supplied in the data portion of the request
    (for write) or response (for read) message. Similarly, an osd class
    method operation implies a data item will be supplied to receive
    the response data from the operation.

    Add a ceph_osd_data pointer to each of those structures, and assign
    it to point to eithre the incoming or the outgoing data structure in
    the osd message. The data is not always available when an op is
    initially set up, so add two new functions to allow setting them
    after the op has been initialized.

    Begin to make use of the data item pointer available in the osd
    operation rather than the request data in or out structure in
    places where it's convenient. Add some assertions to verify
    pointers are always set the way they're expected to be.

    This is a sort of stepping stone toward really moving the data
    into the osd request ops, to allow for some validation before
    making that jump.

    This is the first in a series of patches that resolve:
    http://tracker.ceph.com/issues/4657

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder
     
  • There are fields "indata" and "indata_len" defined the ceph osd
    request op structure. The "in" part is with from the point of view
    of the osd server, but is a little confusing here on the client
    side. Change their names to use "request" instead of "in" to
    indicate that it defines data provided with the request (as opposed
    the data returned in the response).

    Rename the local variable in osd_req_encode_op() to match.

    Signed-off-by: Alex Elder
    Reviewed-by: Josh Durgin

    Alex Elder