Commit 70fcf5c3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull UDF fixes and cleanups from Jan Kara:
 "Several small UDF fixes and cleanups and a small cleanup of fanotify
  code"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fanotify: simplify the code of fanotify_merge
  udf: simplify udf_ioctl()
  udf: fix ioctl errors
  udf: allow implicit blocksize specification during mount
  udf: check partition reference in udf_read_inode()
  udf: atomically read inode size
  udf: merge module informations in super.c
  udf: remove next_epos from udf_update_extent_cache()
  udf: Factor out trimming of crtime
  udf: remove empty condition
  udf: remove unneeded line break
  udf: merge bh free
  udf: use pointer for kernel_long_ad argument
  udf: use __packed instead of __attribute__ ((packed))
  udf: Make stat on symlink report symlink length as st_size
  fs/udf: make #ifdef UDF_PREALLOCATE unconditional
  fs: udf: Replace CURRENT_TIME with current_time()
parents 2bfe01ef 6c71100d
...@@ -31,7 +31,6 @@ static bool should_merge(struct fsnotify_event *old_fsn, ...@@ -31,7 +31,6 @@ static bool should_merge(struct fsnotify_event *old_fsn,
static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
{ {
struct fsnotify_event *test_event; struct fsnotify_event *test_event;
bool do_merge = false;
pr_debug("%s: list=%p event=%p\n", __func__, list, event); pr_debug("%s: list=%p event=%p\n", __func__, list, event);
...@@ -47,16 +46,12 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) ...@@ -47,16 +46,12 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
list_for_each_entry_reverse(test_event, list, list) { list_for_each_entry_reverse(test_event, list, list) {
if (should_merge(test_event, event)) { if (should_merge(test_event, event)) {
do_merge = true; test_event->mask |= event->mask;
break; return 1;
} }
} }
if (!do_merge)
return 0; return 0;
test_event->mask |= event->mask;
return 1;
} }
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
......
This diff is collapsed.
...@@ -176,54 +176,46 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -176,54 +176,46 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ {
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
long old_block, new_block; long old_block, new_block;
int result = -EINVAL; int result;
if (inode_permission(inode, MAY_READ) != 0) { if (inode_permission(inode, MAY_READ) != 0) {
udf_debug("no permission to access inode %lu\n", inode->i_ino); udf_debug("no permission to access inode %lu\n", inode->i_ino);
result = -EPERM; return -EPERM;
goto out;
} }
if (!arg) { if (!arg && ((cmd == UDF_GETVOLIDENT) || (cmd == UDF_GETEASIZE) ||
(cmd == UDF_RELOCATE_BLOCKS) || (cmd == UDF_GETEABLOCK))) {
udf_debug("invalid argument to udf_ioctl\n"); udf_debug("invalid argument to udf_ioctl\n");
result = -EINVAL; return -EINVAL;
goto out;
} }
switch (cmd) { switch (cmd) {
case UDF_GETVOLIDENT: case UDF_GETVOLIDENT:
if (copy_to_user((char __user *)arg, if (copy_to_user((char __user *)arg,
UDF_SB(inode->i_sb)->s_volume_ident, 32)) UDF_SB(inode->i_sb)->s_volume_ident, 32))
result = -EFAULT; return -EFAULT;
else return 0;
result = 0;
goto out;
case UDF_RELOCATE_BLOCKS: case UDF_RELOCATE_BLOCKS:
if (!capable(CAP_SYS_ADMIN)) { if (!capable(CAP_SYS_ADMIN))
result = -EPERM; return -EPERM;
goto out; if (get_user(old_block, (long __user *)arg))
} return -EFAULT;
if (get_user(old_block, (long __user *)arg)) {
result = -EFAULT;
goto out;
}
result = udf_relocate_blocks(inode->i_sb, result = udf_relocate_blocks(inode->i_sb,
old_block, &new_block); old_block, &new_block);
if (result == 0) if (result == 0)
result = put_user(new_block, (long __user *)arg); result = put_user(new_block, (long __user *)arg);
goto out; return result;
case UDF_GETEASIZE: case UDF_GETEASIZE:
result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); return put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg);
goto out;
case UDF_GETEABLOCK: case UDF_GETEABLOCK:
result = copy_to_user((char __user *)arg, return copy_to_user((char __user *)arg,
UDF_I(inode)->i_ext.i_data, UDF_I(inode)->i_ext.i_data,
UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0;
goto out; default:
return -ENOIOCTLCMD;
} }
out: return 0;
return result;
} }
static int udf_release_file(struct inode *inode, struct file *filp) static int udf_release_file(struct inode *inode, struct file *filp)
......
...@@ -43,10 +43,6 @@ ...@@ -43,10 +43,6 @@
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.h" #include "udf_sb.h"
MODULE_AUTHOR("Ben Fennema");
MODULE_DESCRIPTION("Universal Disk Format Filesystem");
MODULE_LICENSE("GPL");
#define EXTENT_MERGE_SIZE 5 #define EXTENT_MERGE_SIZE 5
static umode_t udf_convert_permissions(struct fileEntry *); static umode_t udf_convert_permissions(struct fileEntry *);
...@@ -57,14 +53,12 @@ static sector_t inode_getblk(struct inode *, sector_t, int *, int *); ...@@ -57,14 +53,12 @@ static sector_t inode_getblk(struct inode *, sector_t, int *, int *);
static int8_t udf_insert_aext(struct inode *, struct extent_position, static int8_t udf_insert_aext(struct inode *, struct extent_position,
struct kernel_lb_addr, uint32_t); struct kernel_lb_addr, uint32_t);
static void udf_split_extents(struct inode *, int *, int, int, static void udf_split_extents(struct inode *, int *, int, int,
struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); struct kernel_long_ad *, int *);
static void udf_prealloc_extents(struct inode *, int, int, static void udf_prealloc_extents(struct inode *, int, int,
struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); struct kernel_long_ad *, int *);
static void udf_merge_extents(struct inode *, static void udf_merge_extents(struct inode *, struct kernel_long_ad *, int *);
struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); static void udf_update_extents(struct inode *, struct kernel_long_ad *, int,
static void udf_update_extents(struct inode *, int, struct extent_position *);
struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int,
struct extent_position *);
static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
static void __udf_clear_extent_cache(struct inode *inode) static void __udf_clear_extent_cache(struct inode *inode)
...@@ -111,7 +105,7 @@ static int udf_read_extent_cache(struct inode *inode, loff_t bcount, ...@@ -111,7 +105,7 @@ static int udf_read_extent_cache(struct inode *inode, loff_t bcount,
/* Add extent to extent cache */ /* Add extent to extent cache */
static void udf_update_extent_cache(struct inode *inode, loff_t estart, static void udf_update_extent_cache(struct inode *inode, loff_t estart,
struct extent_position *pos, int next_epos) struct extent_position *pos)
{ {
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
...@@ -120,18 +114,15 @@ static void udf_update_extent_cache(struct inode *inode, loff_t estart, ...@@ -120,18 +114,15 @@ static void udf_update_extent_cache(struct inode *inode, loff_t estart,
__udf_clear_extent_cache(inode); __udf_clear_extent_cache(inode);
if (pos->bh) if (pos->bh)
get_bh(pos->bh); get_bh(pos->bh);
memcpy(&iinfo->cached_extent.epos, pos, memcpy(&iinfo->cached_extent.epos, pos, sizeof(struct extent_position));
sizeof(struct extent_position));
iinfo->cached_extent.lstart = estart; iinfo->cached_extent.lstart = estart;
if (next_epos)
switch (iinfo->i_alloc_type) { switch (iinfo->i_alloc_type) {
case ICBTAG_FLAG_AD_SHORT: case ICBTAG_FLAG_AD_SHORT:
iinfo->cached_extent.epos.offset -= iinfo->cached_extent.epos.offset -= sizeof(struct short_ad);
sizeof(struct short_ad);
break; break;
case ICBTAG_FLAG_AD_LONG: case ICBTAG_FLAG_AD_LONG:
iinfo->cached_extent.epos.offset -= iinfo->cached_extent.epos.offset -= sizeof(struct long_ad);
sizeof(struct long_ad); break;
} }
spin_unlock(&iinfo->i_extent_cache_lock); spin_unlock(&iinfo->i_extent_cache_lock);
} }
...@@ -747,11 +738,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -747,11 +738,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
~(inode->i_sb->s_blocksize - 1)); ~(inode->i_sb->s_blocksize - 1));
udf_write_aext(inode, &cur_epos, &eloc, elen, 1); udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
} }
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset);
return newblock; goto out_free;
} }
/* Are we beyond EOF? */ /* Are we beyond EOF? */
...@@ -774,11 +762,9 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -774,11 +762,9 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
/* Create extents for the hole between EOF and offset */ /* Create extents for the hole between EOF and offset */
ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); ret = udf_do_extend_file(inode, &prev_epos, laarr, offset);
if (ret < 0) { if (ret < 0) {
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
*err = ret; *err = ret;
return 0; newblock = 0;
goto out_free;
} }
c = 0; c = 0;
offset = 0; offset = 0;
...@@ -841,11 +827,9 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -841,11 +827,9 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
iinfo->i_location.partitionReferenceNum, iinfo->i_location.partitionReferenceNum,
goal, err); goal, err);
if (!newblocknum) { if (!newblocknum) {
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
*err = -ENOSPC; *err = -ENOSPC;
return 0; newblock = 0;
goto out_free;
} }
if (isBeyondEOF) if (isBeyondEOF)
iinfo->i_lenExtents += inode->i_sb->s_blocksize; iinfo->i_lenExtents += inode->i_sb->s_blocksize;
...@@ -857,14 +841,12 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -857,14 +841,12 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
* block */ * block */
udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum); udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);
#ifdef UDF_PREALLOCATE
/* We preallocate blocks only for regular files. It also makes sense /* We preallocate blocks only for regular files. It also makes sense
* for directories but there's a problem when to drop the * for directories but there's a problem when to drop the
* preallocation. We might use some delayed work for that but I feel * preallocation. We might use some delayed work for that but I feel
* it's overengineering for a filesystem like UDF. */ * it's overengineering for a filesystem like UDF. */
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
udf_prealloc_extents(inode, c, lastblock, laarr, &endnum); udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);
#endif
/* merge any continuous blocks in laarr */ /* merge any continuous blocks in laarr */
udf_merge_extents(inode, laarr, &endnum); udf_merge_extents(inode, laarr, &endnum);
...@@ -874,15 +856,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -874,15 +856,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
* the new number of extents is less than the old number */ * the new number of extents is less than the old number */
udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
newblock = udf_get_pblock(inode->i_sb, newblocknum, newblock = udf_get_pblock(inode->i_sb, newblocknum,
iinfo->i_location.partitionReferenceNum, 0); iinfo->i_location.partitionReferenceNum, 0);
if (!newblock) { if (!newblock) {
*err = -EIO; *err = -EIO;
return 0; goto out_free;
} }
*new = 1; *new = 1;
iinfo->i_next_alloc_block = block; iinfo->i_next_alloc_block = block;
...@@ -893,13 +871,15 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, ...@@ -893,13 +871,15 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
udf_sync_inode(inode); udf_sync_inode(inode);
else else
mark_inode_dirty(inode); mark_inode_dirty(inode);
out_free:
brelse(prev_epos.bh);
brelse(cur_epos.bh);
brelse(next_epos.bh);
return newblock; return newblock;
} }
static void udf_split_extents(struct inode *inode, int *c, int offset, static void udf_split_extents(struct inode *inode, int *c, int offset,
int newblocknum, int newblocknum, struct kernel_long_ad *laarr,
struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
int *endnum) int *endnum)
{ {
unsigned long blocksize = inode->i_sb->s_blocksize; unsigned long blocksize = inode->i_sb->s_blocksize;
...@@ -963,7 +943,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, ...@@ -963,7 +943,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset,
} }
static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], struct kernel_long_ad *laarr,
int *endnum) int *endnum)
{ {
int start, length = 0, currlength = 0, i; int start, length = 0, currlength = 0, i;
...@@ -1058,8 +1038,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, ...@@ -1058,8 +1038,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
} }
} }
static void udf_merge_extents(struct inode *inode, static void udf_merge_extents(struct inode *inode, struct kernel_long_ad *laarr,
struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
int *endnum) int *endnum)
{ {
int i; int i;
...@@ -1158,8 +1137,7 @@ static void udf_merge_extents(struct inode *inode, ...@@ -1158,8 +1137,7 @@ static void udf_merge_extents(struct inode *inode,
} }
} }
static void udf_update_extents(struct inode *inode, static void udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr,
struct kernel_long_ad laarr[EXTENT_MERGE_SIZE],
int startnum, int endnum, int startnum, int endnum,
struct extent_position *epos) struct extent_position *epos)
{ {
...@@ -1299,6 +1277,12 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1299,6 +1277,12 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
int ret = -EIO; int ret = -EIO;
reread: reread:
if (iloc->partitionReferenceNum >= sbi->s_partitions) {
udf_debug("partition reference: %d > logical volume partitions: %d\n",
iloc->partitionReferenceNum, sbi->s_partitions);
return -EIO;
}
if (iloc->logicalBlockNum >= if (iloc->logicalBlockNum >=
sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) { sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
udf_debug("block=%d, partition=%d out of range\n", udf_debug("block=%d, partition=%d out of range\n",
...@@ -1549,7 +1533,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ...@@ -1549,7 +1533,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
break; break;
case ICBTAG_FILE_TYPE_SYMLINK: case ICBTAG_FILE_TYPE_SYMLINK:
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &udf_symlink_inode_operations;
inode_nohighmem(inode); inode_nohighmem(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_mode = S_IFLNK | S_IRWXUGO;
break; break;
...@@ -1627,6 +1611,14 @@ static int udf_sync_inode(struct inode *inode) ...@@ -1627,6 +1611,14 @@ static int udf_sync_inode(struct inode *inode)
return udf_update_inode(inode, 1); return udf_update_inode(inode, 1);
} }
static void udf_adjust_time(struct udf_inode_info *iinfo, struct timespec time)
{
if (iinfo->i_crtime.tv_sec > time.tv_sec ||
(iinfo->i_crtime.tv_sec == time.tv_sec &&
iinfo->i_crtime.tv_nsec > time.tv_nsec))
iinfo->i_crtime = time;
}
static int udf_update_inode(struct inode *inode, int do_sync) static int udf_update_inode(struct inode *inode, int do_sync)
{ {
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
...@@ -1753,20 +1745,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) ...@@ -1753,20 +1745,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
efe->objectSize = cpu_to_le64(inode->i_size); efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
if (iinfo->i_crtime.tv_sec > inode->i_atime.tv_sec || udf_adjust_time(iinfo, inode->i_atime);
(iinfo->i_crtime.tv_sec == inode->i_atime.tv_sec && udf_adjust_time(iinfo, inode->i_mtime);
iinfo->i_crtime.tv_nsec > inode->i_atime.tv_nsec)) udf_adjust_time(iinfo, inode->i_ctime);
iinfo->i_crtime = inode->i_atime;
if (iinfo->i_crtime.tv_sec > inode->i_mtime.tv_sec ||
(iinfo->i_crtime.tv_sec == inode->i_mtime.tv_sec &&
iinfo->i_crtime.tv_nsec > inode->i_mtime.tv_nsec))
iinfo->i_crtime = inode->i_mtime;
if (iinfo->i_crtime.tv_sec > inode->i_ctime.tv_sec ||
(iinfo->i_crtime.tv_sec == inode->i_ctime.tv_sec &&
iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
iinfo->i_crtime = inode->i_ctime;
udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime); udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime); udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
...@@ -2286,8 +2267,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block, ...@@ -2286,8 +2267,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
uint32_t *elen, sector_t *offset) uint32_t *elen, sector_t *offset)
{ {
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
loff_t lbcount = 0, bcount = loff_t lbcount = 0, bcount = (loff_t) block << blocksize_bits;
(loff_t) block << blocksize_bits;
int8_t etype; int8_t etype;
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
...@@ -2308,7 +2288,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block, ...@@ -2308,7 +2288,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
lbcount += *elen; lbcount += *elen;
} while (lbcount <= bcount); } while (lbcount <= bcount);
/* update extent cache */ /* update extent cache */
udf_update_extent_cache(inode, lbcount - *elen, pos, 1); udf_update_extent_cache(inode, lbcount - *elen, pos);
*offset = (bcount + *elen - lbcount) >> blocksize_bits; *offset = (bcount + *elen - lbcount) >> blocksize_bits;
return etype; return etype;
......
...@@ -58,7 +58,7 @@ unsigned long udf_get_last_block(struct super_block *sb) ...@@ -58,7 +58,7 @@ unsigned long udf_get_last_block(struct super_block *sb)
*/ */
if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock) || if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock) ||
lblock == 0) lblock == 0)
lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits; lblock = i_size_read(bdev->bd_inode) >> sb->s_blocksize_bits;
if (lblock) if (lblock)
return lblock - 1; return lblock - 1;
......
...@@ -141,8 +141,6 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, ...@@ -141,8 +141,6 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
iinfo->i_lenEAttr += size; iinfo->i_lenEAttr += size;
return (struct genericFormat *)&ea[offset]; return (struct genericFormat *)&ea[offset];
} }
if (loc & 0x02)
;
return NULL; return NULL;
} }
......
...@@ -931,7 +931,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -931,7 +931,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
} }
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &udf_symlink_inode_operations;
inode_nohighmem(inode); inode_nohighmem(inode);
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
......
...@@ -70,17 +70,17 @@ struct UDFIdentSuffix { ...@@ -70,17 +70,17 @@ struct UDFIdentSuffix {
uint8_t OSClass; uint8_t OSClass;
uint8_t OSIdentifier; uint8_t OSIdentifier;
uint8_t reserved[4]; uint8_t reserved[4];
} __attribute__ ((packed)); } __packed;
struct impIdentSuffix { struct impIdentSuffix {
uint8_t OSClass; uint8_t OSClass;
uint8_t OSIdentifier; uint8_t OSIdentifier;
uint8_t reserved[6]; uint8_t reserved[6];
} __attribute__ ((packed)); } __packed;
struct appIdentSuffix { struct appIdentSuffix {
uint8_t impUse[8]; uint8_t impUse[8];
} __attribute__ ((packed)); } __packed;
/* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */ /* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */
/* Implementation Use (UDF 2.50 2.2.6.4) */ /* Implementation Use (UDF 2.50 2.2.6.4) */
...@@ -92,7 +92,7 @@ struct logicalVolIntegrityDescImpUse { ...@@ -92,7 +92,7 @@ struct logicalVolIntegrityDescImpUse {
__le16 minUDFWriteRev; __le16 minUDFWriteRev;
__le16 maxUDFWriteRev; __le16 maxUDFWriteRev;
uint8_t impUse[0]; uint8_t impUse[0];
} __attribute__ ((packed)); } __packed;
/* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */ /* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */
/* Implementation Use (UDF 2.50 2.2.7.2) */ /* Implementation Use (UDF 2.50 2.2.7.2) */
...@@ -104,7 +104,7 @@ struct impUseVolDescImpUse { ...@@ -104,7 +104,7 @@ struct impUseVolDescImpUse {
dstring LVInfo3[36]; dstring LVInfo3[36];
struct regid impIdent; struct regid impIdent;
uint8_t impUse[128]; uint8_t impUse[128];
} __attribute__ ((packed)); } __packed;
struct udfPartitionMap2 { struct udfPartitionMap2 {
uint8_t partitionMapType; uint8_t partitionMapType;
...@@ -113,7 +113,7 @@ struct udfPartitionMap2 { ...@@ -113,7 +113,7 @@ struct udfPartitionMap2 {
struct regid partIdent; struct regid partIdent;
__le16 volSeqNum; __le16 volSeqNum;
__le16 partitionNum; __le16 partitionNum;
} __attribute__ ((packed)); } __packed;
/* Virtual Partition Map (UDF 2.50 2.2.8) */ /* Virtual Partition Map (UDF 2.50 2.2.8) */
struct virtualPartitionMap { struct virtualPartitionMap {
...@@ -124,7 +124,7 @@ struct virtualPartitionMap { ...@@ -124,7 +124,7 @@ struct virtualPartitionMap {
__le16 volSeqNum; __le16 volSeqNum;
__le16 partitionNum; __le16 partitionNum;
uint8_t reserved2[24]; uint8_t reserved2[24];
} __attribute__ ((packed)); } __packed;
/* Sparable Partition Map (UDF 2.50 2.2.9) */ /* Sparable Partition Map (UDF 2.50 2.2.9) */
struct sparablePartitionMap { struct sparablePartitionMap {
...@@ -139,7 +139,7 @@ struct sparablePartitionMap { ...@@ -139,7 +139,7 @@ struct sparablePartitionMap {
uint8_t reserved2[1]; uint8_t reserved2[1];
__le32 sizeSparingTable; __le32 sizeSparingTable;
__le32 locSparingTable[4]; __le32 locSparingTable[4];
} __attribute__ ((packed)); } __packed;
/* Metadata Partition Map (UDF 2.4.0 2.2.10) */ /* Metadata Partition Map (UDF 2.4.0 2.2.10) */
struct metadataPartitionMap { struct metadataPartitionMap {
...@@ -156,14 +156,14 @@ struct metadataPartitionMap { ...@@ -156,14 +156,14 @@ struct metadataPartitionMap {
__le16 alignUnitSize; __le16 alignUnitSize;
uint8_t flags; uint8_t flags;
uint8_t reserved2[5]; uint8_t reserved2[5];
} __attribute__ ((packed)); } __packed;
/* Virtual Allocation Table (UDF 1.5 2.2.10) */ /* Virtual Allocation Table (UDF 1.5 2.2.10) */
struct virtualAllocationTable15 { struct virtualAllocationTable15 {
__le32 VirtualSector[0]; __le32 VirtualSector[0];
struct regid vatIdent; struct regid vatIdent;
__le32 previousVATICBLoc; __le32 previousVATICBLoc;
} __attribute__ ((packed)); } __packed;
#define ICBTAG_FILE_TYPE_VAT15 0x00U #define ICBTAG_FILE_TYPE_VAT15 0x00U
...@@ -181,7 +181,7 @@ struct virtualAllocationTable20 { ...@@ -181,7 +181,7 @@ struct virtualAllocationTable20 {
__le16 reserved; __le16 reserved;
uint8_t impUse[0]; uint8_t impUse[0];
__le32 vatEntry[0]; __le32 vatEntry[0];
} __attribute__ ((packed)); } __packed;
#define ICBTAG_FILE_TYPE_VAT20 0xF8U #define ICBTAG_FILE_TYPE_VAT20 0xF8U
...@@ -189,7 +189,7 @@ struct virtualAllocationTable20 { ...@@ -189,7 +189,7 @@ struct virtualAllocationTable20 {
struct sparingEntry { struct sparingEntry {
__le32 origLocation; __le32 origLocation;
__le32 mappedLocation; __le32 mappedLocation;
} __attribute__ ((packed)); } __packed;
struct sparingTable { struct sparingTable {
struct tag descTag; struct tag descTag;
...@@ -199,7 +199,7 @@ struct sparingTable { ...@@ -199,7 +199,7 @@ struct sparingTable {
__le32 sequenceNum; __le32 sequenceNum;
struct sparingEntry struct sparingEntry
mapEntry[0]; mapEntry[0];
} __attribute__ ((packed)); } __packed;
/* Metadata File (and Metadata Mirror File) (UDF 2.50 2.2.13.1) */ /* Metadata File (and Metadata Mirror File) (UDF 2.50 2.2.13.1) */
#define ICBTAG_FILE_TYPE_MAIN 0xFA #define ICBTAG_FILE_TYPE_MAIN 0xFA
...@@ -210,7 +210,7 @@ struct sparingTable { ...@@ -210,7 +210,7 @@ struct sparingTable {
struct allocDescImpUse { struct allocDescImpUse {
__le16 flags; __le16 flags;
uint8_t impUse[4]; uint8_t impUse[4];
} __attribute__ ((packed)); } __packed;
#define AD_IU_EXT_ERASED 0x0001 #define AD_IU_EXT_ERASED 0x0001
...@@ -222,7 +222,7 @@ struct allocDescImpUse { ...@@ -222,7 +222,7 @@ struct allocDescImpUse {
struct freeEaSpace { struct freeEaSpace {
__le16 headerChecksum; __le16 headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[0];
} __attribute__ ((packed)); } __packed;
/* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */ /* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */
struct DVDCopyrightImpUse { struct DVDCopyrightImpUse {
...@@ -230,14 +230,14 @@ struct DVDCopyrightImpUse { ...@@ -230,14 +230,14 @@ struct DVDCopyrightImpUse {
uint8_t CGMSInfo; uint8_t CGMSInfo;
uint8_t dataType; uint8_t dataType;
uint8_t protectionSystemInfo[4]; uint8_t protectionSystemInfo[4];
} __attribute__ ((packed)); } __packed;
/* Application Use Extended Attribute (UDF 2.50 3.3.4.6) */ /* Application Use Extended Attribute (UDF 2.50 3.3.4.6) */
/* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */ /* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
struct freeAppEASpace { struct freeAppEASpace {
__le16 headerChecksum; __le16 headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[0];
} __attribute__ ((packed)); } __packed;
/* UDF Defined System Stream (UDF 2.50 3.3.7) */ /* UDF Defined System Stream (UDF 2.50 3.3.7) */
#define UDF_ID_UNIQUE_ID "*UDF Unique ID Mapping Data" #define UDF_ID_UNIQUE_ID "*UDF Unique ID Mapping Data"
......
...@@ -264,9 +264,6 @@ static void __exit exit_udf_fs(void) ...@@ -264,9 +264,6 @@ static void __exit exit_udf_fs(void)
destroy_inodecache(); destroy_inodecache();
} }
module_init(init_udf_fs)
module_exit(exit_udf_fs)
static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count) static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
{ {
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_sb_info *sbi = UDF_SB(sb);
...@@ -1216,7 +1213,8 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) ...@@ -1216,7 +1213,8 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
struct udf_inode_info *vati; struct udf_inode_info *vati;
uint32_t pos; uint32_t pos;
struct virtualAllocationTable20 *vat20; struct virtualAllocationTable20 *vat20;
sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; sector_t blocks = i_size_read(sb->s_bdev->bd_inode) >>
sb->s_blocksize_bits;
udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
if (!sbi->s_vat_inode && if (!sbi->s_vat_inode &&
...@@ -1806,7 +1804,7 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block, ...@@ -1806,7 +1804,7 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block,
if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
udf_fixed_to_variable(block) >= udf_fixed_to_variable(block) >=
sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) i_size_read(sb->s_bdev->bd_inode) >> sb->s_blocksize_bits)
return -EAGAIN; return -EAGAIN;
bh = udf_read_tagged(sb, block, block, &ident); bh = udf_read_tagged(sb, block, block, &ident);
...@@ -1868,7 +1866,7 @@ static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock, ...@@ -1868,7 +1866,7 @@ static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock,
last[last_count++] = *lastblock - 152; last[last_count++] = *lastblock - 152;
for (i = 0; i < last_count; i++) { for (i = 0; i < last_count; i++) {
if (last[i] >= sb->s_bdev->bd_inode->i_size >> if (last[i] >= i_size_read(sb->s_bdev->bd_inode) >>
sb->s_blocksize_bits) sb->s_blocksize_bits)
continue; continue;
ret = udf_check_anchor_block(sb, last[i], fileset); ret = udf_check_anchor_block(sb, last[i], fileset);
...@@ -1957,7 +1955,7 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, ...@@ -1957,7 +1955,7 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
if (!nsr_off) { if (!nsr_off) {
if (!silent) if (!silent)
udf_warn(sb, "No VRS found\n"); udf_warn(sb, "No VRS found\n");
return 0; return -EINVAL;
} }
if (nsr_off == -1) if (nsr_off == -1)
udf_debug("Failed to read sector at offset %d. " udf_debug("Failed to read sector at offset %d. "
...@@ -1986,6 +1984,7 @@ static void udf_open_lvid(struct super_block *sb) ...@@ -1986,6 +1984,7 @@ static void udf_open_lvid(struct super_block *sb)
struct buffer_head *bh = sbi->s_lvid_bh; struct buffer_head *bh = sbi->s_lvid_bh;
struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDesc *lvid;
struct logicalVolIntegrityDescImpUse *lvidiu; struct logicalVolIntegrityDescImpUse *lvidiu;
struct timespec ts;
if (!bh) if (!bh)
return; return;
...@@ -1997,8 +1996,8 @@ static void udf_open_lvid(struct super_block *sb) ...@@ -1997,8 +1996,8 @@ static void udf_open_lvid(struct super_block *sb)
mutex_lock(&sbi->s_alloc_mutex); mutex_lock(&sbi->s_alloc_mutex);
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ktime_get_real_ts(&ts);
CURRENT_TIME); udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
lvid->descTag.descCRC = cpu_to_le16( lvid->descTag.descCRC = cpu_to_le16(
...@@ -2019,6 +2018,7 @@ static void udf_close_lvid(struct super_block *sb) ...@@ -2019,6 +2018,7 @@ static void udf_close_lvid(struct super_block *sb)
struct buffer_head *bh = sbi->s_lvid_bh; struct buffer_head *bh = sbi->s_lvid_bh;
struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDesc *lvid;
struct logicalVolIntegrityDescImpUse *lvidiu; struct logicalVolIntegrityDescImpUse *lvidiu;
struct timespec ts;
if (!bh) if (!bh)
return; return;
...@@ -2030,7 +2030,8 @@ static void udf_close_lvid(struct super_block *sb) ...@@ -2030,7 +2030,8 @@ static void udf_close_lvid(struct super_block *sb)
mutex_lock(&sbi->s_alloc_mutex); mutex_lock(&sbi->s_alloc_mutex);
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); ktime_get_real_ts(&ts);
udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev)) if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
...@@ -2158,15 +2159,25 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -2158,15 +2159,25 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
ret = udf_load_vrs(sb, &uopt, silent, &fileset); ret = udf_load_vrs(sb, &uopt, silent, &fileset);
} else { } else {
uopt.blocksize = bdev_logical_block_size(sb->s_bdev); uopt.blocksize = bdev_logical_block_size(sb->s_bdev);
while (uopt.blocksize <= 4096) {
ret = udf_load_vrs(sb, &uopt, silent, &fileset); ret = udf_load_vrs(sb, &uopt, silent, &fileset);
if (ret == -EAGAIN && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) { if (ret < 0) {
if (!silent) if (!silent && ret != -EACCES) {
pr_notice("Rescanning with blocksize %d\n", pr_notice("Scanning with blocksize %d failed\n",
UDF_DEFAULT_BLOCKSIZE); uopt.blocksize);
}
brelse(sbi->s_lvid_bh); brelse(sbi->s_lvid_bh);
sbi->s_lvid_bh = NULL; sbi->s_lvid_bh = NULL;
uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; /*
ret = udf_load_vrs(sb, &uopt, silent, &fileset); * EACCES is special - we want to propagate to
* upper layers that we cannot handle RW mount.
*/
if (ret == -EACCES)
break;
} else
break;
uopt.blocksize <<= 1;
} }
} }
if (ret < 0) { if (ret < 0) {
...@@ -2497,3 +2508,9 @@ static unsigned int udf_count_free(struct super_block *sb) ...@@ -2497,3 +2508,9 @@ static unsigned int udf_count_free(struct super_block *sb)
return accum; return accum;
} }
MODULE_AUTHOR("Ben Fennema");
MODULE_DESCRIPTION("Universal Disk Format Filesystem");
MODULE_LICENSE("GPL");
module_init(init_udf_fs)
module_exit(exit_udf_fs)
...@@ -152,9 +152,39 @@ static int udf_symlink_filler(struct file *file, struct page *page) ...@@ -152,9 +152,39 @@ static int udf_symlink_filler(struct file *file, struct page *page)
return err; return err;
} }
static int udf_symlink_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
struct inode *inode = d_backing_inode(dentry);
struct page *page;
generic_fillattr(inode, stat);
page = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(page))
return PTR_ERR(page);
/*
* UDF uses non-trivial encoding of symlinks so i_size does not match
* number of characters reported by readlink(2) which apparently some
* applications expect. Also POSIX says that "The value returned in the
* st_size field shall be the length of the contents of the symbolic
* link, and shall not count a trailing null if one is present." So
* let's report the length of string returned by readlink(2) for
* st_size.
*/
stat->size = strlen(page_address(page));
put_page(page);
return 0;
}
/* /*
* symlinks can't do much... * symlinks can't do much...
*/ */
const struct address_space_operations udf_symlink_aops = { const struct address_space_operations udf_symlink_aops = {
.readpage = udf_symlink_filler, .readpage = udf_symlink_filler,
}; };
const struct inode_operations udf_symlink_inode_operations = {
.get_link = page_get_link,
.getattr = udf_symlink_getattr,
};
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "udfend.h" #include "udfend.h"
#include "udf_i.h" #include "udf_i.h"
#define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8 #define UDF_DEFAULT_PREALLOC_BLOCKS 8
extern __printf(3, 4) void _udf_err(struct super_block *sb, extern __printf(3, 4) void _udf_err(struct super_block *sb,
...@@ -85,6 +84,7 @@ extern const struct inode_operations udf_dir_inode_operations; ...@@ -85,6 +84,7 @@ extern const struct inode_operations udf_dir_inode_operations;
extern const struct file_operations udf_dir_operations; extern const struct file_operations udf_dir_operations;
extern const struct inode_operations udf_file_inode_operations; extern const struct inode_operations udf_file_inode_operations;
extern const struct file_operations udf_file_operations; extern const struct file_operations udf_file_operations;
extern const struct inode_operations udf_symlink_inode_operations;
extern const struct address_space_operations udf_aops; extern const struct address_space_operations udf_aops;
extern const struct address_space_operations udf_adinicb_aops; extern const struct address_space_operations udf_adinicb_aops;
extern const struct address_space_operations udf_symlink_aops; extern const struct address_space_operations udf_symlink_aops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment