From 6fb1ca92a6409a9d5b0696447cd4997bc9aaf5a2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 9 Sep 2014 13:03:03 +0200 Subject: udf: Fix race between write(2) and close(2) Currently write(2) updating i_size and close(2) of the file can race in such a way that udf_truncate_tail_extent() called from udf_file_release() sees old i_size but already new extents added by the running write call. This results in complaints like: UDF-fs: warning (device vdb2): udf_truncate_tail_extent: Too long extent after EOF in inode 877: i_size: 0 lbcount: 1073739776 extent 0+1073739776 UDF-fs: error (device vdb2): udf_truncate_tail_extent: Extent after EOF in inode 877 Fix the problem by grabbing i_mutex in udf_file_release() to be sure i_size is consistent with current state of extent list. Also avoid truncating tail extent unnecessarily when the file is still open for writing. Signed-off-by: Jan Kara diff --git a/fs/udf/file.c b/fs/udf/file.c index 86c6743..bb15771 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -223,11 +223,18 @@ out: static int udf_release_file(struct inode *inode, struct file *filp) { - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE && + atomic_read(&inode->i_writecount) > 1) { + /* + * Grab i_mutex to avoid races with writes changing i_size + * while we are running. + */ + mutex_lock(&inode->i_mutex); down_write(&UDF_I(inode)->i_data_sem); udf_discard_prealloc(inode); udf_truncate_tail_extent(inode); up_write(&UDF_I(inode)->i_data_sem); + mutex_unlock(&inode->i_mutex); } return 0; } -- cgit v0.10.2 From a93114e4688f8ff7aba3a1012f17cfadc054d08b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Sep 2014 20:48:02 +0200 Subject: ext3: Don't use MAXQUOTAS value MAXQUOTAS value defines maximum number of quota types VFS supports. This isn't necessarily the number of types ext3 supports and with addition of project quotas these two numbers stop matching. So make ext3 use its private definition. CC: linux-ext4@vger.kernel.org Signed-off-by: Jan Kara diff --git a/fs/ext3/ext3.h b/fs/ext3/ext3.h index e85ff15..fc3cdcf 100644 --- a/fs/ext3/ext3.h +++ b/fs/ext3/ext3.h @@ -237,6 +237,8 @@ struct ext3_new_group_data { #define EXT3_IOC32_GETVERSION_OLD FS_IOC32_GETVERSION #define EXT3_IOC32_SETVERSION_OLD FS_IOC32_SETVERSION +/* Number of supported quota types */ +#define EXT3_MAXQUOTAS 2 /* * Mount options @@ -248,7 +250,7 @@ struct ext3_mount_options { unsigned long s_commit_interval; #ifdef CONFIG_QUOTA int s_jquota_fmt; - char *s_qf_names[MAXQUOTAS]; + char *s_qf_names[EXT3_MAXQUOTAS]; #endif }; @@ -669,7 +671,7 @@ struct ext3_sb_info { unsigned long s_commit_interval; struct block_device *journal_bdev; #ifdef CONFIG_QUOTA - char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */ + char *s_qf_names[EXT3_MAXQUOTAS]; /* Names of quota files with journalled quota */ int s_jquota_fmt; /* Format of quota to use */ #endif }; @@ -1183,9 +1185,9 @@ extern const struct inode_operations ext3_fast_symlink_inode_operations; #define EXT3_QUOTA_INIT_BLOCKS(sb) 0 #define EXT3_QUOTA_DEL_BLOCKS(sb) 0 #endif -#define EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_TRANS_BLOCKS(sb)) -#define EXT3_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_INIT_BLOCKS(sb)) -#define EXT3_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT3_QUOTA_DEL_BLOCKS(sb)) +#define EXT3_MAXQUOTAS_TRANS_BLOCKS(sb) (EXT3_MAXQUOTAS*EXT3_QUOTA_TRANS_BLOCKS(sb)) +#define EXT3_MAXQUOTAS_INIT_BLOCKS(sb) (EXT3_MAXQUOTAS*EXT3_QUOTA_INIT_BLOCKS(sb)) +#define EXT3_MAXQUOTAS_DEL_BLOCKS(sb) (EXT3_MAXQUOTAS*EXT3_QUOTA_DEL_BLOCKS(sb)) int ext3_mark_iloc_dirty(handle_t *handle, diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 622e882..b79f04b 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -441,7 +441,7 @@ static void ext3_put_super (struct super_block * sb) percpu_counter_destroy(&sbi->s_dirs_counter); brelse(sbi->s_sbh); #ifdef CONFIG_QUOTA - for (i = 0; i < MAXQUOTAS; i++) + for (i = 0; i < EXT3_MAXQUOTAS; i++) kfree(sbi->s_qf_names[i]); #endif @@ -1555,7 +1555,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, /* Needed for iput() to work correctly and not trash data */ sb->s_flags |= MS_ACTIVE; /* Turn on quotas so that they are updated correctly */ - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < EXT3_MAXQUOTAS; i++) { if (EXT3_SB(sb)->s_qf_names[i]) { int ret = ext3_quota_on_mount(sb, i); if (ret < 0) @@ -1606,7 +1606,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, PLURAL(nr_truncates)); #ifdef CONFIG_QUOTA /* Turn quotas off */ - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < EXT3_MAXQUOTAS; i++) { if (sb_dqopt(sb)->files[i]) dquot_quota_off(sb, i); } @@ -2139,7 +2139,7 @@ failed_mount2: kfree(sbi->s_group_desc); failed_mount: #ifdef CONFIG_QUOTA - for (i = 0; i < MAXQUOTAS; i++) + for (i = 0; i < EXT3_MAXQUOTAS; i++) kfree(sbi->s_qf_names[i]); #endif ext3_blkdev_remove(sbi); @@ -2659,7 +2659,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) old_opts.s_commit_interval = sbi->s_commit_interval; #ifdef CONFIG_QUOTA old_opts.s_jquota_fmt = sbi->s_jquota_fmt; - for (i = 0; i < MAXQUOTAS; i++) + for (i = 0; i < EXT3_MAXQUOTAS; i++) if (sbi->s_qf_names[i]) { old_opts.s_qf_names[i] = kstrdup(sbi->s_qf_names[i], GFP_KERNEL); @@ -2763,7 +2763,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) } #ifdef CONFIG_QUOTA /* Release old quota file names */ - for (i = 0; i < MAXQUOTAS; i++) + for (i = 0; i < EXT3_MAXQUOTAS; i++) kfree(old_opts.s_qf_names[i]); #endif if (enable_quota) @@ -2777,7 +2777,7 @@ restore_opts: sbi->s_commit_interval = old_opts.s_commit_interval; #ifdef CONFIG_QUOTA sbi->s_jquota_fmt = old_opts.s_jquota_fmt; - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < EXT3_MAXQUOTAS; i++) { kfree(sbi->s_qf_names[i]); sbi->s_qf_names[i] = old_opts.s_qf_names[i]; } -- cgit v0.10.2 From aca60617738334be3e8e0daa48be06844ce9e9fd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Sep 2014 20:57:45 +0200 Subject: reiserfs: Don't use MAXQUOTAS value MAXQUOTAS value defines maximum number of quota types VFS supports. This isn't necessarily the number of types reiserfs supports and with addition of project quotas these two numbers stop matching. So make reiserfs use its private definition. CC: reiserfs-devel@vger.kernel.org CC: Jeff Mahoney Signed-off-by: Jan Kara diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index 735c2c2..1894d96 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h @@ -506,6 +506,9 @@ typedef struct reiserfs_proc_info_data { } reiserfs_proc_info_data_t; #endif +/* Number of quota types we support */ +#define REISERFS_MAXQUOTAS 2 + /* reiserfs union of in-core super block data */ struct reiserfs_sb_info { /* Buffer containing the super block */ @@ -615,7 +618,7 @@ struct reiserfs_sb_info { spinlock_t old_work_lock; /* protects old_work and work_queued */ #ifdef CONFIG_QUOTA - char *s_qf_names[MAXQUOTAS]; + char *s_qf_names[REISERFS_MAXQUOTAS]; int s_jquota_fmt; #endif char *s_jdev; /* Stored jdev for mount option showing */ diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d46e88a..f1376c9 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -206,7 +206,7 @@ static int finish_unfinished(struct super_block *s) #ifdef CONFIG_QUOTA int i; int ms_active_set; - int quota_enabled[MAXQUOTAS]; + int quota_enabled[REISERFS_MAXQUOTAS]; #endif /* compose key to look for "save" links */ @@ -227,7 +227,7 @@ static int finish_unfinished(struct super_block *s) s->s_flags |= MS_ACTIVE; } /* Turn on quotas so that they are updated correctly */ - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < REISERFS_MAXQUOTAS; i++) { quota_enabled[i] = 1; if (REISERFS_SB(s)->s_qf_names[i]) { int ret; @@ -370,7 +370,7 @@ static int finish_unfinished(struct super_block *s) #ifdef CONFIG_QUOTA /* Turn quotas off */ reiserfs_write_unlock(s); - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < REISERFS_MAXQUOTAS; i++) { if (sb_dqopt(s)->files[i] && quota_enabled[i]) dquot_quota_off(s, i); } @@ -1360,7 +1360,7 @@ static void handle_quota_files(struct super_block *s, char **qf_names, { int i; - for (i = 0; i < MAXQUOTAS; i++) { + for (i = 0; i < REISERFS_MAXQUOTAS; i++) { if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) kfree(REISERFS_SB(s)->s_qf_names[i]); REISERFS_SB(s)->s_qf_names[i] = qf_names[i]; @@ -1381,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) struct reiserfs_journal *journal = SB_JOURNAL(s); char *new_opts = kstrdup(arg, GFP_KERNEL); int err; - char *qf_names[MAXQUOTAS]; + char *qf_names[REISERFS_MAXQUOTAS]; unsigned int qfmt = 0; #ifdef CONFIG_QUOTA int i; @@ -1400,7 +1400,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) (s, arg, &mount_options, &blocks, NULL, &commit_max_age, qf_names, &qfmt)) { #ifdef CONFIG_QUOTA - for (i = 0; i < MAXQUOTAS; i++) + for (i = 0; i < REISERFS_MAXQUOTAS; i++) if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) kfree(qf_names[i]); #endif @@ -1844,7 +1844,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) char *jdev_name; struct reiserfs_sb_info *sbi; int errval = -EINVAL; - char *qf_names[MAXQUOTAS] = {}; + char *qf_names[REISERFS_MAXQUOTAS] = {}; unsigned int qfmt = 0; save_mount_options(s, data); @@ -2169,7 +2169,7 @@ error_unlocked: #ifdef CONFIG_QUOTA { int j; - for (j = 0; j < MAXQUOTAS; j++) + for (j = 0; j < REISERFS_MAXQUOTAS; j++) kfree(qf_names[j]); } #endif -- cgit v0.10.2 From 52362810bec8a912324169920cced021e3887b3e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Sep 2014 21:06:39 +0200 Subject: ocfs2: Don't use MAXQUOTAS value MAXQUOTAS value defines maximum number of quota types VFS supports. This isn't necessarily the number of types ocfs2 supports and with addition of project quotas these two numbers stop matching. So make ocfs2 use its private definition. CC: Mark Fasheh CC: Joel Becker CC: ocfs2-devel@oss.oracle.com Signed-off-by: Jan Kara diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 2930e23..0a8619a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1125,7 +1125,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct ocfs2_super *osb = OCFS2_SB(sb); struct buffer_head *bh = NULL; handle_t *handle = NULL; - struct dquot *transfer_to[MAXQUOTAS] = { }; + struct dquot *transfer_to[OCFS2_MAXQUOTAS] = { }; int qtype; trace_ocfs2_setattr(inode, dentry, @@ -1253,7 +1253,7 @@ bail: brelse(bh); /* Release quota pointers in case we acquired them */ - for (qtype = 0; qtype < MAXQUOTAS; qtype++) + for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++) dqput(transfer_to[qtype]); if (!status && attr->ia_valid & ATTR_MODE) { diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h index f266d67..1eae330 100644 --- a/fs/ocfs2/quota.h +++ b/fs/ocfs2/quota.h @@ -17,6 +17,9 @@ #include "ocfs2.h" +/* Number of quota types we support */ +#define OCFS2_MAXQUOTAS 2 + /* * In-memory structures */ @@ -39,7 +42,7 @@ struct ocfs2_recovery_chunk { }; struct ocfs2_quota_recovery { - struct list_head r_list[MAXQUOTAS]; /* List of chunks to recover */ + struct list_head r_list[OCFS2_MAXQUOTAS]; /* List of chunks to recover */ }; /* In-memory structure with quota header information */ diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index b990a62..c93d6722 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -336,8 +336,8 @@ void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex) int ocfs2_global_read_info(struct super_block *sb, int type) { struct inode *gqinode = NULL; - unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, - GROUP_QUOTA_SYSTEM_INODE }; + unsigned int ino[OCFS2_MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, + GROUP_QUOTA_SYSTEM_INODE }; struct ocfs2_global_disk_dqinfo dinfo; struct mem_dqinfo *info = sb_dqinfo(sb, type); struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv; diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 2001862..10b6539 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -166,12 +166,12 @@ static int ocfs2_read_quota_block(struct inode *inode, u64 v_block, /* Check whether we understand format of quota files */ static int ocfs2_local_check_quota_file(struct super_block *sb, int type) { - unsigned int lmagics[MAXQUOTAS] = OCFS2_LOCAL_QMAGICS; - unsigned int lversions[MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS; - unsigned int gmagics[MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS; - unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS; - unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, - GROUP_QUOTA_SYSTEM_INODE }; + unsigned int lmagics[OCFS2_MAXQUOTAS] = OCFS2_LOCAL_QMAGICS; + unsigned int lversions[OCFS2_MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS; + unsigned int gmagics[OCFS2_MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS; + unsigned int gversions[OCFS2_MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS; + unsigned int ino[OCFS2_MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE, + GROUP_QUOTA_SYSTEM_INODE }; struct buffer_head *bh = NULL; struct inode *linode = sb_dqopt(sb)->files[type]; struct inode *ginode = NULL; @@ -336,7 +336,7 @@ void ocfs2_free_quota_recovery(struct ocfs2_quota_recovery *rec) { int type; - for (type = 0; type < MAXQUOTAS; type++) + for (type = 0; type < OCFS2_MAXQUOTAS; type++) free_recovery_list(&(rec->r_list[type])); kfree(rec); } @@ -382,7 +382,7 @@ static struct ocfs2_quota_recovery *ocfs2_alloc_quota_recovery(void) rec = kmalloc(sizeof(struct ocfs2_quota_recovery), GFP_NOFS); if (!rec) return NULL; - for (type = 0; type < MAXQUOTAS; type++) + for (type = 0; type < OCFS2_MAXQUOTAS; type++) INIT_LIST_HEAD(&(rec->r_list[type])); return rec; } @@ -392,10 +392,11 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery( struct ocfs2_super *osb, int slot_num) { - unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; - unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, - LOCAL_GROUP_QUOTA_SYSTEM_INODE }; + unsigned int feature[OCFS2_MAXQUOTAS] = { + OCFS2_FEATURE_RO_COMPAT_USRQUOTA, + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; + unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, + LOCAL_GROUP_QUOTA_SYSTEM_INODE }; struct super_block *sb = osb->sb; struct ocfs2_local_disk_dqinfo *ldinfo; struct inode *lqinode; @@ -412,7 +413,7 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery( return ERR_PTR(-ENOMEM); /* First init... */ - for (type = 0; type < MAXQUOTAS; type++) { + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) continue; /* At this point, journal of the slot is already replayed so @@ -589,8 +590,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, struct ocfs2_quota_recovery *rec, int slot_num) { - unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, - LOCAL_GROUP_QUOTA_SYSTEM_INODE }; + unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, + LOCAL_GROUP_QUOTA_SYSTEM_INODE }; struct super_block *sb = osb->sb; struct ocfs2_local_disk_dqinfo *ldinfo; struct buffer_head *bh; @@ -604,7 +605,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, "slot %u\n", osb->dev_str, slot_num); mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); - for (type = 0; type < MAXQUOTAS; type++) { + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (list_empty(&(rec->r_list[type]))) continue; trace_ocfs2_finish_quota_recovery(slot_num); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index ddb662b..aa35d63 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -899,11 +899,12 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend) { int type; struct super_block *sb = osb->sb; - unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; + unsigned int feature[OCFS2_MAXQUOTAS] = { + OCFS2_FEATURE_RO_COMPAT_USRQUOTA, + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; int status = 0; - for (type = 0; type < MAXQUOTAS; type++) { + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) continue; if (unsuspend) @@ -927,17 +928,19 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend) static int ocfs2_enable_quotas(struct ocfs2_super *osb) { - struct inode *inode[MAXQUOTAS] = { NULL, NULL }; + struct inode *inode[OCFS2_MAXQUOTAS] = { NULL, NULL }; struct super_block *sb = osb->sb; - unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; - unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, + unsigned int feature[OCFS2_MAXQUOTAS] = { + OCFS2_FEATURE_RO_COMPAT_USRQUOTA, + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; + unsigned int ino[OCFS2_MAXQUOTAS] = { + LOCAL_USER_QUOTA_SYSTEM_INODE, LOCAL_GROUP_QUOTA_SYSTEM_INODE }; int status; int type; sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE; - for (type = 0; type < MAXQUOTAS; type++) { + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) continue; inode[type] = ocfs2_get_system_file_inode(osb, ino[type], @@ -952,12 +955,12 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb) goto out_quota_off; } - for (type = 0; type < MAXQUOTAS; type++) + for (type = 0; type < OCFS2_MAXQUOTAS; type++) iput(inode[type]); return 0; out_quota_off: ocfs2_disable_quotas(osb); - for (type = 0; type < MAXQUOTAS; type++) + for (type = 0; type < OCFS2_MAXQUOTAS; type++) iput(inode[type]); mlog_errno(status); return status; @@ -972,7 +975,7 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) /* We mostly ignore errors in this function because there's not much * we can do when we see them */ - for (type = 0; type < MAXQUOTAS; type++) { + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { if (!sb_has_quota_loaded(sb, type)) continue; /* Cancel periodic syncing before we grab dqonoff_mutex */ @@ -993,8 +996,9 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) /* Handle quota on quotactl */ static int ocfs2_quota_on(struct super_block *sb, int type, int format_id) { - unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, - OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; + unsigned int feature[OCFS2_MAXQUOTAS] = { + OCFS2_FEATURE_RO_COMPAT_USRQUOTA, + OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) return -EINVAL; -- cgit v0.10.2 From 37993271cfa22b5620304f1fa3bf72eabb5b557b Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Sat, 27 Sep 2014 18:14:47 +0200 Subject: udf: remove redundant sys_tz declaration sys_tz is already declared in include/linux/time.h Cc: Jan Kara Signed-off-by: Fabian Frederick Signed-off-by: Jan Kara diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 1f11483..77c331f 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -81,8 +81,6 @@ static time_t year_seconds[MAX_YEAR_SECONDS] = { /*2038*/ SPY(68, 17, 0) }; -extern struct timezone sys_tz; - #define SECS_PER_HOUR (60 * 60) #define SECS_PER_DAY (SECS_PER_HOUR * 24) -- cgit v0.10.2 From c53f755d339b5546600c316333140d5fe958941d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 30 Sep 2014 18:07:08 +0200 Subject: ocfs2: Back out change to use OCFS2_MAXQUOTAS in ocfs2_setattr() ocfs2_setattr() actually needs to really use MAXQUOTAS and not OCFS2_MAXQUOTAS since it will pass the array over to VFS. Currently this isn't a problem since MAXQUOTAS == OCFS2_MAXQUOTAS but it would be once we introduce project quotas. CC: Mark Fasheh CC: Joel Becker CC: ocfs2-devel@oss.oracle.com Signed-off-by: Jan Kara diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 0a8619a..f39482e 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1125,7 +1125,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct ocfs2_super *osb = OCFS2_SB(sb); struct buffer_head *bh = NULL; handle_t *handle = NULL; - struct dquot *transfer_to[OCFS2_MAXQUOTAS] = { }; + struct dquot *transfer_to[MAXQUOTAS] = { }; int qtype; trace_ocfs2_setattr(inode, dentry, -- cgit v0.10.2 From 6174c2eb8ecef271159bdcde460ce8af54d8f72f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 9 Oct 2014 12:52:16 +0200 Subject: udf: Fix loading of special inodes Some UDF media have special inodes (like VAT or metadata partition inodes) whose link_count is 0. Thus commit 4071b9136223 (udf: Properly detect stale inodes) broke loading these inodes because udf_iget() started returning -ESTALE for them. Since we still need to properly detect stale inodes queried by NFS, create two variants of udf_iget() - one which is used for looking up special inodes (which ignores link_count == 0) and one which is used for other cases which return ESTALE when link_count == 0. Fixes: 4071b913622316970d0e1919f7d82b4403fec5f2 CC: stable@vger.kernel.org Signed-off-by: Jan Kara diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 0859884..c9b4df5 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1277,7 +1277,7 @@ update_time: */ #define UDF_MAX_ICB_NESTING 1024 -static int udf_read_inode(struct inode *inode) +static int udf_read_inode(struct inode *inode, bool hidden_inode) { struct buffer_head *bh = NULL; struct fileEntry *fe; @@ -1436,8 +1436,11 @@ reread: link_count = le16_to_cpu(fe->fileLinkCount); if (!link_count) { - ret = -ESTALE; - goto out; + if (!hidden_inode) { + ret = -ESTALE; + goto out; + } + link_count = 1; } set_nlink(inode, link_count); @@ -1826,7 +1829,8 @@ out: return err; } -struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) +struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino, + bool hidden_inode) { unsigned long block = udf_get_lb_pblock(sb, ino, 0); struct inode *inode = iget_locked(sb, block); @@ -1839,7 +1843,7 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) return inode; memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); - err = udf_read_inode(inode); + err = udf_read_inode(inode, hidden_inode); if (err < 0) { iget_failed(inode); return ERR_PTR(err); diff --git a/fs/udf/super.c b/fs/udf/super.c index 5401fc3..e229315 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -959,7 +959,7 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb, addr.logicalBlockNum = meta_file_loc; addr.partitionReferenceNum = partition_num; - metadata_fe = udf_iget(sb, &addr); + metadata_fe = udf_iget_special(sb, &addr); if (IS_ERR(metadata_fe)) { udf_warn(sb, "metadata inode efe not found\n"); @@ -1020,7 +1020,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) udf_debug("Bitmap file location: block = %d part = %d\n", addr.logicalBlockNum, addr.partitionReferenceNum); - fe = udf_iget(sb, &addr); + fe = udf_iget_special(sb, &addr); if (IS_ERR(fe)) { if (sb->s_flags & MS_RDONLY) udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n"); @@ -1119,7 +1119,7 @@ static int udf_fill_partdesc_info(struct super_block *sb, }; struct inode *inode; - inode = udf_iget(sb, &loc); + inode = udf_iget_special(sb, &loc); if (IS_ERR(inode)) { udf_debug("cannot load unallocSpaceTable (part %d)\n", p_index); @@ -1154,7 +1154,7 @@ static int udf_fill_partdesc_info(struct super_block *sb, }; struct inode *inode; - inode = udf_iget(sb, &loc); + inode = udf_iget_special(sb, &loc); if (IS_ERR(inode)) { udf_debug("cannot load freedSpaceTable (part %d)\n", p_index); @@ -1198,7 +1198,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index, vat_block >= map->s_partition_root && vat_block >= start_block - 3; vat_block--) { ino.logicalBlockNum = vat_block - map->s_partition_root; - inode = udf_iget(sb, &ino); + inode = udf_iget_special(sb, &ino); if (!IS_ERR(inode)) { sbi->s_vat_inode = inode; break; diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 742557b..1cc3c99 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -138,7 +138,18 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, /* file.c */ extern long udf_ioctl(struct file *, unsigned int, unsigned long); /* 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 *, + bool hidden_inode); +static inline struct inode *udf_iget_special(struct super_block *sb, + struct kernel_lb_addr *ino) +{ + return __udf_iget(sb, ino, true); +} +static inline struct inode *udf_iget(struct super_block *sb, + struct kernel_lb_addr *ino) +{ + return __udf_iget(sb, ino, false); +} extern int udf_expand_file_adinicb(struct inode *); extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head *udf_bread(struct inode *, int, int, int *); -- cgit v0.10.2