]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: implement online get/set fs label
authorEric Sandeen <sandeen@sandeen.net>
Thu, 28 Jun 2018 20:11:57 +0000 (15:11 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 28 Jun 2018 20:11:57 +0000 (15:11 -0500)
Source kernel commit: f7664b31975bd893190708e76b2c424328f0c49b

The GET ioctl is trivial, just return the current label.

The SET ioctl is more involved:
It transactionally modifies the superblock to write a new filesystem
label to the primary super.

A new variant of xfs_sync_sb then writes the superblock buffer
immediately to disk so that the change is visible from userspace.

It then invalidates any page cache that userspace might have previously
read on the block device so that i.e. blkid can see the change
immediately, and updates all secondary superblocks as userspace relable
does.

Also includes for bisectability:

xfs: use xfs_trans_getsb in xfs_sync_sb_buf

Source kernel commit: 89c2e71123badc1e75316ccd969ee8a5c6fd921a

Use xfs_trans_getsb rather than reaching right in for
mp->m_sb_bp; I think this is more correct, and it facilitates
building this libxfs code in userspace as well.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
[darrick: use dchinner's new xfs_update_secondary_sbs function]
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_format.h
libxfs/xfs_sb.c
libxfs/xfs_sb.h

index cc1055d024965080c64fcdbe5d774acf1815a1f7..850a400b939b81c306d3bb9a5fb38e896b521358 100644 (file)
@@ -98,6 +98,9 @@ struct xfs_ifork;
         XFS_SB_VERSION2_PROJID32BIT    | \
         XFS_SB_VERSION2_FTYPE)
 
+/* Maximum size of the xfs filesystem label, no terminating NULL */
+#define XFSLABEL_MAX                   12
+
 /*
  * Superblock - in core version.  Must match the ondisk version below.
  * Must be padded to 64 bit alignment.
@@ -122,7 +125,7 @@ typedef struct xfs_sb {
        uint16_t        sb_sectsize;    /* volume sector size, bytes */
        uint16_t        sb_inodesize;   /* inode size, bytes */
        uint16_t        sb_inopblock;   /* inodes per block */
-       char            sb_fname[12];   /* file system name */
+       char            sb_fname[XFSLABEL_MAX]; /* file system name */
        uint8_t         sb_blocklog;    /* log2 of sb_blocksize */
        uint8_t         sb_sectlog;     /* log2 of sb_sectsize */
        uint8_t         sb_inodelog;    /* log2 of sb_inodesize */
@@ -213,7 +216,7 @@ typedef struct xfs_dsb {
        __be16          sb_sectsize;    /* volume sector size, bytes */
        __be16          sb_inodesize;   /* inode size, bytes */
        __be16          sb_inopblock;   /* inodes per block */
-       char            sb_fname[12];   /* file system name */
+       char            sb_fname[XFSLABEL_MAX]; /* file system name */
        __u8            sb_blocklog;    /* log2 of sb_blocksize */
        __u8            sb_sectlog;     /* log2 of sb_sectsize */
        __u8            sb_inodelog;    /* log2 of sb_inodesize */
index 2113b0b39e4f36c48324436a6736d16f74415692..acb34f88f43fbd6dcc045c3d611ae5bdc342aa7a 100644 (file)
@@ -943,6 +943,38 @@ xfs_update_secondary_sbs(
        return saved_error ? saved_error : error;
 }
 
+/*
+ * Same behavior as xfs_sync_sb, except that it is always synchronous and it
+ * also writes the superblock buffer to disk sector 0 immediately.
+ */
+int
+xfs_sync_sb_buf(
+       struct xfs_mount        *mp)
+{
+       struct xfs_trans        *tp;
+       struct xfs_buf          *bp;
+       int                     error;
+
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
+       if (error)
+               return error;
+
+       bp = xfs_trans_getsb(tp, mp, 0);
+       xfs_log_sb(tp);
+       xfs_trans_bhold(tp, bp);
+       xfs_trans_set_sync(tp);
+       error = xfs_trans_commit(tp);
+       if (error)
+               goto out;
+       /*
+        * write out the sb buffer to get the changes to disk
+        */
+       error = xfs_bwrite(bp);
+out:
+       xfs_buf_relse(bp);
+       return error;
+}
+
 int
 xfs_fs_geometry(
        struct xfs_sb           *sbp,
index fc65d4e1433a7f450a16c4aecf469cc3dc34d911..03e0cc6bf3a6395a88d354f71c4190e21edc1eb4 100644 (file)
@@ -36,6 +36,7 @@ extern int    xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t);
 
 extern void    xfs_log_sb(struct xfs_trans *tp);
 extern int     xfs_sync_sb(struct xfs_mount *mp, bool wait);
+extern int     xfs_sync_sb_buf(struct xfs_mount *mp);
 extern void    xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
 extern void    xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
 extern void    xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);