root/fs/xfs/xfs_pnfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xfs_break_leased_layouts
  2. xfs_fs_get_uuid
  3. xfs_fs_map_blocks
  4. xfs_pnfs_validate_isize
  5. xfs_fs_commit_blocks

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2014 Christoph Hellwig.
   4  */
   5 #include "xfs.h"
   6 #include "xfs_shared.h"
   7 #include "xfs_format.h"
   8 #include "xfs_log_format.h"
   9 #include "xfs_trans_resv.h"
  10 #include "xfs_mount.h"
  11 #include "xfs_inode.h"
  12 #include "xfs_trans.h"
  13 #include "xfs_bmap.h"
  14 #include "xfs_iomap.h"
  15 
  16 /*
  17  * Ensure that we do not have any outstanding pNFS layouts that can be used by
  18  * clients to directly read from or write to this inode.  This must be called
  19  * before every operation that can remove blocks from the extent map.
  20  * Additionally we call it during the write operation, where aren't concerned
  21  * about exposing unallocated blocks but just want to provide basic
  22  * synchronization between a local writer and pNFS clients.  mmap writes would
  23  * also benefit from this sort of synchronization, but due to the tricky locking
  24  * rules in the page fault path we don't bother.
  25  */
  26 int
  27 xfs_break_leased_layouts(
  28         struct inode            *inode,
  29         uint                    *iolock,
  30         bool                    *did_unlock)
  31 {
  32         struct xfs_inode        *ip = XFS_I(inode);
  33         int                     error;
  34 
  35         while ((error = break_layout(inode, false)) == -EWOULDBLOCK) {
  36                 xfs_iunlock(ip, *iolock);
  37                 *did_unlock = true;
  38                 error = break_layout(inode, true);
  39                 *iolock &= ~XFS_IOLOCK_SHARED;
  40                 *iolock |= XFS_IOLOCK_EXCL;
  41                 xfs_ilock(ip, *iolock);
  42         }
  43 
  44         return error;
  45 }
  46 
  47 /*
  48  * Get a unique ID including its location so that the client can identify
  49  * the exported device.
  50  */
  51 int
  52 xfs_fs_get_uuid(
  53         struct super_block      *sb,
  54         u8                      *buf,
  55         u32                     *len,
  56         u64                     *offset)
  57 {
  58         struct xfs_mount        *mp = XFS_M(sb);
  59 
  60         printk_once(KERN_NOTICE
  61 "XFS (%s): using experimental pNFS feature, use at your own risk!\n",
  62                 mp->m_fsname);
  63 
  64         if (*len < sizeof(uuid_t))
  65                 return -EINVAL;
  66 
  67         memcpy(buf, &mp->m_sb.sb_uuid, sizeof(uuid_t));
  68         *len = sizeof(uuid_t);
  69         *offset = offsetof(struct xfs_dsb, sb_uuid);
  70         return 0;
  71 }
  72 
  73 /*
  74  * Get a layout for the pNFS client.
  75  */
  76 int
  77 xfs_fs_map_blocks(
  78         struct inode            *inode,
  79         loff_t                  offset,
  80         u64                     length,
  81         struct iomap            *iomap,
  82         bool                    write,
  83         u32                     *device_generation)
  84 {
  85         struct xfs_inode        *ip = XFS_I(inode);
  86         struct xfs_mount        *mp = ip->i_mount;
  87         struct xfs_bmbt_irec    imap;
  88         xfs_fileoff_t           offset_fsb, end_fsb;
  89         loff_t                  limit;
  90         int                     bmapi_flags = XFS_BMAPI_ENTIRE;
  91         int                     nimaps = 1;
  92         uint                    lock_flags;
  93         int                     error = 0;
  94 
  95         if (XFS_FORCED_SHUTDOWN(mp))
  96                 return -EIO;
  97 
  98         /*
  99          * We can't export inodes residing on the realtime device.  The realtime
 100          * device doesn't have a UUID to identify it, so the client has no way
 101          * to find it.
 102          */
 103         if (XFS_IS_REALTIME_INODE(ip))
 104                 return -ENXIO;
 105 
 106         /*
 107          * The pNFS block layout spec actually supports reflink like
 108          * functionality, but the Linux pNFS server doesn't implement it yet.
 109          */
 110         if (xfs_is_reflink_inode(ip))
 111                 return -ENXIO;
 112 
 113         /*
 114          * Lock out any other I/O before we flush and invalidate the pagecache,
 115          * and then hand out a layout to the remote system.  This is very
 116          * similar to direct I/O, except that the synchronization is much more
 117          * complicated.  See the comment near xfs_break_leased_layouts
 118          * for a detailed explanation.
 119          */
 120         xfs_ilock(ip, XFS_IOLOCK_EXCL);
 121 
 122         error = -EINVAL;
 123         limit = mp->m_super->s_maxbytes;
 124         if (!write)
 125                 limit = max(limit, round_up(i_size_read(inode),
 126                                      inode->i_sb->s_blocksize));
 127         if (offset > limit)
 128                 goto out_unlock;
 129         if (offset > limit - length)
 130                 length = limit - offset;
 131 
 132         error = filemap_write_and_wait(inode->i_mapping);
 133         if (error)
 134                 goto out_unlock;
 135         error = invalidate_inode_pages2(inode->i_mapping);
 136         if (WARN_ON_ONCE(error))
 137                 return error;
 138 
 139         end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + length);
 140         offset_fsb = XFS_B_TO_FSBT(mp, offset);
 141 
 142         lock_flags = xfs_ilock_data_map_shared(ip);
 143         error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
 144                                 &imap, &nimaps, bmapi_flags);
 145         xfs_iunlock(ip, lock_flags);
 146 
 147         if (error)
 148                 goto out_unlock;
 149 
 150         if (write) {
 151                 enum xfs_prealloc_flags flags = 0;
 152 
 153                 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
 154 
 155                 if (!nimaps || imap.br_startblock == HOLESTARTBLOCK) {
 156                         /*
 157                          * xfs_iomap_write_direct() expects to take ownership of
 158                          * the shared ilock.
 159                          */
 160                         xfs_ilock(ip, XFS_ILOCK_SHARED);
 161                         error = xfs_iomap_write_direct(ip, offset, length,
 162                                                        &imap, nimaps);
 163                         if (error)
 164                                 goto out_unlock;
 165 
 166                         /*
 167                          * Ensure the next transaction is committed
 168                          * synchronously so that the blocks allocated and
 169                          * handed out to the client are guaranteed to be
 170                          * present even after a server crash.
 171                          */
 172                         flags |= XFS_PREALLOC_SET | XFS_PREALLOC_SYNC;
 173                 }
 174 
 175                 error = xfs_update_prealloc_flags(ip, flags);
 176                 if (error)
 177                         goto out_unlock;
 178         }
 179         xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 180 
 181         error = xfs_bmbt_to_iomap(ip, iomap, &imap, false);
 182         *device_generation = mp->m_generation;
 183         return error;
 184 out_unlock:
 185         xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 186         return error;
 187 }
 188 
 189 /*
 190  * Ensure the size update falls into a valid allocated block.
 191  */
 192 static int
 193 xfs_pnfs_validate_isize(
 194         struct xfs_inode        *ip,
 195         xfs_off_t               isize)
 196 {
 197         struct xfs_bmbt_irec    imap;
 198         int                     nimaps = 1;
 199         int                     error = 0;
 200 
 201         xfs_ilock(ip, XFS_ILOCK_SHARED);
 202         error = xfs_bmapi_read(ip, XFS_B_TO_FSBT(ip->i_mount, isize - 1), 1,
 203                                 &imap, &nimaps, 0);
 204         xfs_iunlock(ip, XFS_ILOCK_SHARED);
 205         if (error)
 206                 return error;
 207 
 208         if (imap.br_startblock == HOLESTARTBLOCK ||
 209             imap.br_startblock == DELAYSTARTBLOCK ||
 210             imap.br_state == XFS_EXT_UNWRITTEN)
 211                 return -EIO;
 212         return 0;
 213 }
 214 
 215 /*
 216  * Make sure the blocks described by maps are stable on disk.  This includes
 217  * converting any unwritten extents, flushing the disk cache and updating the
 218  * time stamps.
 219  *
 220  * Note that we rely on the caller to always send us a timestamp update so that
 221  * we always commit a transaction here.  If that stops being true we will have
 222  * to manually flush the cache here similar to what the fsync code path does
 223  * for datasyncs on files that have no dirty metadata.
 224  */
 225 int
 226 xfs_fs_commit_blocks(
 227         struct inode            *inode,
 228         struct iomap            *maps,
 229         int                     nr_maps,
 230         struct iattr            *iattr)
 231 {
 232         struct xfs_inode        *ip = XFS_I(inode);
 233         struct xfs_mount        *mp = ip->i_mount;
 234         struct xfs_trans        *tp;
 235         bool                    update_isize = false;
 236         int                     error, i;
 237         loff_t                  size;
 238 
 239         ASSERT(iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME));
 240 
 241         xfs_ilock(ip, XFS_IOLOCK_EXCL);
 242 
 243         size = i_size_read(inode);
 244         if ((iattr->ia_valid & ATTR_SIZE) && iattr->ia_size > size) {
 245                 update_isize = true;
 246                 size = iattr->ia_size;
 247         }
 248 
 249         for (i = 0; i < nr_maps; i++) {
 250                 u64 start, length, end;
 251 
 252                 start = maps[i].offset;
 253                 if (start > size)
 254                         continue;
 255 
 256                 end = start + maps[i].length;
 257                 if (end > size)
 258                         end = size;
 259 
 260                 length = end - start;
 261                 if (!length)
 262                         continue;
 263         
 264                 /*
 265                  * Make sure reads through the pagecache see the new data.
 266                  */
 267                 error = invalidate_inode_pages2_range(inode->i_mapping,
 268                                         start >> PAGE_SHIFT,
 269                                         (end - 1) >> PAGE_SHIFT);
 270                 WARN_ON_ONCE(error);
 271 
 272                 error = xfs_iomap_write_unwritten(ip, start, length, false);
 273                 if (error)
 274                         goto out_drop_iolock;
 275         }
 276 
 277         if (update_isize) {
 278                 error = xfs_pnfs_validate_isize(ip, size);
 279                 if (error)
 280                         goto out_drop_iolock;
 281         }
 282 
 283         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
 284         if (error)
 285                 goto out_drop_iolock;
 286 
 287         xfs_ilock(ip, XFS_ILOCK_EXCL);
 288         xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 289         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 290 
 291         xfs_setattr_time(ip, iattr);
 292         if (update_isize) {
 293                 i_size_write(inode, iattr->ia_size);
 294                 ip->i_d.di_size = iattr->ia_size;
 295         }
 296 
 297         xfs_trans_set_sync(tp);
 298         error = xfs_trans_commit(tp);
 299 
 300 out_drop_iolock:
 301         xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 302         return error;
 303 }

/* [<][>][^][v][top][bottom][index][help] */