~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to fs/adfs/inode.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * it under the terms of the GNU General Public License version 2 as
8
8
 * published by the Free Software Foundation.
9
9
 */
10
 
#include <linux/smp_lock.h>
11
10
#include <linux/buffer_head.h>
12
11
#include <linux/writeback.h>
13
12
#include "adfs.h"
73
72
static const struct address_space_operations adfs_aops = {
74
73
        .readpage       = adfs_readpage,
75
74
        .writepage      = adfs_writepage,
76
 
        .sync_page      = block_sync_page,
77
75
        .write_begin    = adfs_write_begin,
78
76
        .write_end      = generic_write_end,
79
77
        .bmap           = _adfs_bmap
80
78
};
81
79
 
82
 
static inline unsigned int
83
 
adfs_filetype(struct inode *inode)
84
 
{
85
 
        unsigned int type;
86
 
 
87
 
        if (ADFS_I(inode)->stamped)
88
 
                type = (ADFS_I(inode)->loadaddr >> 8) & 0xfff;
89
 
        else
90
 
                type = (unsigned int) -1;
91
 
 
92
 
        return type;
93
 
}
94
 
 
95
80
/*
96
81
 * Convert ADFS attributes and filetype to Linux permission.
97
82
 */
98
83
static umode_t
99
84
adfs_atts2mode(struct super_block *sb, struct inode *inode)
100
85
{
101
 
        unsigned int filetype, attr = ADFS_I(inode)->attr;
 
86
        unsigned int attr = ADFS_I(inode)->attr;
102
87
        umode_t mode, rmask;
103
88
        struct adfs_sb_info *asb = ADFS_SB(sb);
104
89
 
107
92
                return S_IFDIR | S_IXUGO | mode;
108
93
        }
109
94
 
110
 
        filetype = adfs_filetype(inode);
111
 
 
112
 
        switch (filetype) {
 
95
        switch (ADFS_I(inode)->filetype) {
113
96
        case 0xfc0:     /* LinkFS */
114
97
                return S_IFLNK|S_IRWXUGO;
115
98
 
175
158
 
176
159
/*
177
160
 * Convert an ADFS time to Unix time.  ADFS has a 40-bit centi-second time
178
 
 * referenced to 1 Jan 1900 (til 2248)
 
161
 * referenced to 1 Jan 1900 (til 2248) so we need to discard 2208988800 seconds
 
162
 * of time to convert from RISC OS epoch to Unix epoch.
179
163
 */
180
164
static void
181
165
adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
182
166
{
183
167
        unsigned int high, low;
 
168
        /* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since
 
169
         * 01 Jan 1900 00:00:00 (RISC OS epoch)
 
170
         */
 
171
        static const s64 nsec_unix_epoch_diff_risc_os_epoch =
 
172
                                                        2208988800000000000LL;
 
173
        s64 nsec;
184
174
 
185
175
        if (ADFS_I(inode)->stamped == 0)
186
176
                goto cur_time;
187
177
 
188
 
        high = ADFS_I(inode)->loadaddr << 24;
189
 
        low  = ADFS_I(inode)->execaddr;
 
178
        high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */
 
179
        low  = ADFS_I(inode)->execaddr;    /* bottom 32 bits of timestamp */
190
180
 
191
 
        high |= low >> 8;
192
 
        low  &= 255;
 
181
        /* convert 40-bit centi-seconds to 32-bit seconds
 
182
         * going via nanoseconds to retain precision
 
183
         */
 
184
        nsec = (((s64) high << 32) | (s64) low) * 10000000; /* cs to ns */
193
185
 
194
186
        /* Files dated pre  01 Jan 1970 00:00:00. */
195
 
        if (high < 0x336e996a)
 
187
        if (nsec < nsec_unix_epoch_diff_risc_os_epoch)
196
188
                goto too_early;
197
189
 
198
 
        /* Files dated post 18 Jan 2038 03:14:05. */
199
 
        if (high >= 0x656e9969)
200
 
                goto too_late;
201
 
 
202
 
        /* discard 2208988800 (0x336e996a00) seconds of time */
203
 
        high -= 0x336e996a;
204
 
 
205
 
        /* convert 40-bit centi-seconds to 32-bit seconds */
206
 
        tv->tv_sec = (((high % 100) << 8) + low) / 100 + (high / 100 << 8);
207
 
        tv->tv_nsec = 0;
 
190
        /* convert from RISC OS to Unix epoch */
 
191
        nsec -= nsec_unix_epoch_diff_risc_os_epoch;
 
192
 
 
193
        *tv = ns_to_timespec(nsec);
208
194
        return;
209
195
 
210
196
 cur_time:
211
 
        *tv = CURRENT_TIME_SEC;
 
197
        *tv = CURRENT_TIME;
212
198
        return;
213
199
 
214
200
 too_early:
215
201
        tv->tv_sec = tv->tv_nsec = 0;
216
202
        return;
217
 
 
218
 
 too_late:
219
 
        tv->tv_sec = 0x7ffffffd;
220
 
        tv->tv_nsec = 0;
221
 
        return;
222
203
}
223
204
 
224
205
/*
280
261
        ADFS_I(inode)->loadaddr  = obj->loadaddr;
281
262
        ADFS_I(inode)->execaddr  = obj->execaddr;
282
263
        ADFS_I(inode)->attr      = obj->attr;
283
 
        ADFS_I(inode)->stamped    = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
 
264
        ADFS_I(inode)->filetype  = obj->filetype;
 
265
        ADFS_I(inode)->stamped   = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
284
266
 
285
267
        inode->i_mode    = adfs_atts2mode(sb, inode);
286
268
        adfs_adfs2unix_time(&inode->i_mtime, inode);
316
298
        unsigned int ia_valid = attr->ia_valid;
317
299
        int error;
318
300
        
319
 
        lock_kernel();
320
 
 
321
301
        error = inode_change_ok(inode, attr);
322
302
 
323
303
        /*
359
339
        if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
360
340
                mark_inode_dirty(inode);
361
341
out:
362
 
        unlock_kernel();
363
342
        return error;
364
343
}
365
344
 
374
353
        struct object_info obj;
375
354
        int ret;
376
355
 
377
 
        lock_kernel();
378
356
        obj.file_id     = inode->i_ino;
379
357
        obj.name_len    = 0;
380
358
        obj.parent_id   = ADFS_I(inode)->parent_id;
384
362
        obj.size        = inode->i_size;
385
363
 
386
364
        ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
387
 
        unlock_kernel();
388
365
        return ret;
389
366
}