)]}'
{
  "commit": "2be63d5ce929603d4e7cedabd9e992eb34a0ff95",
  "tree": "2d3077ab32bed985cc35beb05ae4bddc90ddc1d9",
  "parents": [
    "1ec9a1ae1e30c733077c0b288c4301b66b7a81f2"
  ],
  "author": {
    "name": "Filipe Manana",
    "email": "fdmanana@suse.com",
    "time": "Fri Feb 12 11:34:23 2016 +0000"
  },
  "committer": {
    "name": "Chris Mason",
    "email": "clm@fb.com",
    "time": "Tue Mar 01 08:23:29 2016 -0800"
  },
  "message": "Btrfs: fix file loss on log replay after renaming a file and fsync\n\nWe have two cases where we end up deleting a file at log replay time\nwhen we should not. For this to happen the file must have been renamed\nand a directory inode must have been fsynced/logged.\n\nTwo examples that exercise these two cases are listed below.\n\n  Case 1)\n\n  $ mkfs.btrfs -f /dev/sdb\n  $ mount /dev/sdb /mnt\n  $ mkdir -p /mnt/a/b\n  $ mkdir /mnt/c\n  $ touch /mnt/a/b/foo\n  $ sync\n  $ mv /mnt/a/b/foo /mnt/c/\n  # Create file bar just to make sure the fsync on directory a/ does\n  # something and it\u0027s not a no-op.\n  $ touch /mnt/a/bar\n  $ xfs_io -c \"fsync\" /mnt/a\n  \u003c power fail / crash \u003e\n\n  The next time the filesystem is mounted, the log replay procedure\n  deletes file foo.\n\n  Case 2)\n\n  $ mkfs.btrfs -f /dev/sdb\n  $ mount /dev/sdb /mnt\n  $ mkdir /mnt/a\n  $ mkdir /mnt/b\n  $ mkdir /mnt/c\n  $ touch /mnt/a/foo\n  $ ln /mnt/a/foo /mnt/b/foo_link\n  $ touch /mnt/b/bar\n  $ sync\n  $ unlink /mnt/b/foo_link\n  $ mv /mnt/b/bar /mnt/c/\n  $ xfs_io -c \"fsync\" /mnt/a/foo\n  \u003c power fail / crash \u003e\n\n  The next time the filesystem is mounted, the log replay procedure\n  deletes file bar.\n\nThe reason why the files are deleted is because when we log inodes\nother then the fsync target inode, we ignore their last_unlink_trans\nvalue and leave the log without enough information to later replay the\nrename operations. So we need to look at the last_unlink_trans values\nand fallback to a transaction commit if they are greater than the\nid of the last committed transaction.\n\nSo fix this by looking at the last_unlink_trans values and fallback to\ntransaction commits when needed. Also, when logging other inodes (for\ncase 1 we logged descendants of the fsync target inode while for case 2\nwe logged ascendants) we need to care about concurrent tasks updating\nthe last_unlink_trans of inodes we are logging (which was already an\nexisting problem in check_parent_dirs_for_sync()). Since we can not\nacquire their inode mutex (vfs\u0027 struct inode -\u003ei_mutex), as that causes\ndeadlocks with other concurrent operations that acquire the i_mutex of\n2 inodes (other fsyncs or renames for example), we need to serialize on\nthe log_mutex of the inode we are logging. A task setting a new value for\nan inode\u0027s last_unlink_trans must acquire the inode\u0027s log_mutex and it\nmust do this update before doing the actual unlink operation (which is\nalready the case except when deleting a snapshot). Conversely the task\nlogging the inode must first log the inode and then check the inode\u0027s\nlast_unlink_trans value while holding its log_mutex, as if its value is\nnot greater then the id of the last committed transaction it means it\nlogged a safe state of the inode\u0027s items, while if its value is not\nsmaller then the id of the last committed transaction it means the inode\nstate it has logged might not be safe (the concurrent task might have\njust updated last_unlink_trans but hasn\u0027t done yet the unlink operation)\nand therefore a transaction commit must be done.\n\nTest cases for xfstests follow in separate patches.\n\nSigned-off-by: Filipe Manana \u003cfdmanana@suse.com\u003e\nSigned-off-by: Chris Mason \u003cclm@fb.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "ccb30ca9ebb26ac18326481648c0270e646655c7",
      "old_mode": 33188,
      "old_path": "fs/btrfs/ioctl.c",
      "new_id": "0af5ecbda9a3c7211939c6df1c3955eaee220920",
      "new_mode": 33188,
      "new_path": "fs/btrfs/ioctl.c"
    },
    {
      "type": "modify",
      "old_id": "43c6781af6549a8a8e4708b2c29691db7551f652",
      "old_mode": 33188,
      "old_path": "fs/btrfs/tree-log.c",
      "new_id": "9f6372dd0eabd5b6f396673527b546c4888d87cc",
      "new_mode": 33188,
      "new_path": "fs/btrfs/tree-log.c"
    }
  ]
}
