Note, this is an experimental interface and could be changed someday.
 
+config BLK_CGROUP_FC_APPID
+       bool "Enable support to track FC I/O Traffic across cgroup applications"
+       depends on BLK_CGROUP=y
+       help
+         Enabling this option enables the support to track FC I/O traffic across
+         cgroup applications. It enables the Fabric and the storage targets to
+         identify, monitor, and handle FC traffic based on VM tags by inserting
+         application specific identification into the FC frame.
+
 config BLK_CGROUP_IOCOST
        bool "Enable support for cost model based cgroup IO controller"
        depends on BLK_CGROUP=y
 
          each attached FiberChannel device to sysfs, say Y.
          Otherwise, say N.
 
+config FC_APPID
+       bool "Enable support to track FC I/O Traffic"
+       depends on BLOCK && BLK_CGROUP
+       depends on SCSI
+       select BLK_CGROUP_FC_APPID
+       default y
+       help
+         If you say Y here, it enables the support to track
+         FC I/O traffic over fabric. It enables the Fabric and the
+         storage targets to identify, monitor, and handle FC traffic
+         based on VM tags by inserting application specific
+         identification into the FC frame.
+
 config SCSI_ISCSI_ATTRS
        tristate "iSCSI Transport Attributes"
        depends on SCSI && NET
 
 
 /* Max limits for throttle policy */
 #define THROTL_IOPS_MAX                UINT_MAX
+#define FC_APPID_LEN              129
+
 
 #ifdef CONFIG_BLK_CGROUP
 
        struct blkcg_policy_data        *cpd[BLKCG_MAX_POLS];
 
        struct list_head                all_blkcgs_node;
+#ifdef CONFIG_BLK_CGROUP_FC_APPID
+       char                            fc_app_id[FC_APPID_LEN];
+#endif
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct list_head                cgwb_list;
 #endif
 
 #endif /* CONFIG_BLOCK */
 #endif /* CONFIG_BLK_CGROUP */
+
+#ifdef CONFIG_BLK_CGROUP_FC_APPID
+/*
+ * Sets the fc_app_id field associted to blkcg
+ * @app_id: application identifier
+ * @cgrp_id: cgroup id
+ * @app_id_len: size of application identifier
+ */
+static inline int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len)
+{
+       struct cgroup *cgrp;
+       struct cgroup_subsys_state *css;
+       struct blkcg *blkcg;
+       int ret  = 0;
+
+       if (app_id_len > FC_APPID_LEN)
+               return -EINVAL;
+
+       cgrp = cgroup_get_from_id(cgrp_id);
+       if (!cgrp)
+               return -ENOENT;
+       css = cgroup_get_e_css(cgrp, &io_cgrp_subsys);
+       if (!css) {
+               ret = -ENOENT;
+               goto out_cgrp_put;
+       }
+       blkcg = css_to_blkcg(css);
+       /*
+        * There is a slight race condition on setting the appid.
+        * Worst case an I/O may not find the right id.
+        * This is no different from the I/O we let pass while obtaining
+        * the vmid from the fabric.
+        * Adding the overhead of a lock is not necessary.
+        */
+       strlcpy(blkcg->fc_app_id, app_id, app_id_len);
+       css_put(css);
+out_cgrp_put:
+       cgroup_put(cgrp);
+       return ret;
+}
+
+/**
+ * blkcg_get_fc_appid - get the fc app identifier associated with a bio
+ * @bio: target bio
+ *
+ * On success return the fc_app_id, on failure return NULL
+ */
+static inline char *blkcg_get_fc_appid(struct bio *bio)
+{
+       if (bio && bio->bi_blkg &&
+               (bio->bi_blkg->blkcg->fc_app_id[0] != '\0'))
+               return bio->bi_blkg->blkcg->fc_app_id;
+       return NULL;
+}
+#else
+static inline int blkcg_set_fc_appid(char *buf, u64 id, size_t len) { return -EINVAL; }
+static inline char *blkcg_get_fc_appid(struct bio *bio) { return NULL; }
+#endif /*CONFIG_BLK_CGROUP_FC_APPID*/
 #endif /* _BLK_CGROUP_H */