TRIM Patch

Link to this paste: http://bugs.dragonflybsd.org/pastes/419

Added by almost 2 years ago.
Syntax: Diff

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
atg-s-optimus /export_fs/DragonFlyBSD/
$ git show 
commit 410618f1f07446cef84f23b3a7aa66d676d9f37f
Author: Tim Bisson <bissont@mac.com>
Date:   Fri Oct 12 09:14:18 2012 -0700

    Fix TRIM:
    * Only enable TRIM if DRAT (Deterministic Read After TRIM) is supported
    * if trim is on as a option, display that when typing "mount"
    * make sure TRIM occurs with UFS when it is enabled. using
      ip->i_devvp->v_mount->mnt_flag doesn't have mount options.
    ** when softupdates is enabled, struct freeblocks doesn't pass the vnode
       to to the temporary inode pointer. Adding vnode to freeblocks so we
       can get the mountp that has the TRIM flag enabled.
    * change post trim ffs_blkfree_cg() to use taskqueue_swi_mp and get mp
      token when modifying freemapw

diff --git a/sys/dev/disk/ahci/ahci_cam.c b/sys/dev/disk/ahci/ahci_cam.c
index 3b5d857..f0a41fa 100644
--- a/sys/dev/disk/ahci/ahci_cam.c
+++ b/sys/dev/disk/ahci/ahci_cam.c
@@ -1095,7 +1095,8 @@ ahci_xpt_scsi_disk_io(struct ahci_port *ap, struct ata_port *atx,
                 */
                if (at->at_identify.support_dsm) {
                        rdata->inquiry_data.vendor_specific1[0] =
-                           at->at_identify.support_dsm &ATA_SUPPORT_DSM_TRIM;
+                           (at->at_identify.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
+                           (at->at_identify.support3 & ATA_SUPPORT_DRAT);
                        rdata->inquiry_data.vendor_specific1[1] = 
                            at->at_identify.max_dsm_blocks;
                }
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index e6a0024..a3b2035 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1835,6 +1835,7 @@ vfs_flagstostr(int flags, const struct mountctl_opt *optp,
                { MNT_SUIDDIR,          "suiddir" },
                { MNT_SOFTDEP,          "soft-updates" },
                { MNT_IGNORE,           "ignore" },
+               { MNT_TRIM,             "trim" },
                { 0,                    NULL}
        };
        int bwritten;
diff --git a/sys/vfs/ufs/ffs_alloc.c b/sys/vfs/ufs/ffs_alloc.c
index afcde72..9a26f1a 100644
--- a/sys/vfs/ufs/ffs_alloc.c
+++ b/sys/vfs/ufs/ffs_alloc.c
@@ -1627,8 +1627,10 @@ ffs_blkfree_trim_task(void *ctx, int pending)
        struct ffs_blkfree_trim_params *tp;
 
        tp = ctx;
+       lwkt_gettoken(&tp->i_devvp->v_mount->mnt_token);
        ffs_blkfree_cg(tp->i_fs, tp->i_devvp, tp->i_dev, tp->i_number,
            tp->i_din_uid, tp->bno, tp->size);
+       lwkt_reltoken(&tp->i_devvp->v_mount->mnt_token);
        kfree(tp, M_TEMP);
 }
 
@@ -1643,7 +1645,7 @@ ffs_blkfree_trim_completed(struct bio *biop)
        tp = bp->b_bio1.bio_caller_info1.ptr;
        TASK_INIT(&tp->task, 0, ffs_blkfree_trim_task, tp);
        tp = biop->bio_caller_info1.ptr;
-       taskqueue_enqueue(taskqueue_swi, &tp->task);
+       taskqueue_enqueue(taskqueue_swi_mp, &tp->task);
        biodone(biop);
 }
 
@@ -1658,7 +1660,7 @@ ffs_blkfree_trim_completed(struct bio *biop)
 void
 ffs_blkfree(struct inode *ip, ufs_daddr_t bno, long size) 
 {
-       struct mount *mp = ip->i_devvp->v_mount;
+       struct mount *mp = ip->i_vnode->v_mount;
        struct ffs_blkfree_trim_params *tp;
 
        if (!(mp->mnt_flag & MNT_TRIM)) {
diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c
index b6a8cbf..9f0a3a6 100644
--- a/sys/vfs/ufs/ffs_softdep.c
+++ b/sys/vfs/ufs/ffs_softdep.c
@@ -1740,6 +1740,7 @@ softdep_setup_freeblocks(struct inode *ip, off_t length)
        freeblks->fb_uid = ip->i_uid;
        freeblks->fb_previousinum = ip->i_number;
        freeblks->fb_devvp = ip->i_devvp;
+       freeblks->fb_vp = ITOV(ip);
        freeblks->fb_fs = fs;
        freeblks->fb_oldsize = ip->i_size;
        freeblks->fb_newsize = length;
@@ -2130,6 +2131,7 @@ handle_workitem_freeblocks(struct freeblks *freeblks)
        ufs_lbn_t baselbns[NIADDR], tmpval;
 
        tip.i_number = freeblks->fb_previousinum;
+       tip.i_vnode = freeblks->fb_vp;
        tip.i_devvp = freeblks->fb_devvp;
        tip.i_dev = freeblks->fb_devvp->v_rdev;
        tip.i_fs = freeblks->fb_fs;
diff --git a/sys/vfs/ufs/softdep.h b/sys/vfs/ufs/softdep.h
index c99396a..80a5d2a 100644
--- a/sys/vfs/ufs/softdep.h
+++ b/sys/vfs/ufs/softdep.h
@@ -401,6 +401,7 @@ struct freeblks {
        ino_t   fb_previousinum;        /* inode of previous owner of blocks */
        struct  vnode *fb_devvp;        /* filesystem device vnode */
        struct  fs *fb_fs;              /* addr of superblock */
+       struct  vnode *fb_vp;           /* vnodeip*/
        off_t   fb_oldsize;             /* previous file size */
        off_t   fb_newsize;             /* new file size */
        int     fb_chkcnt;              /* used to check cnt of blks released */

Download