Skip to content

Commit

Permalink
Merge branch 'hpfs-patches' (patches from Mikulas Patocka)
Browse files Browse the repository at this point in the history
Merge hpfs updates from Mikulas Patocka.

Mainly fstrim support, with some minor other cleanups.

These were actually sent during the merge window, but I wanted to wait
for the FSTRIM compat handling cleanup before applying them.  Mikulas
sent that earlier today.

* emailed patches from Mikulas Patocka <mikulas@twibright.com>:
  hpfs: hpfs_error: Remove static buffer, use vsprintf extension %pV instead
  hpfs: kstrdup() out of memory handling
  hpfs: Remove unessary cast
  hpfs: add fstrim support
  • Loading branch information
Linus Torvalds committed Jul 9, 2015
2 parents 4c0a9f7 + a28e4b2 commit c4b5fd3
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 7 deletions.
95 changes: 95 additions & 0 deletions fs/hpfs/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,98 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a
a->btree.first_free = cpu_to_le16(8);
return a;
}

static unsigned find_run(__le32 *bmp, unsigned *idx)
{
unsigned len;
while (tstbits(bmp, *idx, 1)) {
(*idx)++;
if (unlikely(*idx >= 0x4000))
return 0;
}
len = 1;
while (!tstbits(bmp, *idx + len, 1))
len++;
return len;
}

static int do_trim(struct super_block *s, secno start, unsigned len, secno limit_start, secno limit_end, unsigned minlen, unsigned *result)
{
int err;
secno end;
if (fatal_signal_pending(current))
return -EINTR;
end = start + len;
if (start < limit_start)
start = limit_start;
if (end > limit_end)
end = limit_end;
if (start >= end)
return 0;
if (end - start < minlen)
return 0;
err = sb_issue_discard(s, start, end - start, GFP_NOFS, 0);
if (err)
return err;
*result += end - start;
return 0;
}

int hpfs_trim_fs(struct super_block *s, u64 start, u64 end, u64 minlen, unsigned *result)
{
int err = 0;
struct hpfs_sb_info *sbi = hpfs_sb(s);
unsigned idx, len, start_bmp, end_bmp;
__le32 *bmp;
struct quad_buffer_head qbh;

*result = 0;
if (!end || end > sbi->sb_fs_size)
end = sbi->sb_fs_size;
if (start >= sbi->sb_fs_size)
return 0;
if (minlen > 0x4000)
return 0;
if (start < sbi->sb_dirband_start + sbi->sb_dirband_size && end > sbi->sb_dirband_start) {
hpfs_lock(s);
if (s->s_flags & MS_RDONLY) {
err = -EROFS;
goto unlock_1;
}
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
err = -EIO;
goto unlock_1;
}
idx = 0;
while ((len = find_run(bmp, &idx)) && !err) {
err = do_trim(s, sbi->sb_dirband_start + idx * 4, len * 4, start, end, minlen, result);
idx += len;
}
hpfs_brelse4(&qbh);
unlock_1:
hpfs_unlock(s);
}
start_bmp = start >> 14;
end_bmp = (end + 0x3fff) >> 14;
while (start_bmp < end_bmp && !err) {
hpfs_lock(s);
if (s->s_flags & MS_RDONLY) {
err = -EROFS;
goto unlock_2;
}
if (!(bmp = hpfs_map_bitmap(s, start_bmp, &qbh, "trim"))) {
err = -EIO;
goto unlock_2;
}
idx = 0;
while ((len = find_run(bmp, &idx)) && !err) {
err = do_trim(s, (start_bmp << 14) + idx, len, start, end, minlen, result);
idx += len;
}
hpfs_brelse4(&qbh);
unlock_2:
hpfs_unlock(s);
start_bmp++;
}
return err;
}
1 change: 1 addition & 0 deletions fs/hpfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,5 @@ const struct file_operations hpfs_dir_ops =
.iterate = hpfs_readdir,
.release = hpfs_dir_release,
.fsync = hpfs_file_fsync,
.unlocked_ioctl = hpfs_ioctl,
};
1 change: 1 addition & 0 deletions fs/hpfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ const struct file_operations hpfs_file_ops =
.release = hpfs_file_release,
.fsync = hpfs_file_fsync,
.splice_read = generic_file_splice_read,
.unlocked_ioctl = hpfs_ioctl,
};

const struct inode_operations hpfs_file_iops =
Expand Down
4 changes: 4 additions & 0 deletions fs/hpfs/hpfs_fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/blkdev.h>
#include <asm/unaligned.h>

#include "hpfs.h"
Expand Down Expand Up @@ -200,6 +202,7 @@ void hpfs_free_dnode(struct super_block *, secno);
struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *);
struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **);
struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **);
int hpfs_trim_fs(struct super_block *, u64, u64, u64, unsigned *);

/* anode.c */

Expand Down Expand Up @@ -318,6 +321,7 @@ __printf(2, 3)
void hpfs_error(struct super_block *, const char *, ...);
int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
unsigned hpfs_get_free_dnodes(struct super_block *);
long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg);

/*
* local time (HPFS) to GMT (Unix)
Expand Down
47 changes: 40 additions & 7 deletions fs/hpfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ static void unmark_dirty(struct super_block *s)
}

/* Filesystem error... */
static char err_buf[1024];

void hpfs_error(struct super_block *s, const char *fmt, ...)
{
struct va_format vaf;
va_list args;

va_start(args, fmt);
vsnprintf(err_buf, sizeof(err_buf), fmt, args);

vaf.fmt = fmt;
vaf.va = &args;

pr_err("filesystem error: %pV", &vaf);

va_end(args);

pr_err("filesystem error: %s", err_buf);
if (!hpfs_sb(s)->sb_was_error) {
if (hpfs_sb(s)->sb_err == 2) {
pr_cont("; crashing the system because you wanted it\n");
Expand Down Expand Up @@ -196,12 +199,39 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0;
}


long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
switch (cmd) {
case FITRIM: {
struct fstrim_range range;
secno n_trimmed;
int r;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
return -EFAULT;
r = hpfs_trim_fs(file_inode(file)->i_sb, range.start >> 9, (range.start + range.len) >> 9, (range.minlen + 511) >> 9, &n_trimmed);
if (r)
return r;
range.len = (u64)n_trimmed << 9;
if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range)))
return -EFAULT;
return 0;
}
default: {
return -ENOIOCTLCMD;
}
}
}


static struct kmem_cache * hpfs_inode_cachep;

static struct inode *hpfs_alloc_inode(struct super_block *sb)
{
struct hpfs_inode_info *ei;
ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
ei = kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);
if (!ei)
return NULL;
ei->vfs_inode.i_version = 1;
Expand Down Expand Up @@ -424,11 +454,14 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
int o;
struct hpfs_sb_info *sbi = hpfs_sb(s);
char *new_opts = kstrdup(data, GFP_KERNEL);


if (!new_opts)
return -ENOMEM;

sync_filesystem(s);

*flags |= MS_NOATIME;

hpfs_lock(s);
uid = sbi->sb_uid; gid = sbi->sb_gid;
umask = 0777 & ~sbi->sb_mode;
Expand Down

0 comments on commit c4b5fd3

Please sign in to comment.