Implement client support for the YFSVL.GetCellName RPC operation by which
YFS permits the canonical cell name to be queried from a VL server.

Signed-off-by: David Howells <dhowe...@redhat.com>
---

 fs/afs/afs.h               |    2 -
 fs/afs/afs_vl.h            |    1 
 fs/afs/internal.h          |    2 +
 fs/afs/protocol_yfs.h      |    2 -
 fs/afs/vlclient.c          |  111 ++++++++++++++++++++++++++++++++++++++++++++
 include/trace/events/afs.h |    4 ++
 6 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index f8e34406243e..432cb4b23961 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -10,7 +10,7 @@
 
 #include <linux/in.h>
 
-#define AFS_MAXCELLNAME                64      /* Maximum length of a cell 
name */
+#define AFS_MAXCELLNAME                256     /* Maximum length of a cell 
name */
 #define AFS_MAXVOLNAME         64      /* Maximum length of a volume name */
 #define AFS_MAXNSERVERS                8       /* Maximum servers in a basic 
volume record */
 #define AFS_NMAXNSERVERS       13      /* Maximum servers in a N/U-class 
volume record */
diff --git a/fs/afs/afs_vl.h b/fs/afs/afs_vl.h
index e9b8029920ec..9c65ffb8a523 100644
--- a/fs/afs/afs_vl.h
+++ b/fs/afs/afs_vl.h
@@ -22,6 +22,7 @@ enum AFSVL_Operations {
        VLGETENTRYBYNAMEU       = 527,  /* AFS Get VLDB entry by name 
(UUID-variant) */
        VLGETADDRSU             = 533,  /* AFS Get addrs for fileserver */
        YVLGETENDPOINTS         = 64002, /* YFS Get endpoints for file/volume 
server */
+       YVLGETCELLNAME          = 64014, /* YFS Get actual cell name */
        VLGETCAPABILITIES       = 65537, /* AFS Get server capabilities */
 };
 
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index dce03e068cab..3606cfa50832 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -116,6 +116,7 @@ struct afs_call {
                long                    ret0;   /* Value to reply with instead 
of 0 */
                struct afs_addr_list    *ret_alist;
                struct afs_vldb_entry   *ret_vldb;
+               char                    *ret_str;
        };
        struct afs_operation    *op;
        unsigned int            server_index;
@@ -1373,6 +1374,7 @@ extern struct afs_addr_list *afs_vl_get_addrs_u(struct 
afs_vl_cursor *, const uu
 extern struct afs_call *afs_vl_get_capabilities(struct afs_net *, struct 
afs_addr_cursor *,
                                                struct key *, struct 
afs_vlserver *, unsigned int);
 extern struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *, 
const uuid_t *);
+extern char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *);
 
 /*
  * vl_probe.c
diff --git a/fs/afs/protocol_yfs.h b/fs/afs/protocol_yfs.h
index 32be9c698348..b5bd03b1d3c7 100644
--- a/fs/afs/protocol_yfs.h
+++ b/fs/afs/protocol_yfs.h
@@ -8,7 +8,7 @@
 #define YFS_FS_SERVICE 2500
 #define YFS_CM_SERVICE 2501
 
-#define YFSCBMAX 1024
+#define YFSCBMAX       1024
 
 enum YFS_CM_Operations {
        YFSCBProbe              = 206,  /* probe client */
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index d0c85623ce8f..fd82850cd424 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -645,3 +645,114 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct 
afs_vl_cursor *vc,
        afs_make_call(&vc->ac, call, GFP_KERNEL);
        return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, 
&vc->ac);
 }
+
+/*
+ * Deliver reply data to a YFSVL.GetCellName operation.
+ */
+static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call)
+{
+       char *cell_name;
+       u32 namesz, paddedsz;
+       int ret;
+
+       _enter("{%u,%zu/%u}",
+              call->unmarshall, iov_iter_count(call->iter), call->count);
+
+       switch (call->unmarshall) {
+       case 0:
+               afs_extract_to_tmp(call);
+               call->unmarshall++;
+
+               /* Fall through - and extract the cell name length */
+       case 1:
+               ret = afs_extract_data(call, true);
+               if (ret < 0)
+                       return ret;
+
+               namesz = ntohl(call->tmp);
+               if (namesz > AFS_MAXCELLNAME)
+                       return afs_protocol_error(call, 
afs_eproto_cellname_len);
+               paddedsz = (namesz + 3) & ~3;
+               call->count = namesz;
+               call->count2 = paddedsz - namesz;
+
+               cell_name = kmalloc(namesz + 1, GFP_KERNEL);
+               if (!cell_name)
+                       return -ENOMEM;
+               cell_name[namesz] = 0;
+               call->ret_str = cell_name;
+
+               afs_extract_begin(call, cell_name, namesz);
+               call->unmarshall++;
+
+               /* Fall through - and extract cell name */
+       case 2:
+               ret = afs_extract_data(call, true);
+               if (ret < 0)
+                       return ret;
+
+               afs_extract_discard(call, call->count2);
+               call->unmarshall++;
+
+               /* Fall through - and extract padding */
+       case 3:
+               ret = afs_extract_data(call, false);
+               if (ret < 0)
+                       return ret;
+
+               call->unmarshall++;
+               break;
+       }
+
+       _leave(" = 0 [done]");
+       return 0;
+}
+
+static void afs_destroy_yfsvl_get_cell_name(struct afs_call *call)
+{
+       kfree(call->ret_str);
+       afs_flat_call_destructor(call);
+}
+
+/*
+ * VL.GetCapabilities operation type
+ */
+static const struct afs_call_type afs_YFSVLGetCellName = {
+       .name           = "YFSVL.GetCellName",
+       .op             = afs_YFSVL_GetCellName,
+       .deliver        = afs_deliver_yfsvl_get_cell_name,
+       .destructor     = afs_destroy_yfsvl_get_cell_name,
+};
+
+/*
+ * Probe a volume server for the capabilities that it supports.  This can
+ * return up to 196 words.
+ *
+ * We use this to probe for service upgrade to determine what the server at the
+ * other end supports.
+ */
+char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc)
+{
+       struct afs_call *call;
+       struct afs_net *net = vc->cell->net;
+       __be32 *bp;
+
+       _enter("");
+
+       call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0);
+       if (!call)
+               return ERR_PTR(-ENOMEM);
+
+       call->key = vc->key;
+       call->ret_str = NULL;
+       call->max_lifespan = AFS_VL_MAX_LIFESPAN;
+
+       /* marshall the parameters */
+       bp = call->request;
+       *bp++ = htonl(YVLGETCELLNAME);
+
+       /* Can't take a ref on server */
+       trace_afs_make_vl_call(call);
+       afs_make_call(&vc->ac, call, GFP_KERNEL);
+       return (char *)afs_wait_for_call_to_complete(call, &vc->ac);
+}
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h
index f4d66919fb22..f320b3ad54da 100644
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -111,6 +111,7 @@ enum afs_vl_operation {
        afs_VL_GetEntryByNameU  = 527,          /* AFS Get Vol Entry By Name 
operation ID */
        afs_VL_GetAddrsU        = 533,          /* AFS Get FS server addresses 
*/
        afs_YFSVL_GetEndpoints  = 64002,        /* YFS Get FS & Vol server 
addresses */
+       afs_YFSVL_GetCellName   = 64014,        /* YFS Get actual cell name */
        afs_VL_GetCapabilities  = 65537,        /* AFS Get VL server 
capabilities */
 };
 
@@ -143,6 +144,7 @@ enum afs_eproto_cause {
        afs_eproto_bad_status,
        afs_eproto_cb_count,
        afs_eproto_cb_fid_count,
+       afs_eproto_cellname_len,
        afs_eproto_file_type,
        afs_eproto_ibulkst_cb_count,
        afs_eproto_ibulkst_count,
@@ -316,6 +318,7 @@ enum afs_cb_break_reason {
        EM(afs_VL_GetEntryByNameU,              "VL.GetEntryByNameU") \
        EM(afs_VL_GetAddrsU,                    "VL.GetAddrsU") \
        EM(afs_YFSVL_GetEndpoints,              "YFSVL.GetEndpoints") \
+       EM(afs_YFSVL_GetCellName,               "YFSVL.GetCellName") \
        E_(afs_VL_GetCapabilities,              "VL.GetCapabilities")
 
 #define afs_edit_dir_ops                                 \
@@ -345,6 +348,7 @@ enum afs_cb_break_reason {
        EM(afs_eproto_bad_status,       "BadStatus") \
        EM(afs_eproto_cb_count,         "CbCount") \
        EM(afs_eproto_cb_fid_count,     "CbFidCount") \
+       EM(afs_eproto_cellname_len,     "CellNameLen") \
        EM(afs_eproto_file_type,        "FileTYpe") \
        EM(afs_eproto_ibulkst_cb_count, "IBS.CbCount") \
        EM(afs_eproto_ibulkst_count,    "IBS.FidCount") \


Reply via email to