mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6: UDF: Close small mem leak in udf_find_entry() udf: Fix directory corruption after extent merging udf: Protect udf_file_aio_write from possible races udf: Remove unnecessary bkl usages udf: Use of s_alloc_mutex to serialize udf_relocate_blocks() execution udf: Replace bkl with the UDF_I(inode)->i_data_sem for protect udf_inode_info struct udf: Remove BKL from free space counting functions udf: Call udf_add_free_space() for more blocks at once in udf_free_blocks() udf: Remove BKL from udf_put_super() and udf_remount_fs() udf: Protect default inode credentials by rwlock udf: Protect all modifications of LVID with s_alloc_mutex udf: Move handling of uniqueID into a helper function and protect it by a s_alloc_mutex udf: Remove BKL from udf_update_inode udf: Convert UDF_SB(sb)->s_flags to use bitops fs/udf: Add printf format/argument verification fs/udf: Use vzalloc (Evil merge: this also removes the BKL dependency from the Kconfig file)
This commit is contained in:
commit
7c955fca3e
@ -1,6 +1,5 @@
|
|||||||
config UDF_FS
|
config UDF_FS
|
||||||
tristate "UDF file system support"
|
tristate "UDF file system support"
|
||||||
depends on BKL # needs serious work to remove
|
|
||||||
select CRC_ITU_T
|
select CRC_ITU_T
|
||||||
help
|
help
|
||||||
This is the new file system used on some CD-ROMs and DVDs. Say Y if
|
This is the new file system used on some CD-ROMs and DVDs. Say Y if
|
||||||
|
@ -157,10 +157,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
|
|||||||
udf_debug("bit %ld already set\n", bit + i);
|
udf_debug("bit %ld already set\n", bit + i);
|
||||||
udf_debug("byte=%2x\n",
|
udf_debug("byte=%2x\n",
|
||||||
((char *)bh->b_data)[(bit + i) >> 3]);
|
((char *)bh->b_data)[(bit + i) >> 3]);
|
||||||
} else {
|
|
||||||
udf_add_free_space(sb, sbi->s_partition, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
udf_add_free_space(sb, sbi->s_partition, count);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
if (overflow) {
|
if (overflow) {
|
||||||
block += count;
|
block += count;
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
|
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
@ -190,18 +189,14 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||||||
struct inode *dir = filp->f_path.dentry->d_inode;
|
struct inode *dir = filp->f_path.dentry->d_inode;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
if (filp->f_pos == 0) {
|
if (filp->f_pos == 0) {
|
||||||
if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
|
if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
filp->f_pos++;
|
filp->f_pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = do_udf_readdir(dir, filp, filldir, dirent);
|
result = do_udf_readdir(dir, filp, filldir, dirent);
|
||||||
unlock_kernel();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include <linux/string.h> /* memset */
|
#include <linux/string.h> /* memset */
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/aio.h>
|
#include <linux/aio.h>
|
||||||
@ -114,6 +113,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||||||
size_t count = iocb->ki_left;
|
size_t count = iocb->ki_left;
|
||||||
struct udf_inode_info *iinfo = UDF_I(inode);
|
struct udf_inode_info *iinfo = UDF_I(inode);
|
||||||
|
|
||||||
|
down_write(&iinfo->i_data_sem);
|
||||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||||
if (file->f_flags & O_APPEND)
|
if (file->f_flags & O_APPEND)
|
||||||
pos = inode->i_size;
|
pos = inode->i_size;
|
||||||
@ -126,6 +126,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||||||
udf_expand_file_adinicb(inode, pos + count, &err);
|
udf_expand_file_adinicb(inode, pos + count, &err);
|
||||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||||
udf_debug("udf_expand_adinicb: err=%d\n", err);
|
udf_debug("udf_expand_adinicb: err=%d\n", err);
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -135,6 +136,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||||||
iinfo->i_lenAlloc = inode->i_size;
|
iinfo->i_lenAlloc = inode->i_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
|
|
||||||
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
|
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
|
||||||
if (retval > 0)
|
if (retval > 0)
|
||||||
@ -149,8 +151,6 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||||||
long old_block, new_block;
|
long old_block, new_block;
|
||||||
int result = -EINVAL;
|
int result = -EINVAL;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
if (file_permission(filp, MAY_READ) != 0) {
|
if (file_permission(filp, 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;
|
result = -EPERM;
|
||||||
@ -196,7 +196,6 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,10 +203,10 @@ static int udf_release_file(struct inode *inode, struct file *filp)
|
|||||||
{
|
{
|
||||||
if (filp->f_mode & FMODE_WRITE) {
|
if (filp->f_mode & FMODE_WRITE) {
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
lock_kernel();
|
down_write(&UDF_I(inode)->i_data_sem);
|
||||||
udf_discard_prealloc(inode);
|
udf_discard_prealloc(inode);
|
||||||
udf_truncate_tail_extent(inode);
|
udf_truncate_tail_extent(inode);
|
||||||
unlock_kernel();
|
up_write(&UDF_I(inode)->i_data_sem);
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -92,28 +92,19 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&sbi->s_alloc_mutex);
|
|
||||||
if (sbi->s_lvid_bh) {
|
if (sbi->s_lvid_bh) {
|
||||||
struct logicalVolIntegrityDesc *lvid =
|
struct logicalVolIntegrityDescImpUse *lvidiu;
|
||||||
(struct logicalVolIntegrityDesc *)
|
|
||||||
sbi->s_lvid_bh->b_data;
|
iinfo->i_unique = lvid_get_unique_id(sb);
|
||||||
struct logicalVolIntegrityDescImpUse *lvidiu =
|
mutex_lock(&sbi->s_alloc_mutex);
|
||||||
udf_sb_lvidiu(sbi);
|
lvidiu = udf_sb_lvidiu(sbi);
|
||||||
struct logicalVolHeaderDesc *lvhd;
|
|
||||||
uint64_t uniqueID;
|
|
||||||
lvhd = (struct logicalVolHeaderDesc *)
|
|
||||||
(lvid->logicalVolContentsUse);
|
|
||||||
if (S_ISDIR(mode))
|
if (S_ISDIR(mode))
|
||||||
le32_add_cpu(&lvidiu->numDirs, 1);
|
le32_add_cpu(&lvidiu->numDirs, 1);
|
||||||
else
|
else
|
||||||
le32_add_cpu(&lvidiu->numFiles, 1);
|
le32_add_cpu(&lvidiu->numFiles, 1);
|
||||||
iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID);
|
|
||||||
if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
|
||||||
uniqueID += 16;
|
|
||||||
lvhd->uniqueID = cpu_to_le64(uniqueID);
|
|
||||||
udf_updated_lvid(sb);
|
udf_updated_lvid(sb);
|
||||||
|
mutex_unlock(&sbi->s_alloc_mutex);
|
||||||
}
|
}
|
||||||
mutex_unlock(&sbi->s_alloc_mutex);
|
|
||||||
|
|
||||||
inode_init_owner(inode, dir, mode);
|
inode_init_owner(inode, dir, mode);
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include "udfdecl.h"
|
#include "udfdecl.h"
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
@ -51,6 +50,7 @@ MODULE_LICENSE("GPL");
|
|||||||
static mode_t udf_convert_permissions(struct fileEntry *);
|
static mode_t udf_convert_permissions(struct fileEntry *);
|
||||||
static int udf_update_inode(struct inode *, int);
|
static int udf_update_inode(struct inode *, int);
|
||||||
static void udf_fill_inode(struct inode *, struct buffer_head *);
|
static void udf_fill_inode(struct inode *, struct buffer_head *);
|
||||||
|
static int udf_sync_inode(struct inode *inode);
|
||||||
static int udf_alloc_i_data(struct inode *inode, size_t size);
|
static int udf_alloc_i_data(struct inode *inode, size_t size);
|
||||||
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
|
static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
|
||||||
sector_t *, int *);
|
sector_t *, int *);
|
||||||
@ -79,9 +79,7 @@ void udf_evict_inode(struct inode *inode)
|
|||||||
want_delete = 1;
|
want_delete = 1;
|
||||||
inode->i_size = 0;
|
inode->i_size = 0;
|
||||||
udf_truncate(inode);
|
udf_truncate(inode);
|
||||||
lock_kernel();
|
|
||||||
udf_update_inode(inode, IS_SYNC(inode));
|
udf_update_inode(inode, IS_SYNC(inode));
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
invalidate_inode_buffers(inode);
|
invalidate_inode_buffers(inode);
|
||||||
end_writeback(inode);
|
end_writeback(inode);
|
||||||
@ -97,9 +95,7 @@ void udf_evict_inode(struct inode *inode)
|
|||||||
kfree(iinfo->i_ext.i_data);
|
kfree(iinfo->i_ext.i_data);
|
||||||
iinfo->i_ext.i_data = NULL;
|
iinfo->i_ext.i_data = NULL;
|
||||||
if (want_delete) {
|
if (want_delete) {
|
||||||
lock_kernel();
|
|
||||||
udf_free_inode(inode);
|
udf_free_inode(inode);
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,10 +298,9 @@ static int udf_get_block(struct inode *inode, sector_t block,
|
|||||||
err = -EIO;
|
err = -EIO;
|
||||||
new = 0;
|
new = 0;
|
||||||
bh = NULL;
|
bh = NULL;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
iinfo = UDF_I(inode);
|
iinfo = UDF_I(inode);
|
||||||
|
|
||||||
|
down_write(&iinfo->i_data_sem);
|
||||||
if (block == iinfo->i_next_alloc_block + 1) {
|
if (block == iinfo->i_next_alloc_block + 1) {
|
||||||
iinfo->i_next_alloc_block++;
|
iinfo->i_next_alloc_block++;
|
||||||
iinfo->i_next_alloc_goal++;
|
iinfo->i_next_alloc_goal++;
|
||||||
@ -324,7 +319,7 @@ static int udf_get_block(struct inode *inode, sector_t block,
|
|||||||
map_bh(bh_result, inode->i_sb, phys);
|
map_bh(bh_result, inode->i_sb, phys);
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
unlock_kernel();
|
up_write(&iinfo->i_data_sem);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1022,16 +1017,16 @@ void udf_truncate(struct inode *inode)
|
|||||||
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
|
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
iinfo = UDF_I(inode);
|
iinfo = UDF_I(inode);
|
||||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||||
|
down_write(&iinfo->i_data_sem);
|
||||||
if (inode->i_sb->s_blocksize <
|
if (inode->i_sb->s_blocksize <
|
||||||
(udf_file_entry_alloc_offset(inode) +
|
(udf_file_entry_alloc_offset(inode) +
|
||||||
inode->i_size)) {
|
inode->i_size)) {
|
||||||
udf_expand_file_adinicb(inode, inode->i_size, &err);
|
udf_expand_file_adinicb(inode, inode->i_size, &err);
|
||||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||||
inode->i_size = iinfo->i_lenAlloc;
|
inode->i_size = iinfo->i_lenAlloc;
|
||||||
unlock_kernel();
|
up_write(&iinfo->i_data_sem);
|
||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
udf_truncate_extents(inode);
|
udf_truncate_extents(inode);
|
||||||
@ -1042,10 +1037,13 @@ void udf_truncate(struct inode *inode)
|
|||||||
offset - udf_file_entry_alloc_offset(inode));
|
offset - udf_file_entry_alloc_offset(inode));
|
||||||
iinfo->i_lenAlloc = inode->i_size;
|
iinfo->i_lenAlloc = inode->i_size;
|
||||||
}
|
}
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
} else {
|
} else {
|
||||||
block_truncate_page(inode->i_mapping, inode->i_size,
|
block_truncate_page(inode->i_mapping, inode->i_size,
|
||||||
udf_get_block);
|
udf_get_block);
|
||||||
|
down_write(&iinfo->i_data_sem);
|
||||||
udf_truncate_extents(inode);
|
udf_truncate_extents(inode);
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
|
inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
|
||||||
@ -1053,7 +1051,6 @@ void udf_truncate(struct inode *inode)
|
|||||||
udf_sync_inode(inode);
|
udf_sync_inode(inode);
|
||||||
else
|
else
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __udf_read_inode(struct inode *inode)
|
static void __udf_read_inode(struct inode *inode)
|
||||||
@ -1202,6 +1199,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_lock(&sbi->s_cred_lock);
|
||||||
inode->i_uid = le32_to_cpu(fe->uid);
|
inode->i_uid = le32_to_cpu(fe->uid);
|
||||||
if (inode->i_uid == -1 ||
|
if (inode->i_uid == -1 ||
|
||||||
UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||
|
UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||
|
||||||
@ -1214,13 +1212,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||||||
UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
|
UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
|
||||||
inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
|
inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
|
||||||
|
|
||||||
inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
|
|
||||||
if (!inode->i_nlink)
|
|
||||||
inode->i_nlink = 1;
|
|
||||||
|
|
||||||
inode->i_size = le64_to_cpu(fe->informationLength);
|
|
||||||
iinfo->i_lenExtents = inode->i_size;
|
|
||||||
|
|
||||||
if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&
|
if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY &&
|
||||||
sbi->s_fmode != UDF_INVALID_MODE)
|
sbi->s_fmode != UDF_INVALID_MODE)
|
||||||
inode->i_mode = sbi->s_fmode;
|
inode->i_mode = sbi->s_fmode;
|
||||||
@ -1230,6 +1221,14 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|||||||
else
|
else
|
||||||
inode->i_mode = udf_convert_permissions(fe);
|
inode->i_mode = udf_convert_permissions(fe);
|
||||||
inode->i_mode &= ~sbi->s_umask;
|
inode->i_mode &= ~sbi->s_umask;
|
||||||
|
read_unlock(&sbi->s_cred_lock);
|
||||||
|
|
||||||
|
inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
|
||||||
|
if (!inode->i_nlink)
|
||||||
|
inode->i_nlink = 1;
|
||||||
|
|
||||||
|
inode->i_size = le64_to_cpu(fe->informationLength);
|
||||||
|
iinfo->i_lenExtents = inode->i_size;
|
||||||
|
|
||||||
if (iinfo->i_efe == 0) {
|
if (iinfo->i_efe == 0) {
|
||||||
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
|
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
|
||||||
@ -1373,16 +1372,10 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)
|
|||||||
|
|
||||||
int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
|
int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
int ret;
|
return udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
ret = udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
|
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int udf_sync_inode(struct inode *inode)
|
static int udf_sync_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
return udf_update_inode(inode, 1);
|
return udf_update_inode(inode, 1);
|
||||||
}
|
}
|
||||||
@ -2048,7 +2041,7 @@ long udf_block_map(struct inode *inode, sector_t block)
|
|||||||
struct extent_position epos = {};
|
struct extent_position epos = {};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lock_kernel();
|
down_read(&UDF_I(inode)->i_data_sem);
|
||||||
|
|
||||||
if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==
|
if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) ==
|
||||||
(EXT_RECORDED_ALLOCATED >> 30))
|
(EXT_RECORDED_ALLOCATED >> 30))
|
||||||
@ -2056,7 +2049,7 @@ long udf_block_map(struct inode *inode, sector_t block)
|
|||||||
else
|
else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
unlock_kernel();
|
up_read(&UDF_I(inode)->i_data_sem);
|
||||||
brelse(epos.bh);
|
brelse(epos.bh);
|
||||||
|
|
||||||
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
|
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
|
||||||
|
107
fs/udf/namei.c
107
fs/udf/namei.c
@ -27,7 +27,6 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/crc-itu-t.h>
|
#include <linux/crc-itu-t.h>
|
||||||
@ -228,10 +227,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
|
if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
|
||||||
isdotdot) {
|
isdotdot)
|
||||||
brelse(epos.bh);
|
goto out_ok;
|
||||||
return fi;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lfi)
|
if (!lfi)
|
||||||
continue;
|
continue;
|
||||||
@ -263,7 +260,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
if (dentry->d_name.len > UDF_NAME_LEN - 2)
|
if (dentry->d_name.len > UDF_NAME_LEN - 2)
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
#ifdef UDF_RECOVERY
|
#ifdef UDF_RECOVERY
|
||||||
/* temporary shorthand for specifying files by inode number */
|
/* temporary shorthand for specifying files by inode number */
|
||||||
if (!strncmp(dentry->d_name.name, ".B=", 3)) {
|
if (!strncmp(dentry->d_name.name, ".B=", 3)) {
|
||||||
@ -275,7 +271,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
};
|
};
|
||||||
inode = udf_iget(dir->i_sb, lb);
|
inode = udf_iget(dir->i_sb, lb);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
unlock_kernel();
|
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -291,11 +286,9 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
loc = lelb_to_cpu(cfi.icb.extLocation);
|
loc = lelb_to_cpu(cfi.icb.extLocation);
|
||||||
inode = udf_iget(dir->i_sb, &loc);
|
inode = udf_iget(dir->i_sb, &loc);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
unlock_kernel();
|
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return d_splice_alias(inode, dentry);
|
return d_splice_alias(inode, dentry);
|
||||||
}
|
}
|
||||||
@ -476,15 +469,19 @@ add:
|
|||||||
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
|
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
|
||||||
if (!fibh->ebh)
|
if (!fibh->ebh)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
/* Extents could have been merged, invalidate our position */
|
||||||
|
brelse(epos.bh);
|
||||||
|
epos.bh = NULL;
|
||||||
|
epos.block = dinfo->i_location;
|
||||||
|
epos.offset = udf_file_entry_alloc_offset(dir);
|
||||||
|
|
||||||
if (!fibh->soffset) {
|
if (!fibh->soffset) {
|
||||||
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
|
/* Find the freshly allocated block */
|
||||||
(EXT_RECORDED_ALLOCATED >> 30)) {
|
while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
|
||||||
block = eloc.logicalBlockNum + ((elen - 1) >>
|
(EXT_RECORDED_ALLOCATED >> 30))
|
||||||
|
;
|
||||||
|
block = eloc.logicalBlockNum + ((elen - 1) >>
|
||||||
dir->i_sb->s_blocksize_bits);
|
dir->i_sb->s_blocksize_bits);
|
||||||
} else
|
|
||||||
block++;
|
|
||||||
|
|
||||||
brelse(fibh->sbh);
|
brelse(fibh->sbh);
|
||||||
fibh->sbh = fibh->ebh;
|
fibh->sbh = fibh->ebh;
|
||||||
fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
|
fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
|
||||||
@ -562,10 +559,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
int err;
|
int err;
|
||||||
struct udf_inode_info *iinfo;
|
struct udf_inode_info *iinfo;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
inode = udf_new_inode(dir, mode, &err);
|
inode = udf_new_inode(dir, mode, &err);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +578,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
inode->i_nlink--;
|
inode->i_nlink--;
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
||||||
@ -596,7 +590,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
if (fibh.sbh != fibh.ebh)
|
if (fibh.sbh != fibh.ebh)
|
||||||
brelse(fibh.ebh);
|
brelse(fibh.ebh);
|
||||||
brelse(fibh.sbh);
|
brelse(fibh.sbh);
|
||||||
unlock_kernel();
|
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -614,7 +607,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
if (!old_valid_dev(rdev))
|
if (!old_valid_dev(rdev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
inode = udf_new_inode(dir, mode, &err);
|
inode = udf_new_inode(dir, mode, &err);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
@ -627,7 +619,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
inode->i_nlink--;
|
inode->i_nlink--;
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
||||||
@ -646,7 +637,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
|
|||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +649,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
|||||||
struct udf_inode_info *dinfo = UDF_I(dir);
|
struct udf_inode_info *dinfo = UDF_I(dir);
|
||||||
struct udf_inode_info *iinfo;
|
struct udf_inode_info *iinfo;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
err = -EMLINK;
|
err = -EMLINK;
|
||||||
if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1)
|
if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1)
|
||||||
goto out;
|
goto out;
|
||||||
@ -712,7 +701,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
|||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,7 +782,6 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
struct kernel_lb_addr tloc;
|
struct kernel_lb_addr tloc;
|
||||||
|
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
lock_kernel();
|
|
||||||
fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
|
fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
|
||||||
if (!fi)
|
if (!fi)
|
||||||
goto out;
|
goto out;
|
||||||
@ -826,7 +813,6 @@ end_rmdir:
|
|||||||
brelse(fibh.sbh);
|
brelse(fibh.sbh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,7 +826,6 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
struct kernel_lb_addr tloc;
|
struct kernel_lb_addr tloc;
|
||||||
|
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
lock_kernel();
|
|
||||||
fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
|
fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
|
||||||
if (!fi)
|
if (!fi)
|
||||||
goto out;
|
goto out;
|
||||||
@ -870,7 +855,6 @@ end_unlink:
|
|||||||
brelse(fibh.sbh);
|
brelse(fibh.sbh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -890,21 +874,21 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
int block;
|
int block;
|
||||||
unsigned char *name = NULL;
|
unsigned char *name = NULL;
|
||||||
int namelen;
|
int namelen;
|
||||||
struct buffer_head *bh;
|
|
||||||
struct udf_inode_info *iinfo;
|
struct udf_inode_info *iinfo;
|
||||||
|
struct super_block *sb = dir->i_sb;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
|
inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
iinfo = UDF_I(inode);
|
||||||
|
down_write(&iinfo->i_data_sem);
|
||||||
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_no_entry;
|
goto out_no_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
iinfo = UDF_I(inode);
|
|
||||||
inode->i_data.a_ops = &udf_symlink_aops;
|
inode->i_data.a_ops = &udf_symlink_aops;
|
||||||
inode->i_op = &udf_symlink_inode_operations;
|
inode->i_op = &udf_symlink_inode_operations;
|
||||||
|
|
||||||
@ -912,7 +896,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
struct kernel_lb_addr eloc;
|
struct kernel_lb_addr eloc;
|
||||||
uint32_t bsize;
|
uint32_t bsize;
|
||||||
|
|
||||||
block = udf_new_block(inode->i_sb, inode,
|
block = udf_new_block(sb, inode,
|
||||||
iinfo->i_location.partitionReferenceNum,
|
iinfo->i_location.partitionReferenceNum,
|
||||||
iinfo->i_location.logicalBlockNum, &err);
|
iinfo->i_location.logicalBlockNum, &err);
|
||||||
if (!block)
|
if (!block)
|
||||||
@ -923,17 +907,17 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
eloc.logicalBlockNum = block;
|
eloc.logicalBlockNum = block;
|
||||||
eloc.partitionReferenceNum =
|
eloc.partitionReferenceNum =
|
||||||
iinfo->i_location.partitionReferenceNum;
|
iinfo->i_location.partitionReferenceNum;
|
||||||
bsize = inode->i_sb->s_blocksize;
|
bsize = sb->s_blocksize;
|
||||||
iinfo->i_lenExtents = bsize;
|
iinfo->i_lenExtents = bsize;
|
||||||
udf_add_aext(inode, &epos, &eloc, bsize, 0);
|
udf_add_aext(inode, &epos, &eloc, bsize, 0);
|
||||||
brelse(epos.bh);
|
brelse(epos.bh);
|
||||||
|
|
||||||
block = udf_get_pblock(inode->i_sb, block,
|
block = udf_get_pblock(sb, block,
|
||||||
iinfo->i_location.partitionReferenceNum,
|
iinfo->i_location.partitionReferenceNum,
|
||||||
0);
|
0);
|
||||||
epos.bh = udf_tgetblk(inode->i_sb, block);
|
epos.bh = udf_tgetblk(sb, block);
|
||||||
lock_buffer(epos.bh);
|
lock_buffer(epos.bh);
|
||||||
memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
|
memset(epos.bh->b_data, 0x00, bsize);
|
||||||
set_buffer_uptodate(epos.bh);
|
set_buffer_uptodate(epos.bh);
|
||||||
unlock_buffer(epos.bh);
|
unlock_buffer(epos.bh);
|
||||||
mark_buffer_dirty_inode(epos.bh, inode);
|
mark_buffer_dirty_inode(epos.bh, inode);
|
||||||
@ -941,7 +925,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
} else
|
} else
|
||||||
ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
||||||
|
|
||||||
eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
|
eoffset = sb->s_blocksize - udf_ext0_offset(inode);
|
||||||
pc = (struct pathComponent *)ea;
|
pc = (struct pathComponent *)ea;
|
||||||
|
|
||||||
if (*symname == '/') {
|
if (*symname == '/') {
|
||||||
@ -981,7 +965,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pc->componentType == 5) {
|
if (pc->componentType == 5) {
|
||||||
namelen = udf_put_filename(inode->i_sb, compstart, name,
|
namelen = udf_put_filename(sb, compstart, name,
|
||||||
symname - compstart);
|
symname - compstart);
|
||||||
if (!namelen)
|
if (!namelen)
|
||||||
goto out_no_entry;
|
goto out_no_entry;
|
||||||
@ -1015,27 +999,16 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
||||||
if (!fi)
|
if (!fi)
|
||||||
goto out_no_entry;
|
goto out_no_entry;
|
||||||
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
|
||||||
cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
||||||
bh = UDF_SB(inode->i_sb)->s_lvid_bh;
|
if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
||||||
if (bh) {
|
|
||||||
struct logicalVolIntegrityDesc *lvid =
|
|
||||||
(struct logicalVolIntegrityDesc *)bh->b_data;
|
|
||||||
struct logicalVolHeaderDesc *lvhd;
|
|
||||||
uint64_t uniqueID;
|
|
||||||
lvhd = (struct logicalVolHeaderDesc *)
|
|
||||||
lvid->logicalVolContentsUse;
|
|
||||||
uniqueID = le64_to_cpu(lvhd->uniqueID);
|
|
||||||
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
||||||
cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
|
cpu_to_le32(lvid_get_unique_id(sb));
|
||||||
if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
|
||||||
uniqueID += 16;
|
|
||||||
lvhd->uniqueID = cpu_to_le64(uniqueID);
|
|
||||||
mark_buffer_dirty(bh);
|
|
||||||
}
|
}
|
||||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
||||||
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||||
mark_inode_dirty(dir);
|
mark_inode_dirty(dir);
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
if (fibh.sbh != fibh.ebh)
|
if (fibh.sbh != fibh.ebh)
|
||||||
brelse(fibh.ebh);
|
brelse(fibh.ebh);
|
||||||
brelse(fibh.sbh);
|
brelse(fibh.sbh);
|
||||||
@ -1044,10 +1017,10 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(name);
|
kfree(name);
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_no_entry:
|
out_no_entry:
|
||||||
|
up_write(&iinfo->i_data_sem);
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1060,36 +1033,20 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
|
|||||||
struct udf_fileident_bh fibh;
|
struct udf_fileident_bh fibh;
|
||||||
struct fileIdentDesc cfi, *fi;
|
struct fileIdentDesc cfi, *fi;
|
||||||
int err;
|
int err;
|
||||||
struct buffer_head *bh;
|
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {
|
if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {
|
||||||
unlock_kernel();
|
|
||||||
return -EMLINK;
|
return -EMLINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
||||||
if (!fi) {
|
if (!fi) {
|
||||||
unlock_kernel();
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
||||||
cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
|
cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
|
||||||
bh = UDF_SB(inode->i_sb)->s_lvid_bh;
|
if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
||||||
if (bh) {
|
|
||||||
struct logicalVolIntegrityDesc *lvid =
|
|
||||||
(struct logicalVolIntegrityDesc *)bh->b_data;
|
|
||||||
struct logicalVolHeaderDesc *lvhd;
|
|
||||||
uint64_t uniqueID;
|
|
||||||
lvhd = (struct logicalVolHeaderDesc *)
|
|
||||||
(lvid->logicalVolContentsUse);
|
|
||||||
uniqueID = le64_to_cpu(lvhd->uniqueID);
|
|
||||||
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
||||||
cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
|
cpu_to_le32(lvid_get_unique_id(inode->i_sb));
|
||||||
if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
|
||||||
uniqueID += 16;
|
|
||||||
lvhd->uniqueID = cpu_to_le64(uniqueID);
|
|
||||||
mark_buffer_dirty(bh);
|
|
||||||
}
|
}
|
||||||
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
||||||
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
||||||
@ -1103,7 +1060,6 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
|
|||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
ihold(inode);
|
ihold(inode);
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1124,7 +1080,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
struct kernel_lb_addr tloc;
|
struct kernel_lb_addr tloc;
|
||||||
struct udf_inode_info *old_iinfo = UDF_I(old_inode);
|
struct udf_inode_info *old_iinfo = UDF_I(old_inode);
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
|
ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
|
||||||
if (ofi) {
|
if (ofi) {
|
||||||
if (ofibh.sbh != ofibh.ebh)
|
if (ofibh.sbh != ofibh.ebh)
|
||||||
@ -1248,7 +1203,6 @@ end_rename:
|
|||||||
brelse(nfibh.ebh);
|
brelse(nfibh.ebh);
|
||||||
brelse(nfibh.sbh);
|
brelse(nfibh.sbh);
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -1261,7 +1215,6 @@ static struct dentry *udf_get_parent(struct dentry *child)
|
|||||||
struct fileIdentDesc cfi;
|
struct fileIdentDesc cfi;
|
||||||
struct udf_fileident_bh fibh;
|
struct udf_fileident_bh fibh;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
|
if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
@ -1273,11 +1226,9 @@ static struct dentry *udf_get_parent(struct dentry *child)
|
|||||||
inode = udf_iget(child->d_inode->i_sb, &tloc);
|
inode = udf_iget(child->d_inode->i_sb, &tloc);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return d_obtain_alias(inode);
|
return d_obtain_alias(inode);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
unlock_kernel();
|
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
|
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
|
||||||
uint16_t partition, uint32_t offset)
|
uint16_t partition, uint32_t offset)
|
||||||
@ -159,7 +160,9 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
|
|||||||
struct udf_sb_info *sbi = UDF_SB(sb);
|
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||||
u16 reallocationTableLen;
|
u16 reallocationTableLen;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
mutex_lock(&sbi->s_alloc_mutex);
|
||||||
for (i = 0; i < sbi->s_partitions; i++) {
|
for (i = 0; i < sbi->s_partitions; i++) {
|
||||||
struct udf_part_map *map = &sbi->s_partmaps[i];
|
struct udf_part_map *map = &sbi->s_partmaps[i];
|
||||||
if (old_block > map->s_partition_root &&
|
if (old_block > map->s_partition_root &&
|
||||||
@ -175,8 +178,10 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!st)
|
if (!st) {
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
reallocationTableLen =
|
reallocationTableLen =
|
||||||
le16_to_cpu(st->reallocationTableLen);
|
le16_to_cpu(st->reallocationTableLen);
|
||||||
@ -207,14 +212,16 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
|
|||||||
((old_block -
|
((old_block -
|
||||||
map->s_partition_root) &
|
map->s_partition_root) &
|
||||||
(sdata->s_packet_len - 1));
|
(sdata->s_packet_len - 1));
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
} else if (origLoc == packet) {
|
} else if (origLoc == packet) {
|
||||||
*new_block = le32_to_cpu(
|
*new_block = le32_to_cpu(
|
||||||
entry->mappedLocation) +
|
entry->mappedLocation) +
|
||||||
((old_block -
|
((old_block -
|
||||||
map->s_partition_root) &
|
map->s_partition_root) &
|
||||||
(sdata->s_packet_len - 1));
|
(sdata->s_packet_len - 1));
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
} else if (origLoc > packet)
|
} else if (origLoc > packet)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -251,20 +258,24 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
|
|||||||
st->mapEntry[k].mappedLocation) +
|
st->mapEntry[k].mappedLocation) +
|
||||||
((old_block - map->s_partition_root) &
|
((old_block - map->s_partition_root) &
|
||||||
(sdata->s_packet_len - 1));
|
(sdata->s_packet_len - 1));
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto out;
|
||||||
} /* if old_block */
|
} /* if old_block */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == sbi->s_partitions) {
|
if (i == sbi->s_partitions) {
|
||||||
/* outside of partitions */
|
/* outside of partitions */
|
||||||
/* for now, fail =) */
|
/* for now, fail =) */
|
||||||
return 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
mutex_unlock(&sbi->s_alloc_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
|
static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
|
||||||
|
@ -48,7 +48,6 @@
|
|||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/cdrom.h>
|
#include <linux/cdrom.h>
|
||||||
#include <linux/nls.h>
|
#include <linux/nls.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/vfs.h>
|
#include <linux/vfs.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
@ -135,6 +134,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb)
|
|||||||
ei->i_next_alloc_block = 0;
|
ei->i_next_alloc_block = 0;
|
||||||
ei->i_next_alloc_goal = 0;
|
ei->i_next_alloc_goal = 0;
|
||||||
ei->i_strat4096 = 0;
|
ei->i_strat4096 = 0;
|
||||||
|
init_rwsem(&ei->i_data_sem);
|
||||||
|
|
||||||
return &ei->vfs_inode;
|
return &ei->vfs_inode;
|
||||||
}
|
}
|
||||||
@ -574,13 +574,14 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
|
|||||||
if (!udf_parse_options(options, &uopt, true))
|
if (!udf_parse_options(options, &uopt, true))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
lock_kernel();
|
write_lock(&sbi->s_cred_lock);
|
||||||
sbi->s_flags = uopt.flags;
|
sbi->s_flags = uopt.flags;
|
||||||
sbi->s_uid = uopt.uid;
|
sbi->s_uid = uopt.uid;
|
||||||
sbi->s_gid = uopt.gid;
|
sbi->s_gid = uopt.gid;
|
||||||
sbi->s_umask = uopt.umask;
|
sbi->s_umask = uopt.umask;
|
||||||
sbi->s_fmode = uopt.fmode;
|
sbi->s_fmode = uopt.fmode;
|
||||||
sbi->s_dmode = uopt.dmode;
|
sbi->s_dmode = uopt.dmode;
|
||||||
|
write_unlock(&sbi->s_cred_lock);
|
||||||
|
|
||||||
if (sbi->s_lvid_bh) {
|
if (sbi->s_lvid_bh) {
|
||||||
int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
|
int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
|
||||||
@ -597,7 +598,6 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
|
|||||||
udf_open_lvid(sb);
|
udf_open_lvid(sb);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
unlock_kernel();
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,9 +966,9 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
|
|||||||
(sizeof(struct buffer_head *) * nr_groups);
|
(sizeof(struct buffer_head *) * nr_groups);
|
||||||
|
|
||||||
if (size <= PAGE_SIZE)
|
if (size <= PAGE_SIZE)
|
||||||
bitmap = kmalloc(size, GFP_KERNEL);
|
bitmap = kzalloc(size, GFP_KERNEL);
|
||||||
else
|
else
|
||||||
bitmap = vmalloc(size); /* TODO: get rid of vmalloc */
|
bitmap = vzalloc(size); /* TODO: get rid of vzalloc */
|
||||||
|
|
||||||
if (bitmap == NULL) {
|
if (bitmap == NULL) {
|
||||||
udf_error(sb, __func__,
|
udf_error(sb, __func__,
|
||||||
@ -977,7 +977,6 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(bitmap, 0x00, size);
|
|
||||||
bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1);
|
bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1);
|
||||||
bitmap->s_nr_groups = nr_groups;
|
bitmap->s_nr_groups = nr_groups;
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@ -1781,6 +1780,8 @@ static void udf_open_lvid(struct super_block *sb)
|
|||||||
|
|
||||||
if (!bh)
|
if (!bh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&sbi->s_alloc_mutex);
|
||||||
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
|
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
|
||||||
lvidiu = udf_sb_lvidiu(sbi);
|
lvidiu = udf_sb_lvidiu(sbi);
|
||||||
|
|
||||||
@ -1797,6 +1798,7 @@ static void udf_open_lvid(struct super_block *sb)
|
|||||||
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
|
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
sbi->s_lvid_dirty = 0;
|
sbi->s_lvid_dirty = 0;
|
||||||
|
mutex_unlock(&sbi->s_alloc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void udf_close_lvid(struct super_block *sb)
|
static void udf_close_lvid(struct super_block *sb)
|
||||||
@ -1809,6 +1811,7 @@ static void udf_close_lvid(struct super_block *sb)
|
|||||||
if (!bh)
|
if (!bh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&sbi->s_alloc_mutex);
|
||||||
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
|
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
|
||||||
lvidiu = udf_sb_lvidiu(sbi);
|
lvidiu = udf_sb_lvidiu(sbi);
|
||||||
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
|
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
|
||||||
@ -1829,6 +1832,34 @@ static void udf_close_lvid(struct super_block *sb)
|
|||||||
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
|
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
sbi->s_lvid_dirty = 0;
|
sbi->s_lvid_dirty = 0;
|
||||||
|
mutex_unlock(&sbi->s_alloc_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 lvid_get_unique_id(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct buffer_head *bh;
|
||||||
|
struct udf_sb_info *sbi = UDF_SB(sb);
|
||||||
|
struct logicalVolIntegrityDesc *lvid;
|
||||||
|
struct logicalVolHeaderDesc *lvhd;
|
||||||
|
u64 uniqueID;
|
||||||
|
u64 ret;
|
||||||
|
|
||||||
|
bh = sbi->s_lvid_bh;
|
||||||
|
if (!bh)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
|
||||||
|
lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse;
|
||||||
|
|
||||||
|
mutex_lock(&sbi->s_alloc_mutex);
|
||||||
|
ret = uniqueID = le64_to_cpu(lvhd->uniqueID);
|
||||||
|
if (!(++uniqueID & 0xFFFFFFFF))
|
||||||
|
uniqueID += 16;
|
||||||
|
lvhd->uniqueID = cpu_to_le64(uniqueID);
|
||||||
|
mutex_unlock(&sbi->s_alloc_mutex);
|
||||||
|
mark_buffer_dirty(bh);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
|
static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
|
||||||
@ -1886,8 +1917,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
|||||||
struct kernel_lb_addr rootdir, fileset;
|
struct kernel_lb_addr rootdir, fileset;
|
||||||
struct udf_sb_info *sbi;
|
struct udf_sb_info *sbi;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
|
uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
|
||||||
uopt.uid = -1;
|
uopt.uid = -1;
|
||||||
uopt.gid = -1;
|
uopt.gid = -1;
|
||||||
@ -1896,10 +1925,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
|||||||
uopt.dmode = UDF_INVALID_MODE;
|
uopt.dmode = UDF_INVALID_MODE;
|
||||||
|
|
||||||
sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
|
sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
|
||||||
if (!sbi) {
|
if (!sbi)
|
||||||
unlock_kernel();
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
sb->s_fs_info = sbi;
|
sb->s_fs_info = sbi;
|
||||||
|
|
||||||
@ -1936,6 +1963,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
|||||||
sbi->s_fmode = uopt.fmode;
|
sbi->s_fmode = uopt.fmode;
|
||||||
sbi->s_dmode = uopt.dmode;
|
sbi->s_dmode = uopt.dmode;
|
||||||
sbi->s_nls_map = uopt.nls_map;
|
sbi->s_nls_map = uopt.nls_map;
|
||||||
|
rwlock_init(&sbi->s_cred_lock);
|
||||||
|
|
||||||
if (uopt.session == 0xFFFFFFFF)
|
if (uopt.session == 0xFFFFFFFF)
|
||||||
sbi->s_session = udf_get_last_session(sb);
|
sbi->s_session = udf_get_last_session(sb);
|
||||||
@ -2045,7 +2073,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
|||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||||
unlock_kernel();
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_out:
|
error_out:
|
||||||
@ -2066,7 +2093,6 @@ error_out:
|
|||||||
kfree(sbi);
|
kfree(sbi);
|
||||||
sb->s_fs_info = NULL;
|
sb->s_fs_info = NULL;
|
||||||
|
|
||||||
unlock_kernel();
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2105,8 +2131,6 @@ static void udf_put_super(struct super_block *sb)
|
|||||||
|
|
||||||
sbi = UDF_SB(sb);
|
sbi = UDF_SB(sb);
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
if (sbi->s_vat_inode)
|
if (sbi->s_vat_inode)
|
||||||
iput(sbi->s_vat_inode);
|
iput(sbi->s_vat_inode);
|
||||||
if (sbi->s_partitions)
|
if (sbi->s_partitions)
|
||||||
@ -2122,8 +2146,6 @@ static void udf_put_super(struct super_block *sb)
|
|||||||
kfree(sbi->s_partmaps);
|
kfree(sbi->s_partmaps);
|
||||||
kfree(sb->s_fs_info);
|
kfree(sb->s_fs_info);
|
||||||
sb->s_fs_info = NULL;
|
sb->s_fs_info = NULL;
|
||||||
|
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udf_sync_fs(struct super_block *sb, int wait)
|
static int udf_sync_fs(struct super_block *sb, int wait)
|
||||||
@ -2186,8 +2208,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
|
|||||||
uint16_t ident;
|
uint16_t ident;
|
||||||
struct spaceBitmapDesc *bm;
|
struct spaceBitmapDesc *bm;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
|
|
||||||
loc.logicalBlockNum = bitmap->s_extPosition;
|
loc.logicalBlockNum = bitmap->s_extPosition;
|
||||||
loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
|
loc.partitionReferenceNum = UDF_SB(sb)->s_partition;
|
||||||
bh = udf_read_ptagged(sb, &loc, 0, &ident);
|
bh = udf_read_ptagged(sb, &loc, 0, &ident);
|
||||||
@ -2224,10 +2244,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return accum;
|
return accum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2240,8 +2257,7 @@ static unsigned int udf_count_free_table(struct super_block *sb,
|
|||||||
int8_t etype;
|
int8_t etype;
|
||||||
struct extent_position epos;
|
struct extent_position epos;
|
||||||
|
|
||||||
lock_kernel();
|
mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
|
||||||
|
|
||||||
epos.block = UDF_I(table)->i_location;
|
epos.block = UDF_I(table)->i_location;
|
||||||
epos.offset = sizeof(struct unallocSpaceEntry);
|
epos.offset = sizeof(struct unallocSpaceEntry);
|
||||||
epos.bh = NULL;
|
epos.bh = NULL;
|
||||||
@ -2250,8 +2266,7 @@ static unsigned int udf_count_free_table(struct super_block *sb,
|
|||||||
accum += (elen >> table->i_sb->s_blocksize_bits);
|
accum += (elen >> table->i_sb->s_blocksize_bits);
|
||||||
|
|
||||||
brelse(epos.bh);
|
brelse(epos.bh);
|
||||||
|
mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
|
||||||
unlock_kernel();
|
|
||||||
|
|
||||||
return accum;
|
return accum;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include "udf_i.h"
|
#include "udf_i.h"
|
||||||
|
|
||||||
@ -78,13 +77,16 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
|||||||
int err = -EIO;
|
int err = -EIO;
|
||||||
unsigned char *p = kmap(page);
|
unsigned char *p = kmap(page);
|
||||||
struct udf_inode_info *iinfo;
|
struct udf_inode_info *iinfo;
|
||||||
|
uint32_t pos;
|
||||||
|
|
||||||
lock_kernel();
|
|
||||||
iinfo = UDF_I(inode);
|
iinfo = UDF_I(inode);
|
||||||
|
pos = udf_block_map(inode, 0);
|
||||||
|
|
||||||
|
down_read(&iinfo->i_data_sem);
|
||||||
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
||||||
symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
||||||
} else {
|
} else {
|
||||||
bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
|
bh = sb_bread(inode->i_sb, pos);
|
||||||
|
|
||||||
if (!bh)
|
if (!bh)
|
||||||
goto out;
|
goto out;
|
||||||
@ -95,14 +97,14 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
|||||||
udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
|
udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
unlock_kernel();
|
up_read(&iinfo->i_data_sem);
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_kernel();
|
up_read(&iinfo->i_data_sem);
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
#ifndef _UDF_I_H
|
#ifndef _UDF_I_H
|
||||||
#define _UDF_I_H
|
#define _UDF_I_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The i_data_sem and i_mutex serve for protection of allocation information
|
||||||
|
* of a regular files and symlinks. This includes all extents belonging to
|
||||||
|
* the file/symlink, a fact whether data are in-inode or in external data
|
||||||
|
* blocks, preallocation, goal block information... When extents are read,
|
||||||
|
* i_mutex or i_data_sem must be held (for reading is enough in case of
|
||||||
|
* i_data_sem). When extents are changed, i_data_sem must be held for writing
|
||||||
|
* and also i_mutex must be held.
|
||||||
|
*
|
||||||
|
* For directories i_mutex is used for all the necessary protection.
|
||||||
|
*/
|
||||||
|
|
||||||
struct udf_inode_info {
|
struct udf_inode_info {
|
||||||
struct timespec i_crtime;
|
struct timespec i_crtime;
|
||||||
/* Physical address of inode */
|
/* Physical address of inode */
|
||||||
@ -21,6 +33,7 @@ struct udf_inode_info {
|
|||||||
struct long_ad *i_lad;
|
struct long_ad *i_lad;
|
||||||
__u8 *i_data;
|
__u8 *i_data;
|
||||||
} i_ext;
|
} i_ext;
|
||||||
|
struct rw_semaphore i_data_sem;
|
||||||
struct inode vfs_inode;
|
struct inode vfs_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __LINUX_UDF_SB_H
|
#define __LINUX_UDF_SB_H
|
||||||
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
/* Since UDF 2.01 is ISO 13346 based... */
|
/* Since UDF 2.01 is ISO 13346 based... */
|
||||||
#define UDF_SUPER_MAGIC 0x15013346
|
#define UDF_SUPER_MAGIC 0x15013346
|
||||||
@ -128,6 +129,8 @@ struct udf_sb_info {
|
|||||||
uid_t s_uid;
|
uid_t s_uid;
|
||||||
mode_t s_fmode;
|
mode_t s_fmode;
|
||||||
mode_t s_dmode;
|
mode_t s_dmode;
|
||||||
|
/* Lock protecting consistency of above permission settings */
|
||||||
|
rwlock_t s_cred_lock;
|
||||||
|
|
||||||
/* Root Info */
|
/* Root Info */
|
||||||
struct timespec s_record_time;
|
struct timespec s_record_time;
|
||||||
@ -139,7 +142,7 @@ struct udf_sb_info {
|
|||||||
__u16 s_udfrev;
|
__u16 s_udfrev;
|
||||||
|
|
||||||
/* Miscellaneous flags */
|
/* Miscellaneous flags */
|
||||||
__u32 s_flags;
|
unsigned long s_flags;
|
||||||
|
|
||||||
/* Encoding info */
|
/* Encoding info */
|
||||||
struct nls_table *s_nls_map;
|
struct nls_table *s_nls_map;
|
||||||
@ -161,8 +164,19 @@ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi);
|
|||||||
|
|
||||||
int udf_compute_nr_groups(struct super_block *sb, u32 partition);
|
int udf_compute_nr_groups(struct super_block *sb, u32 partition);
|
||||||
|
|
||||||
#define UDF_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
|
static inline int UDF_QUERY_FLAG(struct super_block *sb, int flag)
|
||||||
#define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
|
{
|
||||||
#define UDF_CLEAR_FLAG(X,Y) ( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) )
|
return test_bit(flag, &UDF_SB(sb)->s_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void UDF_SET_FLAG(struct super_block *sb, int flag)
|
||||||
|
{
|
||||||
|
set_bit(flag, &UDF_SB(sb)->s_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void UDF_CLEAR_FLAG(struct super_block *sb, int flag)
|
||||||
|
{
|
||||||
|
clear_bit(flag, &UDF_SB(sb)->s_flags);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __LINUX_UDF_SB_H */
|
#endif /* __LINUX_UDF_SB_H */
|
||||||
|
@ -111,6 +111,8 @@ struct extent_position {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* super.c */
|
/* super.c */
|
||||||
|
|
||||||
|
__attribute__((format(printf, 3, 4)))
|
||||||
extern void udf_warning(struct super_block *, const char *, const char *, ...);
|
extern void udf_warning(struct super_block *, const char *, const char *, ...);
|
||||||
static inline void udf_updated_lvid(struct super_block *sb)
|
static inline void udf_updated_lvid(struct super_block *sb)
|
||||||
{
|
{
|
||||||
@ -123,6 +125,7 @@ static inline void udf_updated_lvid(struct super_block *sb)
|
|||||||
sb->s_dirt = 1;
|
sb->s_dirt = 1;
|
||||||
UDF_SB(sb)->s_lvid_dirty = 1;
|
UDF_SB(sb)->s_lvid_dirty = 1;
|
||||||
}
|
}
|
||||||
|
extern u64 lvid_get_unique_id(struct super_block *sb);
|
||||||
|
|
||||||
/* namei.c */
|
/* namei.c */
|
||||||
extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
|
extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
|
||||||
@ -133,7 +136,6 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
|
|||||||
extern long udf_ioctl(struct file *, unsigned int, unsigned long);
|
extern long udf_ioctl(struct file *, unsigned int, unsigned long);
|
||||||
/* inode.c */
|
/* inode.c */
|
||||||
extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
|
extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
|
||||||
extern int udf_sync_inode(struct inode *);
|
|
||||||
extern void udf_expand_file_adinicb(struct inode *, int, int *);
|
extern void udf_expand_file_adinicb(struct inode *, int, int *);
|
||||||
extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
|
extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
|
||||||
extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
|
extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
|
||||||
|
Loading…
Reference in New Issue
Block a user