diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/config.h.in ntfs-3g.syn/config.h.in --- ntfs-3g_ntfsprogs-2012.1.15/config.h.in 2012-01-15 14:26:22.000000000 +0100 +++ ntfs-3g.syn/config.h.in 2015-11-10 03:37:39.000000000 +0100 @@ -368,3 +368,8 @@ /* Define to `unsigned int' if does not define. */ #undef size_t + +#if defined(SYNO) +/* include synology specified config macro */ +#include "syno_config.h" +#endif diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/endians.h ntfs-3g.syn/include/ntfs-3g/endians.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/endians.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/endians.h 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /* * endians.h - Definitions related to handling of byte ordering. * Originated from the Linux-NTFS project. @@ -100,7 +103,7 @@ (((u64)(x) & 0x000000000000ff00ull) << 40) | \ (((u64)(x) & 0x00000000000000ffull) << 56)) -#ifdef HAVE_BYTESWAP_H +#if HAVE_BYTESWAP_H && !defined(MY_ABC_HERE) # include #else # define bswap_16(x) __ntfs_bswap_constant_16(x) diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/inode.h ntfs-3g.syn/include/ntfs-3g/inode.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/inode.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/inode.h 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /* * inode.h - Defines for NTFS inode handling. Originated from the Linux-NTFS project. * @@ -28,6 +31,10 @@ /* Forward declaration */ typedef struct _ntfs_inode ntfs_inode; +#ifdef MY_ABC_HERE +typedef struct _syno_cache syno_cache_t; +#endif + #include "types.h" #include "layout.h" #include "support.h" @@ -222,4 +227,25 @@ #define debug_double_inode(num, type) #define debug_cached_inode(ni) +#ifdef MY_ABC_HERE +/* syno inode cache functions and types + Note: + Both _enter and _fetch increase refence count, + but only _release decrease it. + So _enter and _fetch must be used mutual exclusively */ + +syno_cache_t *syno_create_inode_cache(void); +void syno_destroy_inode_cache(syno_cache_t *cache); + +ntfs_inode *syno_inodecache_enter(syno_cache_t *cache, MFT_REF mref, ntfs_inode *inode); +ntfs_inode *syno_inodecache_fetch(syno_cache_t *cache, MFT_REF mref); +ntfs_inode *syno_inodecache_release(syno_cache_t *cache, MFT_REF mref); +ntfs_inode *syno_inodecache_flush(syno_cache_t *cache, MFT_REF mref); +int syno_inodecache_invalidate(syno_cache_t *cache, MFT_REF mref); + +int syno_inodecache_check_ref(syno_cache_t *cache); +int syno_inodecache_flush_all(syno_cache_t *cache); +int syno_inodecache_invalidate_all(syno_cache_t *cache); +#endif + #endif /* defined _NTFS_INODE_H */ diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/logging.h ntfs-3g.syn/include/ntfs-3g/logging.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/logging.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/logging.h 2015-12-01 18:04:08.000000000 +0100 @@ -117,5 +117,14 @@ void ntfs_log_early_error(const char *format, ...) __attribute__((format(printf, 1, 2))); -#endif /* _LOGGING_H_ */ +#ifdef SYNO_DEBUG +#define SYNO_WARN ntfs_log_error +#define SYNO_DBG ntfs_log_error +#define SYNO_ERR ntfs_log_error +#else +#define SYNO_WARN ntfs_log_warning +#define SYNO_DBG ntfs_log_debug +#define SYNO_ERR ntfs_log_error +#endif +#endif /* _LOGGING_H_ */ diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/param.h ntfs-3g.syn/include/ntfs-3g/param.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/param.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/param.h 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /* * param.h - Parameter values for ntfs-3g * @@ -23,7 +26,11 @@ #define _NTFS_PARAM_H #define CACHE_INODE_SIZE 32 /* inode cache, zero or >= 3 and not too big */ +#ifdef MY_ABC_HERE +#define CACHE_NIDATA_SIZE 0 /* idata cache, zero or >= 3 and not too big */ +#else #define CACHE_NIDATA_SIZE 64 /* idata cache, zero or >= 3 and not too big */ +#endif #define CACHE_LOOKUP_SIZE 64 /* lookup cache, zero or >= 3 and not too big */ #define CACHE_SECURID_SIZE 16 /* securid cache, zero or >= 3 and not too big */ #define CACHE_LEGACY_SIZE 8 /* legacy cache size, zero or >= 3 and not too big */ diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/types.h ntfs-3g.syn/include/ntfs-3g/types.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/types.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/types.h 2015-12-01 18:04:08.000000000 +0100 @@ -81,6 +81,8 @@ * As long as this file will be included after were fine. */ #ifndef _WINDEF_H +#ifndef _HAVE_BOOL +#define _HAVE_BOOL /** * enum BOOL - These are just to make the code more readable... */ @@ -104,6 +106,7 @@ ONE = 1, #endif } BOOL; +#endif /* _HAVE_BOOL */ #endif /* defined _WINDEF_H */ /** diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/volume.h ntfs-3g.syn/include/ntfs-3g/volume.h --- ntfs-3g_ntfsprogs-2012.1.15/include/ntfs-3g/volume.h 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/include/ntfs-3g/volume.h 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /* * volume.h - Exports for NTFS volume handling. Originated from the Linux-NTFS project. * @@ -261,6 +264,9 @@ #ifdef XATTR_MAPPINGS struct XATTRMAPPING *xattr_mapping; #endif /* XATTR_MAPPINGS */ +#ifdef MY_ABC_HERE + syno_cache_t *syno_inode_cache; +#endif #if CACHE_INODE_SIZE struct CACHE_HEADER *xinode_cache; #endif diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libfuse-lite/fuse_kern_chan.c ntfs-3g.syn/libfuse-lite/fuse_kern_chan.c --- ntfs-3g_ntfsprogs-2012.1.15/libfuse-lite/fuse_kern_chan.c 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/libfuse-lite/fuse_kern_chan.c 2015-12-01 18:04:08.000000000 +0100 @@ -81,7 +81,7 @@ close(fuse_chan_fd(ch)); } -#define MIN_BUFSIZE 0x21000 +#define MIN_BUFSIZE 0x101000 struct fuse_chan *fuse_kern_chan_new(int fd) { diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libfuse-lite/fuse_loop.c ntfs-3g.syn/libfuse-lite/fuse_loop.c --- ntfs-3g_ntfsprogs-2012.1.15/libfuse-lite/fuse_loop.c 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/libfuse-lite/fuse_loop.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /* FUSE: Filesystem in Userspace Copyright (C) 2001-2007 Miklos Szeredi @@ -13,6 +16,16 @@ #include #include +#ifdef MY_ABC_HERE +int in_fuse_op = 0; +void (*syno_extent_op)(void) = NULL; + +void syno_fuse_register_extent_op(void (*func)(void)) +{ + syno_extent_op = func; +} +#endif + int fuse_session_loop(struct fuse_session *se) { int res = 0; @@ -31,7 +44,16 @@ continue; if (res <= 0) break; +#ifdef MY_ABC_HERE + in_fuse_op = 1; + fuse_session_process(se, buf, res, tmpch); + in_fuse_op = 0; + if (syno_extent_op) { + syno_extent_op(); + } +#else fuse_session_process(se, buf, res, tmpch); +#endif } free(buf); diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/acls.c ntfs-3g.syn/libntfs-3g/acls.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/acls.c 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/acls.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * acls.c - General function to process NTFS ACLs * @@ -108,6 +111,30 @@ #include "secaudit.h" #endif /* HAVE_CONFIG_H */ +#ifdef MY_ABC_HERE +#include +#include +#include +static SID *encodesid(const char *sidstr); +static void SYNOSzSIDConvertFromSID(const SID *sid, char *szSID, int cbSID) +{ + char szBuf[128]; + char *ptr = szBuf; + int len, rest = sizeof(szBuf); + int i, count = sid->sub_authority_count; + + len = snprintf(szBuf, sizeof(szBuf), "S-%u-%u", + sid->revision, sid->identifier_authority.low_part); + for (i = 0; i < count; i++) { + rest -= len; + ptr += len; + len = snprintf(ptr, rest, "-%u", + const_le32_to_cpu(sid->sub_authority[i])); + } + snprintf(szSID, cbSID, "%s", szBuf); +} +#endif + /* * A few useful constants */ @@ -410,6 +436,15 @@ const SID *ntfs_find_usid(const struct MAPPING* usermapping, uid_t uid, SID *defusid) { +#ifdef MY_ABC_HERE + const SID *sid = NULL; + char szSID[128]; + + if (0 == SYNOUserSidGetByUid(uid, szSID, sizeof(szSID))) { + defusid = encodesid(szSID); + sid = defusid; + } +#else const struct MAPPING *p; const SID *sid; le32 leauth; @@ -443,6 +478,7 @@ } else sid = (p ? p->sid : (const SID*)NULL); } +#endif return (sid); } @@ -454,6 +490,15 @@ const SID *ntfs_find_gsid(const struct MAPPING* groupmapping, gid_t gid, SID *defgsid) { +#ifdef MY_ABC_HERE + const SID *sid = NULL; + char szSID[128]; + + if (0 == SYNOGroupSidGetByGid(gid, szSID, sizeof(szSID))) { + defgsid = encodesid(szSID); + sid = defgsid; + } +#else const struct MAPPING *p; const SID *sid; le32 leauth; @@ -487,6 +532,7 @@ } else sid = (p ? p->sid : (const SID*)NULL); } +#endif return (sid); } @@ -498,6 +544,16 @@ uid_t ntfs_find_user(const struct MAPPING* usermapping, const SID *usid) { uid_t uid; +#ifdef MY_ABC_HERE + char szSID[128]; + + SYNOSzSIDConvertFromSID(usid, szSID, sizeof(szSID)); + if (ntfs_is_user_sid(usid)) { + if (-1 == SYNOUserUidGetBySid(szSID, &uid)) { + uid = 0; + } + } +#else const struct MAPPING *p; p = usermapping; @@ -510,6 +566,7 @@ uid = findimplicit(usid,p->sid,0); else uid = (p ? p->xid : 0); +#endif return (uid); } @@ -521,6 +578,16 @@ gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid) { gid_t gid; +#ifdef MY_ABC_HERE + char szSID[128]; + + SYNOSzSIDConvertFromSID(gsid, szSID, sizeof(szSID)); + if (ntfs_is_user_sid(gsid)) { + if (-1 == SYNOGroupGidGetBySid(szSID, &gid)) { + gid = 0; + } + } +#else const struct MAPPING *p; p = groupmapping; @@ -533,6 +600,7 @@ gid = findimplicit(gsid,p->sid,1); else gid = (p ? p->xid : 0); +#endif return (gid); } diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/attrib.c ntfs-3g.syn/libntfs-3g/attrib.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/attrib.c 2012-01-15 14:26:13.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/attrib.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * attrib.c - Attribute handling code. Originated from the Linux-NTFS project. * @@ -5567,10 +5568,26 @@ * have to check whether there is a hole * in the updated region. */ +#ifdef MY_ABC_HERE + sparse = 0; + for (xrl = na->rl; xrl->length; xrl++) { + if (xrl->lcn < 0) { + if (xrl->lcn == LCN_HOLE) { + sparse = 1; + break; + } + if (xrl->lcn != LCN_RL_NOT_MAPPED) { + sparse = -1; + break; + } + } + } +#else xrl = na->rl; if (xrl->lcn == LCN_RL_NOT_MAPPED) xrl++; sparse = ntfs_rl_sparse(xrl); +#endif if (sparse < 0) { ntfs_log_error("Could not check whether sparse\n"); errno = EIO; diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c ntfs-3g.syn/libntfs-3g/dir.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/dir.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * dir.c - Directory handling code. Originated from the Linux-NTFS project. * @@ -1791,6 +1793,12 @@ errno = EINVAL; goto err_out; } +#ifdef MY_ABC_HERE + if (ni && ni->vol) { + /* remove out from cache */ + syno_inodecache_invalidate(ni->vol->syno_inode_cache, ni->mft_no); + } +#endif if (ni->nr_extents == -1) ni = ni->base_ni; if (dir_ni->nr_extents == -1) diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/inode.c ntfs-3g.syn/libntfs-3g/inode.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/inode.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/inode.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * inode.c - Inode handling code. Originated from the Linux-NTFS project. * @@ -57,7 +60,409 @@ #include "ntfstime.h" #include "logging.h" #include "misc.h" +#ifdef MY_ABC_HERE + +#define CACHE_INODE_SIZE 32 +int ntfs_inode_real_close_i(ntfs_inode *ni, int free_inode); + +typedef struct _SYNO_CACHE_ENTRY { + struct _SYNO_CACHE_ENTRY *next; + MFT_REF mref; + ntfs_inode *inode; + int ref_count; +} SYNO_CACHE_ENTRY; + +struct _syno_cache { + const char *name; + int lock_seq; /* lock sequence in cache list */ + SYNO_CACHE_ENTRY *most_recent_entry; + SYNO_CACHE_ENTRY *free_entry; + SYNO_CACHE_ENTRY entry[0]; +}; + +static void syno_dump_cache(syno_cache_t *cache) +{ + int i; + ntfs_log_error("Dumping inode cache\n"); + ntfs_log_error("name:%s (%s)\n", cache->name, cache->lock_seq? "locked" : "not locked"); + ntfs_log_error("most_recent_entry: %p\n", cache->most_recent_entry); + ntfs_log_error("free_entry:%p\n", cache->free_entry); + + ntfs_log_error("entry:\n"); + for (i=0; ientry[i]); + ntfs_log_error(" [%d] %p: next %p, mref %lld, inode %p, ref_count %d\n", + i, entry, entry->next, entry->mref, entry->inode, entry->ref_count); + } +} + +ntfs_inode *syno_inodecache_enter(syno_cache_t *cache, MFT_REF mref, ntfs_inode *inode) +{ + SYNO_CACHE_ENTRY *current; + SYNO_CACHE_ENTRY *previous; + SYNO_CACHE_ENTRY *before; + + if (!cache || !inode) { + return NULL; + } + + /* check if already in cache */ + current = cache->most_recent_entry; + previous = NULL; + before = NULL; + while (current) + { + if (current->mref == mref) + break; + + before = previous; + previous = current; + + current = current->next; + } + + if (!current && !cache->lock_seq) { + /* not in cache, add new entry + use free entry if available, + else kick out lru entry */ + SYNO_CACHE_ENTRY *new_entry; + + if (cache->free_entry) { + new_entry = cache->free_entry; + cache->free_entry = cache->free_entry->next; + } else { + /* kick out lru entry */ + SYNO_CACHE_ENTRY *victim = previous; + SYNO_CACHE_ENTRY *victim_parent = before; + + /* BUG! cache may have less than 3 entry !!*/ + + /* remove from cache list first + for closing inode my change cache list */ + victim_parent->next = victim->next; + + /* sync inode if no more referenced */ + if (victim->inode && + 0 == victim->ref_count) + { + cache->lock_seq = 1; + ntfs_inode_real_close_i(victim->inode, 1); + cache->lock_seq = 0; + } + + new_entry = victim; + } + + /* assign value to new entry */ + new_entry->mref = mref; + new_entry->inode = inode; + new_entry->ref_count = 0; + + /* re-link entry to head of list */ + new_entry->next = cache->most_recent_entry; + cache->most_recent_entry = new_entry; + + current = new_entry; + } + + /* increase ref count as fetch inode */ + if (current) { + current->ref_count++; + return current->inode; + } + return NULL; +} + +ntfs_inode *syno_inodecache_fetch(syno_cache_t *cache, MFT_REF mref) +{ + SYNO_CACHE_ENTRY *current; + SYNO_CACHE_ENTRY *previous; + + if (!cache) + return NULL; + + /* iterate through cache list */ + current = cache->most_recent_entry; + previous = NULL; + while (current) + { + if (current->mref == mref) + break; + + previous = current; + current = current->next; + } + + /* relink if not in head of list */ + if (current && previous && !cache->lock_seq) { + previous->next = current->next; + current->next = cache->most_recent_entry; + cache->most_recent_entry = current; + } + + /* increase reference count */ + if (current) { + current->ref_count++; + return current->inode; + } + return NULL; +} + +ntfs_inode *syno_inodecache_release(syno_cache_t *cache, MFT_REF mref) +{ + SYNO_CACHE_ENTRY *entry; + + if (!cache) + return NULL; + + /* iterate through cache list */ + entry = cache->most_recent_entry; + while (entry) + { + if (entry->mref == mref) + break; + + entry = entry->next; + } + + /* decrease reference count */ + if (entry) { + entry->ref_count--; + return entry->inode; + } + return NULL; +} + +ntfs_inode *syno_inodecache_flush(syno_cache_t *cache, MFT_REF mref) +{ + SYNO_CACHE_ENTRY *entry; + + if (!cache) + return NULL; + + /* iterate through cache list */ + entry = cache->most_recent_entry; + while (entry) + { + if (entry->mref == mref) + break; + + entry = entry->next; + } + + if (entry) { + /* sync entry if not referenced */ + if (0 == entry->ref_count) { + cache->lock_seq = 1; + ntfs_inode_real_close_i(entry->inode, 0); + cache->lock_seq = 0; + } else { + SYNO_WARN("inode %lld is still referenced, skip flush\n", entry->mref); + } + + return entry->inode; + } + + return NULL; +} + +int syno_inodecache_flush_all(syno_cache_t *cache) +{ + SYNO_CACHE_ENTRY *entry; + + if (!cache) + return 0; + + /* iterate through cache list */ + entry = cache->most_recent_entry; + while (entry) + { + /* sync inode if not refereneced */ + if (0 == entry->ref_count) { + cache->lock_seq = 1; + ntfs_inode_real_close_i(entry->inode, 0); + cache->lock_seq = 0; + } else { + if (entry->mref >= FILE_first_user) + SYNO_ERR("inode %lld is still referenced, skip flush\n", entry->mref); + else + SYNO_DBG("inode %lld is still referenced, skip flush\n", entry->mref); + } + + entry = entry->next; + } + + return 0; +} + +/* CAUTION: this function must be called when non-system inode closed, + * or else it will break original inode life cycle. + */ +int syno_inodecache_check_ref(syno_cache_t *cache) +{ + SYNO_CACHE_ENTRY *entry; + + if (!cache) + return 0; + + int count = 0; + /* iterate through cache list */ + entry = cache->most_recent_entry; + while (entry) + { + SYNO_CACHE_ENTRY *this = entry; + entry = entry->next; + + /*if non-system inode is still referenced, sync and invalidate */ + if ( 0 != this->ref_count && + this->mref >= FILE_first_user) + { + ntfs_inode *inode = this->inode; + + SYNO_ERR("ERROR: refenece count of inode %lld is non-zero, invalidate and sync it\n", + this->mref); + syno_dump_cache(cache); + + /* invalidate will not free referenced inode, free it manually */ + syno_inodecache_invalidate(cache, this->mref); + ntfs_inode_real_close_i(inode, 1); + } + else + count++; + } + +#if 0 + int free_cnt = 0; + entry = cache->free_entry; + while (entry) + { + entry = entry->next; + free_cnt++; + } + SYNO_ERR("active: %d, free:%d\n", count, free_cnt); +#endif + + return 0; +} + +int syno_inodecache_invalidate(syno_cache_t *cache, MFT_REF mref) +{ + SYNO_CACHE_ENTRY *current; + SYNO_CACHE_ENTRY *previous; + + if (!cache) { + return 0; + } + + /* iterate through cache list */ + current = cache->most_recent_entry; + previous = NULL; + while (current) + { + if (current->mref == mref) + break; + previous = current; + current = current->next; + } + + if (current) { + /* remove from list */ + if (previous) { + previous->next = current->next; + } else { + cache->most_recent_entry = current->next; + } + + /* sync inode if no more referenced */ + if ( current->inode && + 0 == current->ref_count ) + { + cache->lock_seq = 1; + ntfs_inode_real_close_i(current->inode, 1); + cache->lock_seq = 0; + } + + /* add to free list */ + current->next = cache->free_entry; + cache->free_entry = current; + } + + return 0; +} + +int syno_inodecache_invalidate_all(syno_cache_t *cache) +{ + if (!cache) + return 0; + + while (cache->most_recent_entry) + { + SYNO_CACHE_ENTRY *current = cache->most_recent_entry; + SYNO_CACHE_ENTRY *next = current->next; + + /* remove from list */ + cache->most_recent_entry = next; + + /* sync inode if not refereneced */ + if (0 == current->ref_count) { + cache->lock_seq = 1; + ntfs_inode_real_close_i(current->inode, 1); + cache->lock_seq = 0; + } + + /* add to free list */ + current->next = cache->free_entry; + cache->free_entry = current; + } + + return 0; +} + +syno_cache_t *syno_create_inode_cache(void) +{ + syno_cache_t *cache; + SYNO_CACHE_ENTRY *p; + SYNO_CACHE_ENTRY *q; + int i; + + cache = (syno_cache_t *)malloc(sizeof(syno_cache_t) + + CACHE_INODE_SIZE * sizeof(SYNO_CACHE_ENTRY)); + if (cache) { + cache->name = "syno_inodecache"; + cache->lock_seq = 0; + + /* chain the entries, and mark an invalid entry */ + cache->most_recent_entry = NULL; + cache->free_entry = &cache->entry[0]; + + for (i=0; i<(CACHE_INODE_SIZE - 1); i++) { + p = &cache->entry[i]; + q = &cache->entry[i+1]; + p->next = q; + p->mref = 0; + p->inode = NULL; + p->ref_count = 0; + } + + /* special for the last entry */ + p = &cache->entry[CACHE_INODE_SIZE-1]; + p->next = NULL; + p->mref = 0; + p->inode = NULL; + p->ref_count = 0; + } + return (cache); +} + +void syno_destroy_inode_cache(syno_cache_t *cache) +{ + if (cache) { + syno_inodecache_invalidate_all(cache); + free(cache); + } +} +#endif /* MY_ABC_HERE */ ntfs_inode *ntfs_inode_base(ntfs_inode *ni) { if (ni->nr_extents == -1) @@ -170,6 +575,20 @@ errno = EINVAL; goto out; } +#ifdef MY_ABC_HERE + /* check if inode in cache */ + ntfs_inode *cached; + cached = syno_inodecache_fetch(vol->syno_inode_cache, MREF(mref)); + if (cached) { + SYNO_DBG("Found cached inode %lld\n", cached->mft_no); + ni = cached; + goto out; + } + else + { + SYNO_DBG("Can't find inode %lld in cache\n", MREF(mref)); + } +#endif ni = __ntfs_inode_allocate(vol); if (!ni) goto out; @@ -273,6 +692,18 @@ set_nino_flag(ni,KnownSize); } ntfs_attr_put_search_ctx(ctx); +#ifdef MY_ABC_HERE + if (ni) { + /* cache inode structure */ + ntfs_inode *cached; + cached = syno_inodecache_enter(ni->vol->syno_inode_cache, ni->mft_no, ni); + if (!cached) { + SYNO_DBG("Cache inode %lld in _inode_open failed\n", ni->mft_no); + } else { + SYNO_DBG("Cache inode %lld in _inode_open\n", ni->mft_no); + } + } +#endif out: ntfs_log_leave("\n"); return ni; @@ -309,8 +740,28 @@ * EINVAL @ni is invalid (probably it is an extent inode). * EIO I/O error while trying to write inode to disk. */ +#ifdef MY_ABC_HERE +int ntfs_inode_real_close(ntfs_inode *ni) +{ + if (!ni) + return 0; + ntfs_inode *cached; + cached = syno_inodecache_release(ni->vol->syno_inode_cache, ni->mft_no); + if (cached) { + /* skip inode close if cached */ + SYNO_DBG("inode %lld in cache, skip close\n", ni->mft_no); + return 0; + } else { + /* run normal inode close if not cached */ + SYNO_DBG("inode %lld not in cache, normal close\n", ni->mft_no); + return ntfs_inode_real_close_i(ni, 1); + } +} +int ntfs_inode_real_close_i(ntfs_inode *ni, int free_inode) +#else int ntfs_inode_real_close(ntfs_inode *ni) +#endif { int ret = -1; @@ -387,6 +838,16 @@ ntfs_log_error("Extent inode %lld was not found\n", (long long)ni->mft_no); } +#ifdef MY_ABC_HERE + /* free cached inode if requested */ + if (!free_inode) { + SYNO_DBG("Sync but skip free inode %lld\n", (long long)ni->mft_no); + ret = 0; + goto err; + } + + SYNO_DBG("Sync and free inode %lld\n", (long long)ni->mft_no); +#endif __ntfs_inode_release(ni); ret = 0; diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logging.c ntfs-3g.syn/libntfs-3g/logging.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logging.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/logging.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * logging.c - Centralised logging. Originated from the Linux-NTFS project. * @@ -355,6 +352,20 @@ #ifdef HAVE_SYSLOG_H #define LOG_LINE_LEN 512 +#ifdef MY_ABC_HERE +static inline int SYNO_LVL(int level) +{ + switch(level) { + case NTFS_LOG_LEVEL_CRITICAL: + return LOG_CRIT; + case NTFS_LOG_LEVEL_ERROR: + return LOG_ERR; + case NTFS_LOG_LEVEL_WARNING: + default: + return LOG_NOTICE; + } +} +#endif int ntfs_log_handler_syslog(const char *function __attribute__((unused)), const char *file __attribute__((unused)), @@ -371,7 +382,11 @@ #endif ret = vsnprintf(logbuf, LOG_LINE_LEN, format, args); if (ret < 0) { +#ifdef MY_ABC_HERE + vsyslog(SYNO_LVL(level), format, args); +#else vsyslog(LOG_NOTICE, format, args); +#endif ret = 1; goto out; } @@ -382,7 +397,11 @@ ret = strlen(logbuf); } +#ifdef MY_ABC_HERE + syslog(SYNO_LVL(level), "%s", logbuf); +#else syslog(LOG_NOTICE, "%s", logbuf); +#endif out: errno = olderr; return ret; diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/security.c ntfs-3g.syn/libntfs-3g/security.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/security.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/security.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * security.c - Handling security/ACLs in NTFS. Originated from the Linux-NTFS project. * @@ -2501,8 +2501,13 @@ usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); if (!usid || !gsid) { +#ifdef MY_ABC_HERE + ntfs_log_warning("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); +#else ntfs_log_error("File created by an unmapped user/group %d/%d\n", (int)uid, (int)gid); +#endif usid = gsid = adminsid; } newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, @@ -2558,8 +2563,13 @@ usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); if (!usid || !gsid) { +#ifdef MY_ABC_HERE + ntfs_log_warning("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); +#else ntfs_log_error("File created by an unmapped user/group %d/%d\n", (int)uid, (int)gid); +#endif usid = gsid = adminsid; } newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, @@ -2640,8 +2650,13 @@ usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); if (!usid || !gsid) { +#ifdef MY_ABC_HERE + ntfs_log_warning("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); +#else ntfs_log_error("File created by an unmapped user/group %d/%d\n", (int)uid, (int)gid); +#endif usid = gsid = adminsid; } newattr = ntfs_build_descr(mode, isdir, usid, gsid); @@ -2737,8 +2752,13 @@ usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); if (!usid || !gsid) { +#ifdef MY_ABC_HERE + ntfs_log_warning("File made owned by an unmapped user/group %d/%d\n", + uid, gid); +#else ntfs_log_error("File made owned by an unmapped user/group %d/%d\n", uid, gid); +#endif usid = gsid = adminsid; } #if POSIXACLS diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/unix_io.c ntfs-3g.syn/libntfs-3g/unix_io.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/unix_io.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/unix_io.c 2015-12-01 18:04:08.000000000 +0100 @@ -263,6 +263,15 @@ return write(DEV_FD(dev), buf, count); } +#ifdef SYNO_NTFS_IO_COUNT +long long int total_read = 0; +long long int total_write = 0; +void print_io_counter(void) +{ + ntfs_log_error("io counter: read %lld, write %lld\n", total_read, total_write); +} +#endif + /** * ntfs_device_unix_io_pread - Perform a positioned read from the device * @dev: @@ -277,7 +286,16 @@ static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset) { +#ifdef SYNO_NTFS_IO_COUNT + ssize_t ret; + ret = pread(DEV_FD(dev), buf, count, offset); + if (ret >= 0) { + total_read += ret; + } + return ret; +#else return pread(DEV_FD(dev), buf, count, offset); +#endif } /** @@ -299,7 +317,16 @@ return -1; } NDevSetDirty(dev); +#ifdef SYNO_NTFS_IO_COUNT + ssize_t ret; + ret = pwrite(DEV_FD(dev), buf, count, offset); + if (ret >= 0) { + total_write += ret; + } + return ret; +#else return pwrite(DEV_FD(dev), buf, count, offset); +#endif } /** diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c ntfs-3g.syn/libntfs-3g/volume.c --- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/libntfs-3g/volume.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * volume.c - NTFS volume handling code. Originated from the Linux-NTFS project. * @@ -167,6 +170,11 @@ { int err = 0; +#ifdef MY_ABC_HERE + /* should sync cache before system inode close */ + syno_destroy_inode_cache(v->syno_inode_cache); + v->syno_inode_cache = NULL; +#endif if (ntfs_inode_free(&v->vol_ni)) ntfs_error_set(&err); /* @@ -494,6 +502,11 @@ if (!vol->upcase_len || !vol->upcase) goto error_exit; +#ifdef MY_ABC_HERE + vol->syno_inode_cache = syno_create_inode_cache(); +#endif + ntfs_upcase_table_build(vol->upcase, + vol->upcase_len * sizeof(ntfschar)); /* Default with no locase table and case sensitive file names */ vol->locase = (ntfschar*)NULL; NVolSetCaseSensitive(vol); diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/porting_note ntfs-3g.syn/porting_note --- ntfs-3g_ntfsprogs-2012.1.15/porting_note 1970-01-01 01:00:00.000000000 +0100 +++ ntfs-3g.syn/porting_note 2015-11-10 03:32:54.000000000 +0100 @@ -0,0 +1,12 @@ + +0. git://ntfs-3g.git.sourceforge.net/gitroot/ntfs-3g/ntfs-3g + +1. Porting is based on ntfs-3g tag N2010_8_8. + +2. Megre Synology's modifications. + +3. Upgrade to v2011_10_9_RC. + +4. Patch some files from ntfs-3g_ntfsprogs-2011.10.9-RC.tgz to skip autogen procedure. + +* Have to upgrade to stable version once it's released. \ No newline at end of file diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c ntfs-3g.syn/src/ntfs-3g.c --- ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c 2012-01-15 14:26:14.000000000 +0100 +++ ntfs-3g.syn/src/ntfs-3g.c 2015-12-01 18:04:08.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif /** * ntfs-3g - Third Generation NTFS Driver * @@ -1318,11 +1319,14 @@ ntfschar *stream_name; int stream_name_len, res; +/* need to open file for syncing cache if enable inode cache */ +#ifndef MY_ABC_HERE /* Only for marked descriptors there is something to do */ if (!(fi->fh & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED | CLOSE_DMTIME))) { res = 0; goto out; } +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) { res = stream_name_len; @@ -1352,6 +1356,12 @@ ntfs_attr_close(na); if (ntfs_inode_close(ni)) set_fuse_error(&res); +#ifdef MY_ABC_HERE + if (ni && ni->vol) { + /* if inode is cached, flush and free it, then invalid cache */ + syno_inodecache_invalidate(ni->vol->syno_inode_cache, ni->mft_no); + } +#endif free(path); if (stream_name_len) free(stream_name); @@ -3610,6 +3620,33 @@ ntfs_log_info("Mount options: %s\n", parsed_options); } +#ifdef MY_ABC_HERE +/* runs after each fuse operation + doing cache check and setup alarm */ +void syno_post_process(void) +{ + if (ctx && ctx->vol && ctx->vol->syno_inode_cache) { + /* check cache integrity */ + syno_inodecache_check_ref(ctx->vol->syno_inode_cache); + + /* wake up flusher in 3 seconds */ + alarm(3); + } +} + +extern int in_fuse_op; +static void syno_alarm_handler(int sig) +{ + if (ctx && ctx->vol && ctx->vol->syno_inode_cache) { + if (!in_fuse_op) { + SYNO_DBG("---> syno alarm handler\n"); + syno_inodecache_flush_all(ctx->vol->syno_inode_cache); + SYNO_DBG("<--- syno alarm handler\n"); + } + } +} +#endif + int main(int argc, char *argv[]) { char *parsed_options = NULL; @@ -3626,6 +3663,20 @@ unsigned long existing_mount; int err, fd; +#ifdef MY_ABC_HERE + struct sigaction new_sigact, old_sigact; + new_sigact.sa_handler = syno_alarm_handler; + sigemptyset(&new_sigact.sa_mask); + new_sigact.sa_flags = 0; + + sigaction(SIGALRM, &new_sigact, &old_sigact); + if (sigaction(SIGALRM, &new_sigact, &old_sigact)) { + SYNO_ERR("register alarm handler fail\n"); + } + + extern void syno_fuse_register_extent_op(void (*func)(void)); + syno_fuse_register_extent_op(syno_post_process); +#endif /* * Make sure file descriptors 0, 1 and 2 are open, * otherwise chaos would ensue. @@ -3843,8 +3894,18 @@ err = 0; +#ifdef MY_ABC_HERE + /* clear pending alarm and flush cached inode */ + alarm(0); + syno_alarm_handler(SIGALRM); +#endif + fuse_unmount(opts.mnt_point, ctx->fc); fuse_destroy(fh); +#ifdef SYNO_NTFS_IO_COUNT + extern void print_io_counter(void); + print_io_counter(); +#endif err_out: ntfs_mount_error(opts.device, opts.mnt_point, err); if (ctx->abs_mnt_point) diff -uNr -w -b -B ntfs-3g_ntfsprogs-2012.1.15/syno_config.h ntfs-3g.syn/syno_config.h --- ntfs-3g_ntfsprogs-2012.1.15/syno_config.h 1970-01-01 01:00:00.000000000 +0100 +++ ntfs-3g.syn/syno_config.h 2015-12-01 18:04:08.000000000 +0100 @@ -0,0 +1,18 @@ +#ifndef MY_ABC_HERE +#define MY_ABC_HERE +#endif +/* This file collect the definition macro of + synology developed funtionality */ +#ifndef __SYNO_NTFS_CONFIG_H +#define __SYNO_NTFS_CONFIG_H + +/* force outpur synology message, undefine to follow original rules */ +//#define SYNO_DEBUG + +/* cache inode between each fuse operation */ + +/* redirect message to syslog in synology system */ + +/* Trans ntfs acl to syno linux acl */ + +#endif /* __SYNO_NTFS_CONFIG_H */